Merge pull request #7192 from TeamNewPipe/release/0.21.11

Release/0.21.11
This commit is contained in:
Tobi 2021-10-10 21:03:38 +02:00 committed by GitHub
commit e0ba9b3902
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
108 changed files with 1290 additions and 918 deletions

View File

@ -5,10 +5,9 @@ labels: enhancement
assignees: ''
---
<!-- IF YOU DON'T FILL IN THE TEMPLATE PROPERLY, YOUR ISSUE IS LIABLE TO BE CLOSED. If you feel tired/lazy right now, open your issue some other time. We'll wait. -->
<!-- IF YOU DON'T FILL IN THE TEMPLATE PROPERLY, YOUR ISSUE IS LIABLE TO BE CLOSED. If you are currently unable to do so for any reason, open your issue some other time. We'll wait. -->
<!-- The comments between these brackets won't show up in the submitted issue (as you can see in the Preview). -->
<!-- The comments between these brackets won't show up in the submitted issue (as you can see in the Preview tab). -->
### Checklist
<!-- This checklist is COMPULSORY. The first box has been checked for you to show you how it is done. -->
@ -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
<!-- A clear and concise description of what you wish should happen.
Example: *I think it would be nice if you add feature Y which makes X possible.*
Optionally, also describe alternatives you've considered.
Example: *Z is also a good alternative. Not as good as Y, but at least...* or *I considered Z, but that didn't turn out to be a good idea because...* -->
#### What feature do you want?
<!-- Explain how you want the app's look or behavior to change to suit your needs. -->
#### Is your feature request related to a problem? Please describe it
<!-- A clear and concise description of what the problem is. Maybe the developers and the community could brainstorm and come up with a better solution to your problem. If they exist, link to related Issues and/or PRs for developers to keep track easier.
Example: *I want to do X, but there is no way to do it.* -->
#### Additional context
<!-- Add any other context, like screenshots, about the feature request here.
Example: *Here's a photo of my cat!* -->
#### How will you/everyone benefit from this feature?
<!-- Convince us! How does it change your NewPipe experience and/or your life?
The better this paragraph is, the more likely a developer will think about working on it.
Example: *This feature will help us colonize the galaxy! -->
#### Why do you want this feature?
<!-- Describe any problem or limitation you come across while using the app which would be solved by this feature. -->

View File

@ -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'

View File

@ -1,30 +1,30 @@
<p align="center"><a href="https://newpipe.net"><img src="assets/new_pipe_icon_5.png" width="150"></a></p>
<h2 align="center"><b>NewPipe</b></h2>
<h4 align="center">Una interfaz de streaming lijera y libre para Android.</h4>
<h4 align="center">Una interfaz de streaming ligera y libre para Android.</h4>
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png"></a></p>
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-es.svg"></a></p>
<p align="center">
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/badge/Lanzamiento-v0.20.11-blue.svg" ></a>
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/Licencia-GPL%20v3-blue.svg"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
<a href="https://hosted.weblate.org/engage/newpipe/es/" alt="Estado de la traducción"><img src="https://hosted.weblate.org/widgets/newpipe/es/svg-badge.svg"></a>
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/Canal%20de%20IRC%20-%23newpipe-brightgreen.svg"></a>
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="Lanzamientos GitHub"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="Licencia: GPLv3"><img src="https://img.shields.io/badge/Licencia-GPL%20v3-blue.svg"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Estado del Build"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
<a href="https://hosted.weblate.org/engage/newpipe/es/" alt="Estado de la Traducción"><img src="https://hosted.weblate.org/widgets/newpipe/es/svg-badge.svg"></a>
<a href="https://web.libera.chat/#newpipe" alt="Canal de IRC: #newpipe"><img src="https://img.shields.io/badge/Canal%20de%20IRC%20-%23newpipe-brightgreen.svg"></a>
<a href="https://www.bountysource.com/teams/newpipe" alt="Recompensas en Bountysource"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
</p>
<hr>
<p align="center"><a href="#capturas-de-pantalla">Capturas de pantalla</a> &bull; <a href="#descripción">Descripción</a> &bull; <a href="#características">Características</a> &bull; <a href="#installación-y-actualizaciones">Installación y actualizaciones</a> &bull; <a href="#contribución">Contribución</a> &bull; <a href="#donar">Donar</a> &bull; <a href="#licencias">Licencias</a></p>
<p align="center"><a href="https://newpipe.net">Sitio web</a> &bull; <a href="https://newpipe.net/blog/">Blog</a> &bull; <a href="https://newpipe.net/FAQ/">Preguntas Frecuentes</a> &bull; <a href="https://newpipe.net/press/">Prensa</a></p>
<p align="center"><a href="#capturas-de-pantalla">Capturas de Pantalla</a> &bull; <a href="#descripción">Descripción</a> &bull; <a href="#características">Características</a> &bull; <a href="#instalación-y-actualizaciones">Instalación y Actualizaciones</a> &bull; <a href="#contribución">Contribución</a> &bull; <a href="#donar">Donar</a> &bull; <a href="#licencia">Licencia</a></p>
<p align="center"><a href="https://newpipe.net">Sitio Web</a> &bull; <a href="https://newpipe.net/blog/">Blog</a> &bull; <a href="https://newpipe.net/FAQ/">Preguntas Frecuentes</a> &bull; <a href="https://newpipe.net/press/">Prensa</a></p>
<hr>
*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).*
<b>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.</b>
<b>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.</b>
<b>COLOCAR NEWPIPE O CUALQUIER FORK (BIFURCACIÓN) REALIZADO DE ELLO EN GOOGLE PLAY STORE VIOLA SUS TÉRMINOS Y CONDICIONES.</b>
<b>COLOCAR NEWPIPE O CUALQUIER FORK DE NEWPIPE EN LA GOOGLE PLAY STORE VIOLARÁ SUS TÉRMINOS Y CONDICIONES.</b>
## Capturas de pantalla
## Capturas de Pantalla
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png)
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png)
@ -40,39 +40,43 @@
[<img src="fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png" width=405>](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\]
<!-- Brecha escondida para mantener compatibles los enlaces viejos. -->
<span id="actualizaciones"></span>
## 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).
<a href="https://hosted.weblate.org/engage/newpipe/es/">
<img src="https://hosted.weblate.org/widgets/newpipe/es/287x66-grey.png" alt="Estado de la traducción" />
<img src="https://hosted.weblate.org/widgets/newpipe/es/287x66-grey.png" alt="Estado de la Traducción" />
</a>
## 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.
<table>
<tr>
<td><img src="https://bitcoin.org/img/icons/logotop.svg" alt="Bitcoin"></td>
<td><img src="assets/bitcoin_qr_code.png" alt="Bitcoin QR code" width="100px"></td>
<td><img src="assets/bitcoin_qr_code.png" alt="Código QR del Bitcoin" width="100px"></td>
<td><samp>16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh</samp></td>
</tr>
<tr>
<td><a href="https://liberapay.com/TeamNewPipe/"><img src="https://upload.wikimedia.org/wikipedia/commons/2/27/Liberapay_logo_v2_white-on-yellow.svg" alt="Liberapay" width="80px" ></a></td>
<td><a href="https://liberapay.com/TeamNewPipe/"><img src="assets/liberapay_qr_code.png" alt="Visit NewPipe at liberapay.com" width="100px"></a></td>
<td><a href="https://liberapay.com/TeamNewPipe/donate"><img src="assets/liberapay_donate_button.svg" alt="Donate via Liberapay" height="35px"></a></td>
<td><a href="https://liberapay.com/TeamNewPipe/"><img src="assets/liberapay_qr_code.png" alt="Visita NewPipe en liberapay.com" width="100px"></a></td>
<td><a href="https://liberapay.com/TeamNewPipe/donate"><img src="assets/liberapay_donate_button.svg" alt="Donaa Liberapay" height="35px"></a></td>
</tr>
<tr>
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Bountysource.png/320px-Bountysource.png" alt="Bountysource" width="190px"></a></td>
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="assets/bountysource_qr_code.png" alt="Visit NewPipe at bountysource.com" width="100px"></a></td>
<td><a href="https://www.bountysource.com/teams/newpipe/issues"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f" height="30px" alt="Check out how many bounties you can earn."></a></td>
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="assets/bountysource_qr_code.png" alt="Visita NewPipe en bountysource.com" width="100px"></a></td>
<td><a href="https://www.bountysource.com/teams/newpipe/issues"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f" height="30px" alt="Revisa cuántas recompensas puedes obtener."></a></td>
</tr>
</table>
## 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.

View File

@ -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를 생성하고, 이것에 서명하고, 사용자들에서 업데이트를 전달해야만 하기 때문에,
이것은 업데이트를 받는 가장 느린 방법입니다.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -23,7 +23,7 @@
<b>GOOGLE PLAY STORE'A NEWPIPE VEYA BAŞKA BİR KOPYASINI KOYMAK, PLAY STORE ŞARTLARINI VE KOŞULLARINI İHLAL EDER.</b>
## Ekran fotoğrafları
## Ekran görüntüleri
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png)
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png" width=160>](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.

View File

@ -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}"

View File

@ -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))

View File

@ -146,6 +146,7 @@
<data android:pathPrefix="/embed/" />
<data android:pathPrefix="/watch" />
<data android:pathPrefix="/attribution_link" />
<data android:pathPrefix="/shorts/" />
<!-- channel prefix -->
<data android:pathPrefix="/channel/" />
<data android:pathPrefix="/user/" />
@ -224,6 +225,7 @@
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="tubus.eduvid.org" />
<data android:host="invidio.us" />
<data android:host="dev.invidio.us" />
<data android:host="www.invidio.us" />
@ -309,6 +311,7 @@
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="eduvid.org" />
<data android:host="framatube.org" />
<data android:host="media.assassinate-you.net" />
<data android:host="peertube.co.uk" />
@ -358,6 +361,9 @@
<service
android:name=".RouterActivity$FetcherService"
android:exported="false" />
<service
android:name=".CheckForNewAppVersion"
android:exported="false" />
<!-- opting out of sending metrics to Google in Android System WebView -->
<meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" />

View File

@ -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 <hans@eds.org>
* 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();
}

View File

@ -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);
}
});
}
}

View File

@ -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);
}

View File

@ -350,12 +350,16 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
if (context == null || context.getResources() == null || activity == null) {
return;
}
final List<StreamDialogEntry> 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,

View File

@ -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<ChannelInfo>
.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;
});
}

View File

@ -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<PlaylistInfo> {
final ArrayList<StreamDialogEntry> 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<PlaylistInfo> {
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;
});
}

View File

@ -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<GroupieViewHolder>() {
) : GroupieAdapter() {
var currentIndex: Int = 0
private set

View File

@ -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<FeedState>() {
private var groupName = ""
private var oldestSubscriptionUpdate: OffsetDateTime? = null
private lateinit var groupAdapter: GroupAdapter<GroupieViewHolder>
private lateinit var groupAdapter: GroupieAdapter
@State @JvmField var showPlayedItems: Boolean = true
private var onSettingsChangeListener: SharedPreferences.OnSharedPreferenceChangeListener? = null
@ -131,7 +130,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
viewModel = ViewModelProvider(this, factory).get(FeedViewModel::class.java)
viewModel.stateLiveData.observe(viewLifecycleOwner, { it?.let(::handleResult) })
groupAdapter = GroupAdapter<GroupieViewHolder>().apply {
groupAdapter = GroupieAdapter().apply {
setOnItemClickListener(listenerStreamItem)
setOnItemLongClickListener(listenerStreamItem)
}
@ -326,9 +325,14 @@ class FeedFragment : BaseStateFragment<FeedState>() {
if (context == null || context.resources == null || activity == null) return
val entries = ArrayList<StreamDialogEntry>()
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(

View File

@ -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(

View File

@ -338,9 +338,14 @@ public class StatisticsPlaylistFragment
final ArrayList<StreamDialogEntry> 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,

View File

@ -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<List<PlaylistSt
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;
});
@ -752,8 +753,12 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
final ArrayList<StreamDialogEntry> 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(

View File

@ -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),

View File

@ -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<GroupieViewHolder>
private lateinit var subscriptionGroupAdapter: GroupieAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -153,7 +152,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
}
}
subscriptionGroupAdapter = GroupAdapter<GroupieViewHolder>().apply {
subscriptionGroupAdapter = GroupieAdapter().apply {
add(subscriptionMainSection)
add(subscriptionEmptyFooter)
spanCount = 4
@ -379,7 +378,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
}
private fun setupIconPicker() {
val groupAdapter = GroupAdapter<GroupieViewHolder>()
val groupAdapter = GroupieAdapter()
groupAdapter.addAll(FeedGroupIcon.values().map { PickerIconItem(it) })
feedGroupCreateBinding.iconSelector.apply {

View File

@ -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<Long>()
private val groupAdapter = GroupAdapter<GroupieViewHolder>()
private val groupAdapter = GroupieAdapter()
private val itemTouchHelper = ItemTouchHelper(getItemTouchCallback())
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -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

View File

@ -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<Bitmap> optAlbumArt,
final long duration
) {
if (DEBUG) {
Log.d(TAG, "setMetadata called:"
+ " t: " + title
+ " a: " + artist
+ " thumb: " + (
optAlbumArt.isPresent()
? optAlbumArt.get().hashCode()
: "<none>")
+ " 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()
: "<none>")
+ " 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<Bitmap> 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.
*/

View File

@ -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;

View File

@ -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<StreamInfo, MediaSource> {
@ -21,7 +22,7 @@ public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
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;
}

View File

@ -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<String>?)
}
}
}
preferenceEditor.commit()

View File

@ -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;
};

View File

@ -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) {

View File

@ -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 <T> Intent getPlayerIntent(@NonNull final Context context,
@NonNull final Class<T> 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 <T> Intent getPlayerIntent(@NonNull final Context context,
@NonNull final Class<T> 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 <T> Intent getPlayerEnqueueIntent(@NonNull final Context context,
@NonNull final Class<T> 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 <T> Intent getPlayerEnqueueNextIntent(@NonNull final Context context,
@NonNull final Class<T> 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) {

View File

@ -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) -> {

View File

@ -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 <code>true</code> 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;
}
}

View File

@ -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);
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M18,11v2h4v-2h-4zM16,17.61c0.96,0.71 2.21,1.65 3.2,2.39 0.4,-0.53 0.8,-1.07 1.2,-1.6 -0.99,-0.74 -2.24,-1.68 -3.2,-2.4 -0.4,0.54 -0.8,1.08 -1.2,1.61zM20.4,5.6c-0.4,-0.53 -0.8,-1.07 -1.2,-1.6 -0.99,0.74 -2.24,1.68 -3.2,2.4 0.4,0.53 0.8,1.07 1.2,1.6 0.96,-0.72 2.21,-1.65 3.2,-2.4zM4,9c-1.1,0 -2,0.9 -2,2v2c0,1.1 0.9,2 2,2h1v4h2v-4h1l5,3L13,6L8,9L4,9zM15.5,12c0,-1.33 -0.58,-2.53 -1.5,-3.35v6.69c0.92,-0.81 1.5,-2.01 1.5,-3.34z" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4v2z" />
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4V15z" />
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
</vector>

View File

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,8l-6,6 1.41,1.41L12,10.83l4.59,4.58L18,14z" />
</vector>

View File

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z" />
</vector>

View File

@ -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">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M11,17h2v-6h-2v6zM12,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,8zM11,9h2L13,7h-2v2z" />
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" />
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,8H4A2,2 0 0,0 2,10V14A2,2 0 0,0 4,16H5V20A1,1 0 0,0 6,21H8A1,1 0 0,0 9,20V16H12L17,20V4L12,8M21.5,12C21.5,13.71 20.54,15.26 19,16V8C20.53,8.75 21.5,10.3 21.5,12Z" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
android:pathData="M19.44,9.03L15.41,5H11v2h3.59l2,2H5c-2.8,0 -5,2.2 -5,5s2.2,5 5,5c2.46,0 4.45,-1.69 4.9,-4h1.65l2.77,-2.77c-0.21,0.54 -0.32,1.14 -0.32,1.77 0,2.8 2.2,5 5,5s5,-2.2 5,-5c0,-2.65 -1.97,-4.77 -4.56,-4.97zM7.82,15C7.4,16.15 6.28,17 5,17c-1.63,0 -3,-1.37 -3,-3s1.37,-3 3,-3c1.28,0 2.4,0.85 2.82,2H5v2h2.82zM19,17c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3z" />
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" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z" />
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" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2,16h8v-2L2,14v2z" />
android:pathData="M14,10H3v2h11V10zM14,6H3v2h11V6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2H18zM3,16h7v-2H3V16z" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM2,16h8v-2L2,14v2zM21.5,11.5L23,13l-6.99,7 -4.51,-4.5L13,14l3.01,3 5.49,-5.5z" />
android:pathData="M3,10h11v2h-11z" />
<path
android:fillColor="#FF000000"
android:pathData="M3,6h11v2h-11z" />
<path
android:fillColor="#FF000000"
android:pathData="M3,14h7v2h-7z" />
<path
android:fillColor="#FF000000"
android:pathData="M20.59,11.93l-4.25,4.24l-2.12,-2.12l-1.41,1.41l3.53,3.54l5.66,-5.66z" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M15 5L15 7L8.41 7L20 18.59L18.59 20L7 8.41L7 15L5 15L5 5Z" />
android:pathData="M19,17.59L17.59,19L7,8.41V15H5V5H15V7H8.41L19,17.59Z" />
</vector>

View File

@ -6,5 +6,5 @@
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z" />
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" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
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.73v1.91l0.01,0.01L1,14c0,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" />
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" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
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-1.91l-0.01,-0.01L23,10z" />
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" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10 10,-4.5 10,-10S17.5,2 12,2zM16.2,16.2L11,13L11,7h1.5v5.2l4.5,2.7 -0.8,1.3z" />
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" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M18,11v2h4v-2h-4zM16,17.61c0.96,0.71 2.21,1.65 3.2,2.39 0.4,-0.53 0.8,-1.07 1.2,-1.6 -0.99,-0.74 -2.24,-1.68 -3.2,-2.4 -0.4,0.54 -0.8,1.08 -1.2,1.61zM20.4,5.6c-0.4,-0.53 -0.8,-1.07 -1.2,-1.6 -0.99,0.74 -2.24,1.68 -3.2,2.4 0.4,0.53 0.8,1.07 1.2,1.6 0.96,-0.72 2.21,-1.65 3.2,-2.4zM4,9c-1.1,0 -2,0.9 -2,2v2c0,1.1 0.9,2 2,2h1v4h2v-4h1l5,3L13,6L8,9L4,9zM15.5,12c0,-1.33 -0.58,-2.53 -1.5,-3.35v6.69c0.92,-0.81 1.5,-2.01 1.5,-3.34z" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4v2z" />
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4V15z" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M11,17h2v-6h-2v6zM12,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,8zM11,9h2L13,7h-2v2z" />
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" />
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,8H4A2,2 0 0,0 2,10V14A2,2 0 0,0 4,16H5V20A1,1 0 0,0 6,21H8A1,1 0 0,0 9,20V16H12L17,20V4L12,8M21.5,12C21.5,13.71 20.54,15.26 19,16V8C20.53,8.75 21.5,10.3 21.5,12Z" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M19.44,9.03L15.41,5H11v2h3.59l2,2H5c-2.8,0 -5,2.2 -5,5s2.2,5 5,5c2.46,0 4.45,-1.69 4.9,-4h1.65l2.77,-2.77c-0.21,0.54 -0.32,1.14 -0.32,1.77 0,2.8 2.2,5 5,5s5,-2.2 5,-5c0,-2.65 -1.97,-4.77 -4.56,-4.97zM7.82,15C7.4,16.15 6.28,17 5,17c-1.63,0 -3,-1.37 -3,-3s1.37,-3 3,-3c1.28,0 2.4,0.85 2.82,2H5v2h2.82zM19,17c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3z" />
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" />
</vector>

View File

@ -7,5 +7,5 @@
<!-- Tint here is for preventing pixelization -->
<path
android:fillColor="#ffffff"
android:pathData="M5,19 L15,12 5,5ZM16,5v14h3v-14z" />
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z" />
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" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2,16h8v-2L2,14v2z" />
android:pathData="M14,10H3v2h11V10zM14,6H3v2h11V6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2H18zM3,16h7v-2H3V16z" />
</vector>

View File

@ -1,9 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M14,10L2,10v2h12v-2zM14,6L2,6v2h12L14,6zM2,16h8v-2L2,14v2zM21.5,11.5L23,13l-6.99,7 -4.51,-4.5L13,14l3.01,3 5.49,-5.5z" />
android:pathData="M3,10h11v2h-11z" />
<path
android:fillColor="#FF000000"
android:pathData="M3,6h11v2h-11z" />
<path
android:fillColor="#FF000000"
android:pathData="M3,14h7v2h-7z" />
<path
android:fillColor="#FF000000"
android:pathData="M20.59,11.93l-4.25,4.24l-2.12,-2.12l-1.41,1.41l3.53,3.54l5.66,-5.66z" />
</vector>

View File

@ -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">
<path
android:fillColor="#FF000000"
android:pathData="M19,9L2,9v2h17L19,9zM19,5L2,5v2h17L19,5zM2,15h13v-2L2,13v2zM17,13v6l5,-3 -5,-3z" />
android:pathData="M3,10h11v2h-11z" />
<path
android:fillColor="#FF000000"
android:pathData="M3,6h11v2h-11z" />
<path
android:fillColor="#FF000000"
android:pathData="M3,14h7v2h-7z" />
<path
android:fillColor="#FF000000"
android:pathData="M16,13l0,8l6,-4z" />
</vector>

View File

@ -7,5 +7,5 @@
<!-- Tint here is for preventing pixelization -->
<path
android:fillColor="#ffffff"
android:pathData="m19,5 l-10,7 10,7zM8,19v-14H5v14z" />
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M15 5L15 7L8.41 7L20 18.59L18.59 20L7 8.41L7 15L5 15L5 5Z" />
android:pathData="M19,17.59L17.59,19L7,8.41V15H5V5H15V7H8.41L19,17.59Z" />
</vector>

View File

@ -5,5 +5,5 @@
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z" />
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" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
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.73v1.91l0.01,0.01L1,14c0,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" />
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" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
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-1.91l-0.01,-0.01L23,10z" />
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" />
</vector>

View File

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10 10,-4.5 10,-10S17.5,2 12,2zM16.2,16.2L11,13L11,7h1.5v5.2l4.5,2.7 -0.8,1.3z" />
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" />
</vector>

View File

@ -695,10 +695,8 @@
<ImageButton
android:id="@+id/overlay_play_pause_button"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_width="40dp"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:padding="10dp"
android:scaleType="center"
@ -709,9 +707,8 @@
<ImageButton
android:id="@+id/overlay_close_button"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="2dp"
android:layout_width="40dp"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:padding="10dp"
android:scaleType="center"

View File

@ -166,7 +166,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:minWidth="0dp"
android:padding="@dimen/player_main_buttons_padding"
@ -180,7 +180,7 @@
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingStart="3dp"
@ -199,7 +199,7 @@
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingStart="3dp"
@ -281,7 +281,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/play_with_kodi_title"
android:focusable="true"
@ -296,7 +296,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/open_in_browser"
android:focusable="true"
@ -311,7 +311,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/share"
android:focusable="true"
@ -325,7 +325,7 @@
android:id="@+id/switchMute"
android:layout_width="wrap_content"
android:layout_height="37dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/mute"
android:focusable="true"
@ -339,7 +339,7 @@
android:id="@+id/fullScreenButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="@dimen/player_main_buttons_padding"
@ -447,7 +447,7 @@
android:id="@+id/playbackLiveSync"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:paddingLeft="4dp"
android:paddingRight="4dp"
@ -462,7 +462,7 @@
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="4dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:nextFocusUp="@id/playbackSeekBar"
@ -566,7 +566,7 @@
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="40dp"
android:background="?android:selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
@ -584,7 +584,7 @@
android:layout_centerVertical="true"
android:layout_marginStart="40dp"
android:layout_marginLeft="40dp"
android:background="?android:selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="10dp"
@ -599,7 +599,7 @@
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/repeatButton"
android:background="?android:selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="10dp"
@ -614,8 +614,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/itemsListClose"
android:layout_toRightOf="@id/shuffleButton"
android:layout_toStartOf="@id/itemsListClose"
android:layout_toEndOf="@id/shuffleButton"
android:gravity="center"
android:textColor="@android:color/white" />
</RelativeLayout>

View File

@ -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" />
<RelativeLayout
android:id="@+id/center"
<TextView
android:id="@+id/seek_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_above="@id/metadata"
android:background="#c0000000"
android:paddingLeft="30dp"
android:paddingTop="5dp"
android:paddingRight="30dp"
android:paddingBottom="5dp"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold"
android:visibility="gone"
tools:ignore="RtlHardcoded"
tools:text="1:06:29"
tools:visibility="visible" />
<LinearLayout
android:id="@+id/metadata"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/playback_controls">
<LinearLayout
android:id="@+id/metadata"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="8dp"
tools:ignore="RtlHardcoded,RtlSymmetry">
<TextView
android:id="@+id/song_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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." />
<TextView
android:id="@+id/artist_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="12sp"
tools:text="Duis posuere arcu condimentum lobortis mattis." />
</LinearLayout>
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">
<TextView
android:id="@+id/seek_display"
android:layout_width="wrap_content"
android:id="@+id/song_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#c0000000"
android:paddingLeft="30dp"
android:paddingTop="5dp"
android:paddingRight="30dp"
android:paddingBottom="5dp"
android:textColor="@android:color/white"
android:textSize="22sp"
android:textStyle="bold"
android:visibility="gone"
tools:ignore="RtlHardcoded"
tools:text="1:06:29"
tools:visibility="visible" />
</RelativeLayout>
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." />
<TextView
android:id="@+id/artist_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="12sp"
tools:text="Duis posuere arcu condimentum lobortis mattis." />
</LinearLayout>
<LinearLayout
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:orientation="horizontal"
android:paddingLeft="12dp"
android:paddingRight="12dp">
android:paddingRight="12dp"
android:layout_above="@+id/playback_controls">
<TextView
android:id="@+id/current_time"
@ -163,8 +157,9 @@
android:id="@+id/playback_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/progress_bar"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_marginBottom="12dp"
tools:ignore="RtlHardcoded">
<ImageButton
@ -294,5 +289,4 @@
tools:ignore="ContentDescription" />
</RelativeLayout>
</RelativeLayout>

View File

@ -672,10 +672,8 @@
<ImageButton
android:id="@+id/overlay_play_pause_button"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_width="40dp"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:padding="10dp"
android:scaleType="center"
@ -686,9 +684,8 @@
<ImageButton
android:id="@+id/overlay_close_button"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginLeft="2dp"
android:layout_width="40dp"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:padding="10dp"
android:scaleType="center"

View File

@ -168,7 +168,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:minWidth="0dp"
android:padding="@dimen/player_main_buttons_padding"
@ -182,7 +182,7 @@
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingStart="3dp"
@ -200,7 +200,7 @@
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:paddingStart="6dp"
@ -280,7 +280,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/play_with_kodi_title"
android:focusable="true"
@ -295,7 +295,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/open_in_browser"
android:focusable="true"
@ -310,7 +310,7 @@
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginEnd="8dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/share"
android:focusable="true"
@ -324,7 +324,7 @@
android:id="@+id/switchMute"
android:layout_width="wrap_content"
android:layout_height="37dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/mute"
android:focusable="true"
@ -338,7 +338,7 @@
android:id="@+id/fullScreenButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="@dimen/player_main_buttons_padding"
@ -445,7 +445,7 @@
android:id="@+id/playbackLiveSync"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:paddingLeft="4dp"
android:paddingRight="4dp"
@ -460,7 +460,7 @@
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="4dp"
android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="@dimen/player_main_buttons_padding"
@ -562,7 +562,7 @@
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="40dp"
android:background="?android:selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:contentDescription="@string/close"
android:focusable="true"
@ -580,7 +580,7 @@
android:layout_centerVertical="true"
android:layout_marginStart="40dp"
android:layout_marginLeft="40dp"
android:background="?android:selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="10dp"
@ -595,7 +595,7 @@
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/repeatButton"
android:background="?android:selectableItemBackground"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
android:padding="10dp"
@ -611,8 +611,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/shuffleButton"
android:layout_toLeftOf="@id/itemsListClose"
android:layout_toEndOf="@id/shuffleButton"
android:layout_toStartOf="@id/itemsListClose"
android:textColor="@android:color/white" />
</RelativeLayout>
@ -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" />
</RelativeLayout>
</RelativeLayout>

View File

@ -42,7 +42,7 @@
<string name="unsupported_url">رابط غير مدعوم</string>
<string name="use_external_audio_player_title">استخدام مشغل صوت خارجي</string>
<string name="use_external_video_player_title">استخدام مشغل فيديو خارجي</string>
<string name="content_not_available">محتوى غير متوفر</string>
<string name="content_not_available">المحتوى غير متوفر</string>
<string name="could_not_load_thumbnails">تعذر تحميل كافة الصور المصغرة</string>
<string name="general_error">خطأ</string>
<string name="parsing_error">تعذر تحليل الموقع</string>
@ -56,7 +56,7 @@
<string name="black_theme_title">أسود</string>
<string name="enable_watch_history_title">سجل المشاهدة</string>
<string name="settings_category_history_title">سجل المشاهدة و ذاكرة التخزين المؤقت</string>
<string name="content">محتوى</string>
<string name="content">المحتوى</string>
<string name="downloads">التحميلات</string>
<string name="downloads_title">الملفات المحملة</string>
<string name="all">الجميع</string>
@ -554,7 +554,7 @@
<string name="help">مساعدة</string>
<string name="content_not_supported">هذا المحتوى ليس مدعوم من قبل NewPipe.
\n
\nنامل ان يكون مدعوما في التحديثات القادمة.</string>
\nنأمل أن يكون مدعوما في التحديثات القادمة.</string>
<string name="infinite_videos">∞ فيديو</string>
<string name="more_than_100_videos">+100 فيديو</string>
<string name="artists">الفنانين</string>
@ -631,7 +631,7 @@
<string name="show_description_summary">قم بإيقاف التشغيل لإخفاء وصف الفيديو والمعلومات الإضافية</string>
<string name="show_description_title">إظهار الوصف</string>
<string name="open_with">فتح مع</string>
<string name="paid_content">يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe.</string>
<string name="paid_content">يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثه أو تنزيله عبر NewPipe.</string>
<string name="youtube_music_premium_content">يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium ، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe.</string>
<string name="private_content">هذا المحتوى خاص، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe.</string>
<string name="soundcloud_go_plus_content">هذا هو مسار SoundCloud Go+ ، على الأقل في بلدك ، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe.</string>
@ -715,4 +715,6 @@
</plurals>
<string name="start_main_player_fullscreen_summary">لا تبدأ تشغيل مقاطع الفيديو في المشغل المصغر، ولكن قم بتدوير وضع ملء الشاشة مباشرة، إذا تم تأمين التدوير التلقائي. لا يزال بإمكانك الوصول إلى المشغل المصغر عن طريق الخروج من ملء الشاشة</string>
<string name="start_main_player_fullscreen_title">بدء تشغيل المشغل الرئيسي في وضع ملء الشاشة</string>
<string name="enqueue_next_stream">وضع التالي على قائمة الانتظار</string>
<string name="enqueued_next">تم وضع التالي على قائمة الانتظار</string>
</resources>

View File

@ -189,7 +189,7 @@
<string name="unknown_content">[Neznámý]</string>
<string name="start_here_on_background">Začít přehrávat na pozadí</string>
<string name="start_here_on_popup">Začít přehrávat v pop-upu</string>
<string name="donation_title">Donate</string>
<string name="donation_title">Přispět</string>
<string name="donation_encouragement">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.</string>
<string name="give_back">Daruj</string>
<string name="website_title">Webová stránka</string>
@ -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.</string>
\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</string>
<string name="import_soundcloud_instructions">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 @@
<string name="comments_are_disabled">Komentáře jsou vypnuty</string>
<string name="detail_heart_img_view_description">Srdíčko od tvůrce</string>
<string name="mark_as_watched">Označit jako zhlédnuté</string>
<string name="loading_channel_details">Načítám podrobnosti kanálu…</string>
<string name="loading_channel_details">Načítání podrobností kanálu…</string>
<string name="error_show_channel_details">Chyba při zobrazení prodrobností kanálu</string>
<plurals name="deleted_downloads_toast">
<item quantity="one">%1$s stažení smazáno</item>
@ -675,4 +676,9 @@
<string name="show_image_indicators_title">Ukázat indikátory obrázků</string>
<string name="remote_search_suggestions">Vzdálené návrhy vyhledávání</string>
<string name="local_search_suggestions">Lokální návrhy vyhledávání</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="enqueued_next">Další ve frontě</string>
<string name="enqueue_next_stream">Přidat do fronty (další)</string>
<string name="main_page_content_swipe_remove">Tažením položky odstraníte</string>
<string name="start_main_player_fullscreen_title">Spustit hlavní přehrávač na celé obrazovce</string>
</resources>

View File

@ -544,7 +544,7 @@
<string name="feed_group_show_only_ungrouped_subscriptions">Nur nicht gruppierte Abonnements anzeigen</string>
<string name="playlist_page_summary">Wiedergabelisten-Seite</string>
<string name="no_playlist_bookmarked_yet">Bisher keine Lesezeichen für Wiedergabelisten</string>
<string name="select_a_playlist">Playlist auswählen</string>
<string name="select_a_playlist">Wiedergabeliste auswählen</string>
<string name="error_report_open_github_notice">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.</string>
<string name="search_showing_result_for">Zeige Ergebnisse für: %s</string>
<string name="autoplay_summary">Wiedergabe automatisch starten — %s</string>

View File

@ -190,7 +190,7 @@
<string name="donation_encouragement">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é.</string>
<string name="give_back">Dar de vuelta</string>
<string name="website_title">Sitio web</string>
<string name="website_encouragement">Visite el sitio web de NewPipe para más información y noticias.</string>
<string name="website_encouragement">Visita el sitio web de NewPipe para más información y noticias.</string>
<string name="default_content_country_title">País predefinido del contenido</string>
<string name="switch_to_background">Cambiar a segundo plano</string>
<string name="switch_to_popup">Cambiar a emergente</string>
@ -314,11 +314,11 @@
<string name="one_item_deleted">Se ha borrado 1 elemento.</string>
<string name="app_license">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.</string>
<string name="import_settings">¿Quieres importar también los ajustes\?</string>
<string name="privacy_policy_title">Normativa de privacidad de NewPipe</string>
<string name="privacy_policy_title">Política de privacidad de NewPipe</string>
<string name="privacy_policy_encouragement">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.</string>
<string name="read_privacy_policy">Leer la normativa de privacidad</string>
<string name="start_accept_privacy_policy">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.</string>
<string name="read_privacy_policy">Leer política de privacidad</string>
<string name="start_accept_privacy_policy">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.</string>
<string name="accept">Aceptar</string>
<string name="decline">Declinar</string>
@ -670,4 +670,6 @@
<string name="main_page_content_swipe_remove">Desliza los elementos para removerlos</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Iniciar reproductor principal en pantalla completa</string>
<string name="enqueued_next">Añadido el siguiente vídeo a la cola</string>
<string name="enqueue_next_stream">Añadir el siguiente vídeo a la cola</string>
</resources>

View File

@ -240,7 +240,7 @@
<string name="play_queue_remove">Eemalda</string>
<string name="play_queue_stream_detail">Üksikasjad</string>
<string name="play_queue_audio_settings">Heli seaded</string>
<string name="hold_to_append">Hoia järjekorda lisamiseks</string>
<string name="hold_to_append">Järjekorda lisamiseks vajuta</string>
<string name="start_here_on_background">Hakka taustal mängima</string>
<string name="start_here_on_popup">Hakka mängima hüpikaknas</string>
<string name="drawer_open">Ava sahtel</string>
@ -367,7 +367,7 @@
<string name="paused">peatatud</string>
<string name="queued">järjekorras</string>
<string name="post_processing">järeltöötlus</string>
<string name="enqueue">Järjekord</string>
<string name="enqueue">Esitusjärjekord</string>
<string name="permission_denied">Tegevus keelati süsteemi poolt</string>
<string name="download_failed">Allalaadimine nurjus</string>
<string name="generate_unique_name">Loo kordumatu nimi</string>
@ -667,4 +667,6 @@
</plurals>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Käivita meediamängija täisekraanivaates</string>
<string name="enqueued_next">Lisasin esitamiseks järgmisena</string>
<string name="enqueue_next_stream">Lisa esitamiseks järgmisena</string>
</resources>

View File

@ -488,7 +488,7 @@
<string name="feed_group_dialog_empty_name">Talde izena hutsik</string>
<plurals name="feed_group_dialog_selection_count">
<item quantity="one">%d hautatuta</item>
<item quantity="other">%d hautatuta</item>
<item quantity="other">%d hautatutak</item>
</plurals>
<string name="feed_group_dialog_empty_selection">Ez da harpidetzarik aukeratu</string>
<string name="feed_group_dialog_select_subscriptions">Hautatu harpidetzak</string>
@ -667,4 +667,6 @@
<string name="main_page_content_swipe_remove">Lerratu elementuak aldetara ezabatzeko</string>
<string name="start_main_player_fullscreen_summary">Ez hasi bideoak mini erreproduzitzailean eta hasi bideoak pantaila osoan zuzenean, auto biraketa blokeatuta badago. Mini erreproduzitzailea erabili dezakezu pantaila osotik irtetzean</string>
<string name="start_main_player_fullscreen_title">Hasi erreproduzitzaile nagusia pantaila osoan</string>
<string name="enqueued_next">Isatsari bideo hau erantsita</string>
<string name="enqueue_next_stream">Gehitu bideo hau isatsari</string>
</resources>

View File

@ -253,7 +253,7 @@
<string name="invalid_directory">Aucun dossier de ce type</string>
<string name="invalid_source">Aucun fichier ou contenu de ce type</string>
<string name="invalid_file">Le fichier nexiste pas ou nest pas accessible en lecture ou en écriture</string>
<string name="file_name_empty_error">Le nom du fichier ne peut être vide</string>
<string name="file_name_empty_error">Le nom du fichier ne peut pas être vide</string>
<string name="error_occurred_detail">Une erreur est survenue : %1$s</string>
<string name="controls_download_desc">Télécharger le flux</string>
<string name="auto_queue_title">Ajouter automatiquement le flux suivant à la liste de lecture</string>
@ -670,4 +670,5 @@
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Lancer le lecteur principal en plein écran</string>
<string name="enqueue_next_stream">Mettre en file dattente la suivante</string>
<string name="enqueued_next">Placé comme suivant dans liste de lecture</string>
</resources>

View File

@ -49,7 +49,7 @@
<string name="popup_remember_size_pos_title">Zapamti veličinu i poziciju skočnog prozora</string>
<string name="popup_remember_size_pos_summary">Zapamti posljednju veličinu i poziciju skočnog prozora</string>
<string name="show_search_suggestions_title">Prijedlozi pri traženju</string>
<string name="show_search_suggestions_summary">Prikaži prijedloge pri traženju</string>
<string name="show_search_suggestions_summary">Odaberi prijedloge koji se prikazuju pri traženju</string>
<string name="enable_search_history_title">Povijest pretraživanja</string>
<string name="enable_search_history_summary">Svaku pretragu spremi lokalno</string>
<string name="enable_watch_history_title">Prati povijest</string>

View File

@ -104,7 +104,7 @@
<string name="popup_remember_size_pos_title">Ingat properti popup</string>
<string name="popup_remember_size_pos_summary">Ingat ukuran dan posisi terakhir popup</string>
<string name="show_search_suggestions_title">Saran pencarian</string>
<string name="show_search_suggestions_summary">Tampilkan saran pencarian saat mencari</string>
<string name="show_search_suggestions_summary">Menampilkan saran pencarian saat mencari</string>
<string name="best_resolution">Resolusi terbaik</string>
<string name="settings_category_downloads_title">Unduhan</string>
<string name="settings_file_charset_title">Karakter yang diizinkan sebagai nama berkas</string>
@ -638,4 +638,16 @@
<string name="comments_are_disabled">Komentar dinonaktifkan</string>
<string name="seekbar_preview_thumbnail_title">Pratinjau thumbnail bilah laju</string>
<string name="mark_as_watched">Tandai ditonton</string>
<string name="start_main_player_fullscreen_title">Buka pemutar utama dalam layar penuh</string>
<plurals name="download_finished_notification">
<item quantity="other">%s unduhan selesai</item>
</plurals>
<string name="main_page_content_swipe_remove">Geser item untuk membuangnya</string>
<string name="detail_heart_img_view_description">Disukai oleh kreator</string>
<string name="local_search_suggestions">Saran pencarian lokal</string>
<string name="remote_search_suggestions">Saran pencarian remote</string>
<string name="show_image_indicators_title">Tampilkan indikator gambar</string>
<plurals name="deleted_downloads_toast">
<item quantity="other">Menghapus %1$s unduhan</item>
</plurals>
</resources>

View File

@ -16,7 +16,7 @@
<string name="download_path_dialog_title">비디오 파일이 다운로드 될 폴더를 선택하세요</string>
<string name="default_resolution_title">기본 해상도</string>
<string name="play_with_kodi_title">Kodi로 재생</string>
<string name="kore_not_found">Kore 앱이 발견되지 않았습니다. Kore를 설치할까요?</string>
<string name="kore_not_found">Kore를 설치할까요\?</string>
<string name="show_play_with_kodi_title">\"Kodi로 재생\" 옵션 표시</string>
<string name="show_play_with_kodi_summary">비디오를 Kodi 미디어 센터를 사용해 재생하는 옵션을 표시합니다</string>
<string name="play_audio">오디오</string>
@ -282,7 +282,7 @@
\n
\n계속하시겠습니까\?</string>
<string name="download_thumbnail_title">썸네일 로드하기</string>
<string name="download_thumbnail_summary">동영상 썸네일을 로드하지 않으며, 데이터와 메모리 사용을 최대한 줄입니다. 이 옵션을 선택 시 모든 메모리 캐시와 저장소 캐시를 삭제합니다.</string>
<string name="download_thumbnail_summary">동영상 썸네일을 로드하지 않으며, 데이터와 메모리 사용을 최대한 줄입니다. 이 옵션을 선택 시 모든 메모리 캐시와 저장소 캐시를 삭제합니다</string>
<string name="thumbnail_cache_wipe_complete_notice">이미지 캐시 지워짐</string>
<string name="metadata_cache_wipe_title">캐시된 메타데이터 지우기</string>
<string name="metadata_cache_wipe_summary">캐시된 모든 웹페이지 데이터 지우기</string>
@ -501,7 +501,7 @@
<string name="title_activity_play_queue">재생목록 실행</string>
<string name="settings_category_notification_title">알림</string>
<string name="unsupported_url_dialog_message">URL을 인식할 수 없습니다. 다른 앱으로 여시겠습니까\?</string>
<string name="clear_queue_confirmation_title">스트림을 비우기 전 확인을 요청합니다.</string>
<string name="clear_queue_confirmation_title">대기열을 비우기 전 확인하도록 합니다.</string>
<string name="notification_colorize_summary">안드로이드에서 썸네일의 색상에 따라 알림 색상을 조절합니다. (지원되지 않는 기기가 있을 수 있습니다.)</string>
<string name="notification_action_buffering">버퍼링</string>
<string name="notification_action_4_title">다섯번째 버튼</string>
@ -514,4 +514,10 @@
<string name="clear_queue_confirmation_description">활성화된 플레이어 대기열이 교체됩니다.</string>
<string name="open_with">으로(로) 열기</string>
<string name="mark_as_watched">시청한 것으로 처리</string>
<string name="show_description_summary">비활성화하면 비디오 설명과 추가 정보를 표시하지 않습니다</string>
<string name="show_description_title">설명 표시</string>
<string name="clear_queue_confirmation_summary">원래 플레이어에서 다른 플레이어로 바꾸면 대기열이 지워집니다</string>
<string name="night_theme_title">어두운 테마</string>
<string name="notification_actions_at_most_three">최대 3개까지 축소 알림에 표시될 항목을 고를 수 있습니다!</string>
<string name="notification_actions_summary">아래 항목을 터치해서 편집하세요. 위에서부터 체크된 3개 항목은 축소 알림일 때도 표시됩니다</string>
</resources>

View File

@ -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.</string>
\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</string>
<string name="import_soundcloud_instructions">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 @@
<string name="show_age_restricted_content_summary">Toon inhoud die mogelijk niet geschikt is voor kinderen omwille van een leeftijdslimiet (zoals 18+)</string>
<string name="notification_colorize_summary">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)</string>
<string name="notification_colorize_title">Notificatie kleur aanpassen</string>
<string name="show_thumbnail_summary">Toon miniatuurafbeelding op het vergrendelscherm als achtergrond en in de meldingen</string>
<string name="show_thumbnail_summary">Toon miniatuurafbeelding op het vergrendelscherm als achtergrond en in de notificaties</string>
<string name="show_thumbnail_title">Toon miniatuurafbeelding</string>
<string name="recent">Recent</string>
<string name="recent">Recente</string>
<string name="msg_calculating_hash">Hash berekenen</string>
<string name="hash_channel_description">Meldingen over de voortgang van video hashing</string>
<string name="hash_channel_name">Video Hash Melding</string>
@ -588,7 +589,7 @@
<string name="chapters">Hoofdstukken</string>
<string name="related_items_tab_description">Gerelateerde streams</string>
<string name="comments_tab_description">Reacties</string>
<string name="show_description_summary">Zet uit om video beschrijving en extra informatie te verbergen</string>
<string name="show_description_summary">Zet uit om video omschrijving en andere informatie te verbergen</string>
<string name="open_with">Open met</string>
<string name="radio">Radio</string>
<string name="featured">Uitgelicht</string>
@ -606,7 +607,7 @@
<string name="night_theme_summary">Selecteer uw favoriete nacht thema — %s</string>
<string name="auto_device_theme_title">Automatisch (toestel thema)</string>
<string name="show_channel_details">Toon details van kanaal</string>
<string name="night_theme_title">Nachtmodus</string>
<string name="night_theme_title">Nacht Thema</string>
<string name="metadata_privacy_internal">Intern</string>
<string name="metadata_privacy_private">Privé</string>
<string name="metadata_privacy_unlisted">Niet vermeld</string>
@ -655,4 +656,17 @@
<string name="remote_search_suggestions">Zoeksuggesties op afstand</string>
<string name="local_search_suggestions">Lokale zoeksuggesties</string>
<string name="mark_as_watched">Markeer als bekeken</string>
<plurals name="deleted_downloads_toast">
<item quantity="one">%1$s download verwijderd</item>
<item quantity="other">%1$s downloads verwijderd</item>
</plurals>
<plurals name="download_finished_notification">
<item quantity="one">Download voltooid</item>
<item quantity="other">%s downloads voltooid</item>
</plurals>
<string name="enqueued_next">Volgende item in de wachtrij geplaatst</string>
<string name="enqueue_next_stream">Plaats volgende item in de wachtrij</string>
<string name="main_page_content_swipe_remove">Veeg items om ze te verwijderen</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Start hoofdspeler als volledig scherm</string>
</resources>

View File

@ -117,7 +117,7 @@
<string name="app_description">Lekkie przesyłanie strumieniowe w systemie Android.</string>
<string name="view_on_github">Zobacz na GitHubie</string>
<string name="app_license_title">Licencja NewPipe</string>
<string name="contribution_encouragement">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!</string>
<string name="contribution_encouragement">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!</string>
<string name="read_full_license">Przeczytaj licencję</string>
<string name="contribution_title">Wkład</string>
<string name="settings_file_charset_title">Dozwolone znaki w nazwach plików</string>
@ -304,7 +304,7 @@
\n4. Skopiuj adres URL profilu, na który zostałeś(-aś) przekierowany(-na).</string>
<string name="no_streams_available_download">Brak strumieni do pobrania</string>
<string name="preferred_open_action_settings_title">Preferowana akcja „otwórz”</string>
<string name="preferred_open_action_settings_summary">Domyślna akcja podczas otwierania zawartości - %s</string>
<string name="preferred_open_action_settings_summary">Domyślna akcja podczas otwierania zawartości %s</string>
<string name="caption_setting_title">Napisy</string>
<string name="caption_setting_description">Zmodyfikuj rozmiar tekstu napisów odtwarzacza i style tła. Wymaga ponownego uruchomienia aplikacji, aby zmiany zostały uwzględnione</string>
<string name="clear_views_history_title">Wyczyść historię oglądania</string>

View File

@ -105,7 +105,7 @@
<string name="popup_remember_size_pos_summary">Lembrar último tamanho e posição do popup</string>
<string name="use_external_video_player_summary">Remove o som em algumas resoluções</string>
<string name="show_search_suggestions_title">Sugestões de pesquisa</string>
<string name="show_search_suggestions_summary">Mostra sugestões ao pesquisar</string>
<string name="show_search_suggestions_summary">Escolha as sugestões a serem exibidas enquanto estiver buscando</string>
<string name="best_resolution">Melhor resolução</string>
<string name="title_licenses">Licenças de Terceiros</string>
<string name="tab_about">Sobre</string>
@ -264,14 +264,15 @@
<string name="previous_export">Exportação anterior</string>
<string name="subscriptions_import_unsuccessful">Não foi possível importar inscrições</string>
<string name="subscriptions_export_unsuccessful">Não foi possível exportar inscrições</string>
<string name="import_youtube_instructions">Importe inscrições do YouTubedo pelo Google takeout:
<string name="import_youtube_instructions">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.</string>
\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</string>
<string name="import_soundcloud_instructions">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 @@
<string name="comments_are_disabled">Comentários estão desabilitados</string>
<string name="mark_as_watched">Marcar como visto</string>
<string name="detail_heart_img_view_description">Curtido pelo criador</string>
<string name="show_image_indicators_summary">Exibir fitas coloridas de picasso no topo das imagens indicando sua fonte: vermelho para rede, azul para disco e verde para memória</string>
<string name="loading_channel_details">Carregando detalhes do canal…</string>
<string name="error_show_channel_details">Erro ao exibir detalhes do canal</string>
<plurals name="deleted_downloads_toast">
<item quantity="one">%1$s download apagado</item>
<item quantity="other">%1$s downloads apagados</item>
</plurals>
<plurals name="download_finished_notification">
<item quantity="one">Download finalizado</item>
<item quantity="other">%s downloads finalizados</item>
</plurals>
<string name="show_image_indicators_title">Exibir indicadores com imagem</string>
<string name="enqueued_next">Adicionado na próxima posição da fila</string>
<string name="enqueue_next_stream">Adicionar a próxima posição da fila</string>
<string name="main_page_content_swipe_remove">Deslize items para remove-los</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Iniciar o reprodutor principal em tela cheia</string>
<string name="remote_search_suggestions">Sugestões de busca remotas</string>
<string name="local_search_suggestions">Sugestões de busca locais</string>
</resources>

View File

@ -24,7 +24,7 @@
<string name="error_progress_lost">Progresso perdido, o ficheiro foi eliminado</string>
<string name="channel_unsubscribed">Canal não subscrito</string>
<string name="msg_name">Nome do ficheiro</string>
<string name="enable_playback_state_lists_summary">Mostrar indicadores de posição de reprodução em listas</string>
<string name="enable_playback_state_lists_summary">Mostrar indicadores de posição de reprodução nas listas</string>
<string name="notification_channel_description">Notificações para NewPipe e para os reprodutores popup</string>
<string name="unhook_checkbox">Desvincular (pode causar distorção)</string>
<string name="show_search_suggestions_summary">Escolha as sugestões a mostrar ao pesquisar</string>
@ -68,7 +68,7 @@
<string name="feed_group_dialog_delete_message">Deseja apagar este grupo\?</string>
<string name="error_unknown_host">Não foi possível encontrar o servidor</string>
<string name="subscriptions_import_unsuccessful">Não foi possível importar as subscrições</string>
<string name="downloads">Descargas</string>
<string name="downloads">Transferências</string>
<string name="feed_processing_message">A processar…</string>
<string name="volume_gesture_control_title">Gestos para controlo de volume</string>
<string name="restricted_video">Este vídeo está restringido a idades.
@ -82,7 +82,7 @@
<string name="delete_playback_states_alert">Remover todas as posições de reprodução\?</string>
<string name="enable_queue_limit">Limitar fila de descargas</string>
<string name="show_age_restricted_content_title">Mostrar conteúdo com restrição de idade</string>
<string name="privacy_policy_encouragement">O projeto NewPipe leva a sua privacidade muito a sério. Sendo assim, não recolhe quaisquer dados sem o seu consentimento.
<string name="privacy_policy_encouragement">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.</string>
<string name="file">Ficheiro</string>
<string name="controls_add_to_playlist_title">Adicionar a</string>
@ -93,7 +93,7 @@
<string name="error_connect_host">Não foi possível ligar ao servidor</string>
<string name="show_play_with_kodi_summary">Mostrar uma opção para reproduzir o vídeo no Kodi</string>
<string name="list_view_mode">Modo de exibição</string>
<string name="use_inexact_seek_summary">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</string>
<string name="use_inexact_seek_summary">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</string>
<string name="permission_display_over_apps">Permitir sobreposição a outras aplicações</string>
<string name="export_to">Exportar para</string>
<string name="title_activity_about">Acerca de NewPipe</string>
@ -129,8 +129,8 @@
<string name="no_channel_subscribed_yet">Não existem canais subscritos</string>
<string name="settings_category_player_behavior_title">Comportamento</string>
<string name="no_available_dir">Tem que definir, nas definições, uma pasta para as descargas</string>
<string name="enable_playback_state_lists_title">Posições nas listas</string>
<string name="enable_queue_limit_desc">Uma descarga será executada ao mesmo tempo</string>
<string name="enable_playback_state_lists_title">Posições em listas</string>
<string name="enable_queue_limit_desc">Permitir apenas uma descarga de cada vez</string>
<string name="error_http_not_found">Não encontrado</string>
<string name="background_player_playing_toast">Reprodução em segundo plano</string>
<string name="show_higher_resolutions_title">Mostrar resoluções mais altas</string>
@ -264,7 +264,7 @@
<string name="restore_defaults_confirmation">Deseja repor as predefinições\?</string>
<string name="external_player_unsupported_link_type">Os reprodutores externos não suportam este tipo de hiperligações</string>
<string name="rename">Mudar nome</string>
<string name="downloads_storage_use_saf_summary">\'Storage Access Framework\' permite descargas para um cartão SD externo</string>
<string name="downloads_storage_use_saf_summary">\'Storage Access Framework\' permite transferências para um cartão SD externo</string>
<string name="seek_duration_title">Duração da pesquisa de avanço/recuo rápido</string>
<string name="missing_file">Ficheiro movido ou eliminado</string>
<string name="title_last_played">Última reprodução</string>
@ -313,7 +313,7 @@
<string name="charset_most_special_characters">Mais caracteres especiais</string>
<string name="download_path_audio_title">Pasta para ficheiros de áudio</string>
<string name="error_details_headline">Detalhes:</string>
<string name="settings_category_downloads_title">Descargas</string>
<string name="settings_category_downloads_title">Transferências</string>
<string name="settings_category_feed_title">Fonte</string>
<string name="playlist_page_summary">Página da lista de reprodução</string>
<string name="settings">Definições</string>
@ -323,7 +323,7 @@
<string name="albums">Álbuns</string>
<string name="previous_export">Exportação anterior</string>
<string name="overwrite_unrelated_warning">Já existe um ficheiro com este nome</string>
<string name="error_http_unsupported_range">O servidor não aceita descargas multi-processo, tente novamente com @string/msg_threads = 1</string>
<string name="error_http_unsupported_range">O servidor não aceita transferências multi-processo, tente novamente com @string/msg_threads = 1</string>
<string name="detail_drag_description">Arraste para reordenar</string>
<string name="recovering">a recuperar</string>
<string name="dismiss">Rejeitar</string>
@ -341,7 +341,7 @@
<item quantity="one">%d dia</item>
<item quantity="other">%d dias</item>
</plurals>
<string name="pause_downloads">Pausa nas descargas</string>
<string name="pause_downloads">Pausa nas transferências</string>
<string name="title_activity_recaptcha">Desafio reCAPTCHA</string>
<string name="import_from">Importar de</string>
<string name="one_item_deleted">1 item eliminado.</string>
@ -361,7 +361,7 @@
<string name="could_not_setup_download_menu">Não foi possível configurar o menu de descargas</string>
<string name="limit_data_usage_none_description">Sem limite</string>
<string name="general_error">Erro</string>
<string name="clear_playback_states_title">Remover posições de reprodução</string>
<string name="clear_playback_states_title">Limpar posições de reprodução</string>
<string name="import_ongoing">A importar…</string>
<string name="fragment_feed_title">Novidades</string>
<string name="local">Local</string>
@ -372,7 +372,7 @@
<string name="infinite_videos">∞ vídeos</string>
<string name="export_ongoing">A exportar…</string>
<string name="most_liked">Mais apreciados</string>
<string name="downloads_storage_use_saf_title">Utilizar a escolha de pastas do sistema (SAF)</string>
<string name="downloads_storage_use_saf_title">Utilizar seletor de pastas do sistema (SAF)</string>
<string name="play_queue_stream_detail">Detalhes</string>
<string name="network_error">Erro de rede</string>
<string name="enable_search_history_title">Histórico de pesquisa</string>
@ -403,7 +403,7 @@
<string name="search_history_deleted">Histórico de pesquisa removido</string>
<string name="clear_search_history_title">Limpar histórico de pesquisas</string>
<string name="msg_error">Erro</string>
<string name="popup_remember_size_pos_title">Lembrar propriedades de popup</string>
<string name="popup_remember_size_pos_title">Lembrar propriedades do popup</string>
<string name="download_path_summary">Os ficheiros de vídeo descarregados serão guardados aqui</string>
<string name="switch_to_main">Mudar para principal</string>
<string name="msg_popup_permission">Esta permissão é necessária
@ -425,9 +425,9 @@
<string name="short_thousand">k</string>
<string name="short_billion">MM</string>
<string name="unbookmark_playlist">Remover marcador</string>
<string name="pause_downloads_on_mobile_desc">Útil ao trocar para dados móveis, mas algumas descargas não podem ser suspensas</string>
<string name="pause_downloads_on_mobile_desc">Útil ao trocar para dados móveis, mas algumas transferências não podem ser suspensas</string>
<string name="hold_to_append">Toque longo para colocar na fila</string>
<string name="downloads_title">Descargas</string>
<string name="downloads_title">Transferências</string>
<string name="error_file_creation">Não foi possível criar o ficheiro</string>
<string name="conferences">Conferências</string>
<string name="saved_tabs_invalid_json">Não foi possível ler as guias gravadas, portanto usando as guias predefinidas</string>
@ -446,7 +446,7 @@
<string name="settings_category_updates_title">Atualizações</string>
<string name="list_thumbnail_view_description">Miniatura do vídeo</string>
<string name="updates_setting_title">Atualizações</string>
<string name="start_downloads">Iniciar descarga</string>
<string name="start_downloads">Iniciar transferências</string>
<string name="enable_search_history_summary">Guardar termos de pesquisa localmente</string>
<string name="unsupported_url">URL não suportado</string>
<string name="download_dialog_title">Descarregar</string>
@ -457,7 +457,7 @@
<string name="popup_player">Reprodutor \'popup\'</string>
<string name="feed_use_dedicated_fetch_method_summary">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)</string>
<string name="watch_history_states_deleted">Posições de reprodução removidas</string>
<string name="downloads_storage_ask_title">Perguntar localização</string>
<string name="downloads_storage_ask_title">Perguntar para onde transferir</string>
<string name="show_info">Mostrar informação</string>
<string name="clear_views_history_title">Limpar histórico de visualizações</string>
<string name="download_to_sdcard_error_message">Não é possível guardar no cartão SD. Repor pasta de descargas\?</string>
@ -470,7 +470,7 @@
<string name="default_video_format_title">Formato padrão de vídeo</string>
<string name="show_hold_to_append_title">Mostrar dica \"Toque longo para colocar na fila\"</string>
<string name="choose_instance_prompt">Escolha uma instância</string>
<string name="metadata_cache_wipe_summary">Remover todos os dados da página web</string>
<string name="metadata_cache_wipe_summary">Limpar todos os dados da página web</string>
<string name="drawer_close">Fechar menu</string>
<string name="brightness_gesture_control_summary">Utilizar gestos para controlar o brilho do reprodutor</string>
<string name="remove_watched">Remover visualizados</string>
@ -481,9 +481,9 @@
<string name="videos_string">Vídeos</string>
<string name="metadata_cache_wipe_complete_notice">Meta-dados em cache limpos</string>
<string name="show_hold_to_append_summary">Mostrar dica ao premir em segundo plano ou no botão \"Detalhes:\" da janela popup</string>
<string name="no_player_found_toast">Nenhum reprodutor foi encontrado (pode instalar VLC para reproduzir).</string>
<string name="downloads_storage_ask_summary">Ser-lhe-á perguntado onde guardar cada descarga.
\nAtive o seletor de pastas do sistema (SAF) se quiser descarregar para um cartão SD externo</string>
<string name="no_player_found_toast">Não foi encontrado um reprodutor (pode instalar VLC para reproduzir).</string>
<string name="downloads_storage_ask_summary">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</string>
<string name="show_play_with_kodi_title">Mostrar opção \"Reproduzir no Kodi\"</string>
<string name="search_no_results">Sem resultados</string>
<string name="disabled">Desativado</string>
@ -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.</string>
<string name="open_in_popup_mode">Abrir em modo popup</string>
<string name="open_in_popup_mode">Abrir no modo popup</string>
<string name="pause">Pausa</string>
<string name="preferred_player_fetcher_notification_message">A carregar o conteúdo solicitado</string>
<string name="channel_page_summary">Página do canal</string>
@ -529,7 +529,7 @@
<string name="caption_setting_description">Modificar escala de legendas e estilo de fundo. Tem que reiniciar a aplicação para aplicar as alterações</string>
<string name="permission_denied">Ação recusada pelo sistema</string>
<string name="songs">Músicas</string>
<string name="localization_changes_requires_app_restart">O idioma será alterado assim que reiniciar a aplicação</string>
<string name="localization_changes_requires_app_restart">O idioma será alterado assim que reiniciar a app</string>
<string name="peertube_instance_add_title">Adicionar instância</string>
<string name="tracks">Faixas</string>
<string name="play_with_kodi_title">Reproduzir no Kodi</string>
@ -551,13 +551,13 @@
<string name="clear_queue_confirmation_description">A fila do reprodutor ativo será substituída</string>
<string name="clear_queue_confirmation_summary">Mudar de um reprodutor para outro pode substituir a sua fila</string>
<string name="clear_queue_confirmation_title">Pedir confirmação antes de limpar uma fila</string>
<string name="popup_remember_size_pos_summary">Lembrar do último tamanho e posição do popup</string>
<string name="popup_remember_size_pos_summary">Lembrar último tamanho e posição do popup</string>
<string name="notification_action_nothing">Nada</string>
<string name="notification_action_buffering">A carregar</string>
<string name="notification_action_shuffle">Baralhar</string>
<string name="notification_action_repeat">Repetir</string>
<string name="notification_actions_at_most_three">Pode selecionar, no máximo, três ações para mostrar na notificação compacta!</string>
<string name="notification_actions_summary">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</string>
<string name="notification_actions_summary">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</string>
<string name="notification_action_4_title">Quinto botão de ação</string>
<string name="notification_action_3_title">Quarto botão de ação</string>
<string name="notification_action_2_title">Terceiro botão de ação</string>
@ -573,7 +573,7 @@
<string name="clear_cookie_title">Limpar cookies reCAPTCHA</string>
<string name="youtube_restricted_mode_enabled_summary">O YouTube fornece um \"Modo restrito\" que oculta o conteúdo destinado a adultos</string>
<string name="show_age_restricted_content_summary">Mostrar conteúdo possivelmente impróprio para crianças porque tem um limite de idade (como 18+)</string>
<string name="notification_colorize_summary">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)</string>
<string name="notification_colorize_summary">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)</string>
<string name="notification_colorize_title">Colorir notificação</string>
<string name="show_thumbnail_summary">Usar miniaturas no fundo do ecrã de bloqueio e em notificações</string>
<string name="show_thumbnail_title">Mostrar miniatura</string>
@ -600,13 +600,13 @@
<string name="restricted_video_no_stream">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.</string>
<string name="radio">Rádio</string>
<string name="featured">Destaque</string>
<string name="featured">Destaques</string>
<string name="recaptcha_solve">Resolver</string>
<string name="download_has_started">Descarga iniciada</string>
<string name="select_night_theme_toast">Pode escolher o seu tema escuro favorito abaixo</string>
<string name="night_theme_summary">Escolha o seu tema escuro favorito — %s</string>
<string name="auto_device_theme_title">Automático (Tema do aparelho)</string>
<string name="night_theme_title">Tema Escuro</string>
<string name="auto_device_theme_title">Automático (Tema do dispositivo)</string>
<string name="night_theme_title">Tema escuro</string>
<string name="show_channel_details">Mostrar detalhes do canal</string>
<string name="disable_media_tunneling_summary">Desative esta opção se estiverem a ocorrer erros de ecrã escuro ou paragens durante a reprodução</string>
<string name="disable_media_tunneling_title">Desativar túnel multimédia</string>
@ -641,12 +641,12 @@
<string name="feed_load_error_account_info">Não foi possível carregar o feed para \'%s\'.</string>
<string name="feed_load_error">Erro ao carregar o feed</string>
<string name="downloads_storage_use_saf_summary_api_29">A partir do Android 10, apenas o \'Storage Access Framework\' é compatível</string>
<string name="downloads_storage_use_saf_summary_api_19">O \'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores</string>
<string name="downloads_storage_ask_summary_no_saf_notice">Sempre que descarregar um ficheiro, terá que indicar o local para o guardar</string>
<string name="downloads_storage_use_saf_summary_api_19">\'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores</string>
<string name="downloads_storage_ask_summary_no_saf_notice">Sempre que transferir um ficheiro, terá que indicar o local para o guardar</string>
<string name="dont_show">Não mostrar</string>
<string name="low_quality_smaller">Baixa qualidade (menor)</string>
<string name="high_quality_larger">Alta qualidade (maior)</string>
<string name="seekbar_preview_thumbnail_title">Pré visualização da miniatura da barra de busca</string>
<string name="seekbar_preview_thumbnail_title">Pré-visualização da miniatura da barra de pesquisa</string>
<string name="no_dir_yet">Ainda sem pasta de descarregas definida, escolha agora a pasta de descarregas padrão</string>
<string name="comments_are_disabled">Comentários estão desativados</string>
<string name="mark_as_watched">Marcar como visto</string>
@ -665,8 +665,8 @@
<item quantity="other">%s descargas concluídas</item>
</plurals>
<string name="main_page_content_swipe_remove">Deslizar itens para removê-los</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Iniciar o reprodutor principal em ecrã cheio</string>
<string name="start_main_player_fullscreen_summary">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.</string>
<string name="start_main_player_fullscreen_title">Iniciar reprodutor principal em ecrã completo</string>
<string name="enqueued_next">Enfileirado o próximo</string>
<string name="enqueue_next_stream">Enfileirar o próximo</string>
</resources>

View File

@ -81,7 +81,7 @@
<string name="msg_running">Descarga NewPipe</string>
<string name="app_ui_crash">Aplicação terminou em erro</string>
<string name="info_labels">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:</string>
<string name="open_in_popup_mode">Abrir em modo popup</string>
<string name="open_in_popup_mode">Abrir no modo popup</string>
<string name="black_theme_title">Preto</string>
<string name="all">Tudo</string>
<string name="yes">Sim</string>
@ -97,13 +97,13 @@
<string name="disabled">Desativado</string>
<string name="default_popup_resolution_title">Resolução padrão para janela popup</string>
<string name="show_higher_resolutions_title">Mostrar resoluções mais altas</string>
<string name="show_higher_resolutions_summary">Apenas alguns aparelhos conseguem reproduzir vídeos em 2K/4K</string>
<string name="show_higher_resolutions_summary">Apenas alguns dispositivos conseguem reproduzir vídeos em 2K/4K</string>
<string name="controls_popup_title">Popup</string>
<string name="popup_remember_size_pos_title">Lembrar propriedades de popup</string>
<string name="popup_remember_size_pos_title">Lembrar propriedades do popup</string>
<string name="clear">Limpar</string>
<string name="controls_background_title">Segundo plano</string>
<string name="use_external_video_player_summary">Remove o áudio em algumas resoluções</string>
<string name="popup_remember_size_pos_summary">Lembrar do último tamanho e posição do popup</string>
<string name="popup_remember_size_pos_summary">Lembrar último tamanho e posição do popup</string>
<string name="show_search_suggestions_title">Sugestões de pesquisa</string>
<string name="show_search_suggestions_summary">Escolha as sugestões a mostrar ao pesquisar</string>
<string name="best_resolution">Melhor resolução</string>
@ -229,7 +229,7 @@
<string name="drawer_close">Fechar menu</string>
<string name="name">Nome</string>
<string name="metadata_cache_wipe_title">Limpar meta-dados em cache</string>
<string name="metadata_cache_wipe_summary">Remover todos os dados da página web</string>
<string name="metadata_cache_wipe_summary">Limpar todos os dados da página web</string>
<string name="metadata_cache_wipe_complete_notice">Meta-dados em cache limpos</string>
<string name="file">Ficheiro</string>
<string name="title_last_played">Última reprodução</string>
@ -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</string>
<string name="import_soundcloud_instructions">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.</string>
@ -397,8 +397,8 @@
<string name="close">Fechar</string>
<string name="enable_playback_resume_title">Continuar reprodução</string>
<string name="enable_playback_resume_summary">Restaurar última posição de reprodução</string>
<string name="enable_playback_state_lists_title">Posições nas listas</string>
<string name="enable_playback_state_lists_summary">Mostrar indicadores de posição de reprodução em listas</string>
<string name="enable_playback_state_lists_title">Posições em listas</string>
<string name="enable_playback_state_lists_summary">Mostrar indicadores de posição de reprodução nas listas</string>
<string name="settings_category_clear_data_title">Limpar dados</string>
<string name="watch_history_states_deleted">Posições de reprodução removidas</string>
<string name="missing_file">Ficheiro movido ou eliminado</string>
@ -406,20 +406,20 @@
<string name="overwrite_failed">não é possível sobrescrever o ficheiro</string>
<string name="download_already_pending">Existe uma descarga pendente com este nome</string>
<string name="error_postprocessing_stopped">NewPipe foi fechado enquanto trabalhava no ficheiro</string>
<string name="error_insufficient_storage">Não há espaço livre no aparelho</string>
<string name="error_insufficient_storage">Não há espaço livre no dispositivo</string>
<string name="error_progress_lost">Progresso perdido, o ficheiro foi eliminado</string>
<string name="error_timeout">Ligação expirada</string>
<string name="confirm_prompt">Deseja limpar o histórico de descargas ou remover todos os ficheiros descarregados\?</string>
<string name="enable_queue_limit">Limitar fila de descargas</string>
<string name="enable_queue_limit_desc">Uma descarga será executada ao mesmo tempo</string>
<string name="enable_queue_limit_desc">Permitir apenas uma descarga de cada vez</string>
<string name="start_downloads">Iniciar transferências</string>
<string name="pause_downloads">Pausa nas transferências</string>
<string name="downloads_storage_ask_title">Perguntar para onde transferir</string>
<string name="downloads_storage_ask_summary">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</string>
<string name="downloads_storage_use_saf_title">Usar o seletor de pastas do sistema (SAF)</string>
<string name="downloads_storage_use_saf_title">Utilizar seletor de pastas do sistema (SAF)</string>
<string name="downloads_storage_use_saf_summary">\'Storage Access Framework\' permite transferências para um cartão SD externo</string>
<string name="clear_playback_states_title">Remover posições de reprodução</string>
<string name="clear_playback_states_title">Limpar posições de reprodução</string>
<string name="clear_playback_states_summary">Remove todas as posições de reprodução</string>
<string name="delete_playback_states_alert">Remover todas as posições de reprodução\?</string>
<string name="drawer_header_description">Alternar serviço, agora selecionado:</string>
@ -573,7 +573,7 @@
<string name="clear_cookie_title">Limpar cookies reCAPTCHA</string>
<string name="youtube_restricted_mode_enabled_summary">O YouTube fornece um \"Modo restrito\" que oculta o conteúdo destinado a adultos</string>
<string name="show_age_restricted_content_summary">Mostrar conteúdo possivelmente impróprio para crianças porque tem um limite de idade (como 18+)</string>
<string name="notification_colorize_summary">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)</string>
<string name="notification_colorize_summary">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)</string>
<string name="notification_colorize_title">Colorir notificação</string>
<string name="show_thumbnail_summary">Usar miniaturas no fundo do ecrã de bloqueio e em notificações</string>
<string name="show_thumbnail_title">Mostrar miniatura</string>
@ -605,8 +605,8 @@
<string name="night_theme_summary">Escolha o seu tema escuro favorito — %s</string>
<string name="download_has_started">Descarga iniciada</string>
<string name="select_night_theme_toast">Pode escolher o seu tema escuro favorito abaixo</string>
<string name="auto_device_theme_title">Automático (Tema do aparelho)</string>
<string name="night_theme_title">Tema Escuro</string>
<string name="auto_device_theme_title">Automático (Tema do dispositivo)</string>
<string name="night_theme_title">Tema escuro</string>
<string name="show_channel_details">Mostrar detalhes do canal</string>
<string name="disable_media_tunneling_summary">Desative esta opção se estiverem a ocorrer erros de ecrã escuro ou paragens durante a reprodução</string>
<string name="disable_media_tunneling_title">Desativar túnel multimédia</string>
@ -622,8 +622,8 @@
<string name="feed_load_error_account_info">Não foi possível carregar o feed para \'%s\'.</string>
<string name="feed_load_error">Erro ao carregar o feed</string>
<string name="downloads_storage_use_saf_summary_api_29">A partir do Android 10, apenas o \'Storage Access Framework\' é compatível</string>
<string name="downloads_storage_use_saf_summary_api_19">O \'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores</string>
<string name="seekbar_preview_thumbnail_title">Pré-visualização da miniatura da barra de busca</string>
<string name="downloads_storage_use_saf_summary_api_19">\'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores</string>
<string name="seekbar_preview_thumbnail_title">Pré-visualização da miniatura da barra de pesquisa</string>
<string name="mark_as_watched">Marcar como visto</string>
<string name="off">Desligado</string>
<string name="on">Ligado</string>
@ -665,8 +665,8 @@
<item quantity="other">%s descargas concluídas</item>
</plurals>
<string name="main_page_content_swipe_remove">Deslizar itens para removê-los</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Iniciar o reprodutor principal em ecrã cheio</string>
<string name="start_main_player_fullscreen_summary">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.</string>
<string name="start_main_player_fullscreen_title">Iniciar reprodutor principal em ecrã completo</string>
<string name="enqueued_next">Enfileirado o próximo</string>
<string name="enqueue_next_stream">Enfileirar o próximo</string>
</resources>

File diff suppressed because it is too large Load Diff

View File

@ -238,7 +238,7 @@
<string name="error_occurred_detail">Произошла ошибка: %1$s</string>
<string name="detail_drag_description">Перетащите, чтобы изменить порядок</string>
<string name="create">Создать</string>
<string name="dismiss">Отклонить</string>
<string name="dismiss">Скрыть</string>
<string name="rename">Переименовать</string>
<string name="title_last_played">Недавно проигранные</string>
<string name="title_most_played">Часто проигрываемые</string>
@ -664,7 +664,7 @@
<string name="mark_as_watched">Пометить как проигранные</string>
<string name="error_show_channel_details">Не удалось отобразить сведения о канале</string>
<string name="loading_channel_details">Загрузка сведений о канале…</string>
<string name="show_image_indicators_summary">Picasso: указать цветом источник изображений (красный - сеть, синий - диск, зелёный - память)</string>
<string name="show_image_indicators_summary">Picasso: указать цветом источник изображений (красный — сеть, синий — диск, зелёный — память)</string>
<string name="show_image_indicators_title">Цветные метки на изображениях</string>
<string name="remote_search_suggestions">Серверные предложения поиска</string>
<string name="local_search_suggestions">Локальные предложения поиска</string>
@ -683,4 +683,6 @@
<string name="main_page_content_swipe_remove">Удалять элементы смахиванием</string>
<string name="start_main_player_fullscreen_summary">Запускать видео во весь экран, если отключён автоповорот. Мини-плеер доступен при выходе из полноэкранного режима</string>
<string name="start_main_player_fullscreen_title">Начинать просмотр в полноэкранном режиме</string>
<string name="enqueued_next">Добавлено следующим</string>
<string name="enqueue_next_stream">Добавить следующим</string>
</resources>

View File

@ -667,4 +667,6 @@
<string name="main_page_content_swipe_remove">Trìsina sos elementos pro los bogare</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Allughe su letore printzipale a ischermu intreu</string>
<string name="enqueued_next">Postu in lista comente imbeniente</string>
<string name="enqueue_next_stream">Pone in lista comente imbeniente</string>
</resources>

View File

@ -667,4 +667,6 @@
<string name="main_page_content_swipe_remove">Ögeleri kaldırmak için kaydır</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Ana oynatıcıyı tam ekranda başlat</string>
<string name="enqueue_next_stream">Sonrakini sıraya ekle</string>
<string name="enqueued_next">Sonraki sıraya eklendi</string>
</resources>

View File

@ -654,4 +654,6 @@
<string name="main_page_content_swipe_remove">Vuốt các mục để xóa chúng</string>
<string name="start_main_player_fullscreen_summary">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</string>
<string name="start_main_player_fullscreen_title">Khởi động trình phát chính ở toàn màn hình</string>
<string name="enqueued_next">Đã cho mục tiếp vào hàng đợi</string>
<string name="enqueue_next_stream">Cho mục tiếp vào hàng đợi</string>
</resources>

View File

@ -655,4 +655,6 @@
<string name="main_page_content_swipe_remove">滑動項目以刪除它們</string>
<string name="start_main_player_fullscreen_summary">如果自動旋轉被鎖定,請不要在迷你播放器中啟動影片,而是直接切換到全螢幕模式。您仍然可以透過結束全螢幕存取迷你播放器</string>
<string name="start_main_player_fullscreen_title">以全螢幕開始主播放器</string>
<string name="enqueued_next">已將下一個加入佇列</string>
<string name="enqueue_next_stream">將下一個加入佇列</string>
</resources>

View File

@ -416,6 +416,8 @@
<string name="show_channel_details">Show channel details</string>
<string name="enqueue_stream">Enqueue</string>
<string name="enqueued">Enqueued</string>
<string name="enqueue_next_stream">Enqueue next</string>
<string name="enqueued_next">Enqueued next</string>
<string name="start_here_on_background">Start playing in the background</string>
<string name="start_here_on_popup">Start playing in a popup</string>
<!-- Drawer -->
@ -701,4 +703,4 @@
<!-- Show Channel Details -->
<string name="error_show_channel_details">Error at Show Channel Details</string>
<string name="loading_channel_details">Loading Channel Details…</string>
</resources>
</resources>

View File

@ -16,7 +16,6 @@
<item name="actionColor">@color/white</item>
<item name="floatingActionButtonStyle">@style/FloatingActionButtonTheme</item>
<item name="toolbarSearchColor">@color/white</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="colorControlActivated">?attr/colorPrimary</item>
</style>
<style name="Base" parent="Base.V19"/>

View File

@ -8,7 +8,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.2'
classpath 'com.android.tools.build:gradle:7.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong

14
doc/gradle.md Normal file
View File

@ -0,0 +1,14 @@
# Custom gradle parameters
You can use these parameters by specifying them inside the `gradle.properties` file as
`systemProp.<name>=<value>` or passing them through the CLI with `-D<name>=<value>`.
## packageSuffix
This allows you to specify a suffix, which will be added on release builds to the application id,
the `app_name` string and the apk file.
No validation is made, so make sure to pass in a valid value.
## skipFormatKtlint
This allows you to skip the `formatKtLint` task.
No value is needed.
It is used for CI in order to check for badly formatted files.

View File

@ -0,0 +1,10 @@
• Added a "play next" button to the long press menu
• Added YouTube shorts path prefix to intent filter
• Fixed Settings import
• Swap seekbar position with player buttons in Queue screen
• Various fixes related to MediasessionManager
• Fixed seekbar not completed after video end
• Disabled media tunneling on RealtekATV
• Expanded minimized player buttons clickable area
To see further changes, view the changelog (and blog post) from the Links tab below.

Some files were not shown because too many files have changed in this diff Show More