mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-23 09:20:51 +02:00
Compare commits
80 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
600e156c4c | ||
![]() |
464d0e50b0 | ||
![]() |
7411c54f9e | ||
![]() |
7c74deb700 | ||
![]() |
e63165e80f | ||
![]() |
e2bc9dfacd | ||
![]() |
48789dbab7 | ||
![]() |
196f0f0475 | ||
![]() |
085b59f2e1 | ||
![]() |
2fdc2664ff | ||
![]() |
a33a5c5527 | ||
![]() |
a7c0f37904 | ||
![]() |
4889ab3462 | ||
![]() |
3923deeaad | ||
![]() |
80d6fff0ca | ||
![]() |
fe43b4da39 | ||
![]() |
67afd05e22 | ||
![]() |
0fcaf20221 | ||
![]() |
0277b94b37 | ||
![]() |
c7efa8c4f1 | ||
![]() |
bf6645e829 | ||
![]() |
ea1b42510c | ||
![]() |
72818ffa42 | ||
![]() |
985308bf0c | ||
![]() |
86381696f4 | ||
![]() |
08b960cc6e | ||
![]() |
731c65cd59 | ||
![]() |
a85e8a29ff | ||
![]() |
22b2f52f8c | ||
![]() |
a713ce2126 | ||
![]() |
4fac3cf304 | ||
![]() |
74e20a8c52 | ||
![]() |
8cf4ba25f5 | ||
![]() |
feb65cf8f3 | ||
![]() |
93592d23f4 | ||
![]() |
338a4837bc | ||
![]() |
8e19fe535c | ||
![]() |
2aeccc0c5c | ||
![]() |
8db1234a59 | ||
![]() |
80fb351ad3 | ||
![]() |
523f85d4d1 | ||
![]() |
bfff500915 | ||
![]() |
3e83bb0d95 | ||
![]() |
bdaee25e61 | ||
![]() |
71d3227791 | ||
![]() |
a28aa6a8c4 | ||
![]() |
292e103073 | ||
![]() |
39a3f03e79 | ||
![]() |
404a6c12a6 | ||
![]() |
8271409afe | ||
![]() |
985f659026 | ||
![]() |
7c36cbffd0 | ||
![]() |
285ea4e3fd | ||
![]() |
8ce18647f1 | ||
![]() |
aee0478235 | ||
![]() |
c3cf1d81c2 | ||
![]() |
c2b6cec37d | ||
![]() |
b265cabc22 | ||
![]() |
463dd8ea74 | ||
![]() |
0263125e11 | ||
![]() |
1fc8e4c148 | ||
![]() |
c43bca6007 | ||
![]() |
4c31636d19 | ||
![]() |
3a61ab59f2 | ||
![]() |
1db3c57ef0 | ||
![]() |
eeaf3496d5 | ||
![]() |
70f421b787 | ||
![]() |
86fa629591 | ||
![]() |
553b80164b | ||
![]() |
8518933ca8 | ||
![]() |
ea53b7d4ad | ||
![]() |
37a96d063f | ||
![]() |
b360920472 | ||
![]() |
9e1744f904 | ||
![]() |
85a468bda9 | ||
![]() |
b236bb407b | ||
![]() |
8978187c64 | ||
![]() |
eba0b07782 | ||
![]() |
80161c36c6 | ||
![]() |
aea912f499 |
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1 +1,8 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: 💬 IRC
|
||||||
|
url: https://webchat.freenode.net/#newpipe
|
||||||
|
about: Chat with us via IRC for quick Q/A
|
||||||
|
- name: 💬 Matrix
|
||||||
|
url: https://matrix.to/#/#freenode_#newpipe:matrix.org
|
||||||
|
about: Chat with us via Matrix for quick Q/A
|
||||||
|
40
.github/workflows/ci.yml
vendored
40
.github/workflows/ci.yml
vendored
@@ -1,6 +1,13 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-test:
|
build-and-test:
|
||||||
@@ -33,3 +40,34 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: app
|
name: app
|
||||||
path: app/build/outputs/apk/debug/*.apk
|
path: app/build/outputs/apk/debug/*.apk
|
||||||
|
# sonar:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v2
|
||||||
|
# with:
|
||||||
|
# fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
|
|
||||||
|
# - name: Set up JDK 11
|
||||||
|
# uses: actions/setup-java@v1.4.3
|
||||||
|
# with:
|
||||||
|
# java-version: 11 # Sonar requires JDK 11
|
||||||
|
|
||||||
|
# - name: Cache SonarCloud packages
|
||||||
|
# uses: actions/cache@v2
|
||||||
|
# with:
|
||||||
|
# path: ~/.sonar/cache
|
||||||
|
# key: ${{ runner.os }}-sonar
|
||||||
|
# restore-keys: ${{ runner.os }}-sonar
|
||||||
|
|
||||||
|
# - name: Cache Gradle packages
|
||||||
|
# uses: actions/cache@v2
|
||||||
|
# with:
|
||||||
|
# path: ~/.gradle/caches
|
||||||
|
# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
|
||||||
|
# restore-keys: ${{ runner.os }}-gradle
|
||||||
|
|
||||||
|
# - name: Build and analyze
|
||||||
|
# env:
|
||||||
|
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
||||||
|
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
# run: ./gradlew build sonarqube --info
|
||||||
|
140
README.es.md
Normal file
140
README.es.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
<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>
|
||||||
|
|
||||||
|
<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://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="http://webchat.freenode.net/?channels=%23newpipe" 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>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p align="center"><a href="#capturas-de-pantalla">Capturas de pantalla</a> • <a href="#descripción">Descripción</a> • <a href="#características">Características</a> • <a href="#installación-y-actualizaciones">Installación y actualizaciones</a> • <a href="#contribución">Contribución</a> • <a href="#donar">Donar</a> • <a href="#licencias">Licencias</a></p>
|
||||||
|
<p align="center"><a href="https://newpipe.net">Sitio web</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">Preguntas Frecuentes</a> • <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) .*
|
||||||
|
|
||||||
|
<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>COLOCAR NEWPIPE O CUALQUIER FORK (BIFURCACIÓN) REALIZADO DE ELLO EN GOOGLE PLAY STORE VIOLA SUS TÉRMINOS Y CONDICIONES.</b>
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_03.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_04.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_05.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_06.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_07.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_08.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_09.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png)
|
||||||
|
[<img src="fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png" width=405>](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png)
|
||||||
|
[<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.
|
||||||
|
|
||||||
|
### Características
|
||||||
|
* Buscar videos
|
||||||
|
* Mostrar información general sobre videos
|
||||||
|
* Mirar videos de YouTube
|
||||||
|
* Escuchar audio de YouTube
|
||||||
|
* Modo popup (reproductor flotante)
|
||||||
|
* Elegir reproductor para mirar el video
|
||||||
|
* Descargar videos
|
||||||
|
* Descargar solamente audio
|
||||||
|
* Abrir video en Kodi
|
||||||
|
* Mostrar videos próximos/relacionados
|
||||||
|
* Buscar a través de YouTube en un idioma específico
|
||||||
|
* Mirar/Bloquear materiales restringidas por edad.
|
||||||
|
* Mostrar información general sobre canales
|
||||||
|
* Buscar 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
|
||||||
|
* Subtítulos
|
||||||
|
* Apoyo de medios en directo
|
||||||
|
* 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:
|
||||||
|
|
||||||
|
* YouTube
|
||||||
|
* SoundCloud \[beta\]
|
||||||
|
* media.ccc.de \[beta\]
|
||||||
|
* PeerTube instances \[beta\]
|
||||||
|
* Bandcamp \[beta\]
|
||||||
|
|
||||||
|
<!-- Brecha escondida para mantener compatibles los enlaces viejos. -->
|
||||||
|
<span id="actualizaciones"></span>
|
||||||
|
|
||||||
|
## 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.schabi.org/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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## 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 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" />
|
||||||
|
</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).
|
||||||
|
|
||||||
|
<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><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>
|
||||||
|
</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>
|
||||||
|
</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/).
|
||||||
|
|
||||||
|
## Licencia
|
||||||
|
[](http://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.
|
@@ -2,8 +2,7 @@
|
|||||||
<h2 align="center"><b>NewPipe</b></h2>
|
<h2 align="center"><b>NewPipe</b></h2>
|
||||||
<h4 align="center">自由で軽量な Android 向けストリーミングフロントエンド</h4>
|
<h4 align="center">自由で軽量な Android 向けストリーミングフロントエンド</h4>
|
||||||
|
|
||||||
<!-- F-Droid is extremely out of date, so we hide this for now. -->
|
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-ja.svg"></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-ja.svg"></a></p> -->
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub リリース"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg"></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub リリース"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg"></a>
|
||||||
@@ -18,7 +17,7 @@
|
|||||||
<p align="center"><a href="https://newpipe.net">ウェブサイト</a> • <a href="https://newpipe.net/blog/">ブログ</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">ニュース</a></p>
|
<p align="center"><a href="https://newpipe.net">ウェブサイト</a> • <a href="https://newpipe.net/blog/">ブログ</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">ニュース</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
*他の言語で読む: [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) 。*
|
*他の言語で読む: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt.br.md), [日本語](README.ja.md), [Română](README.ro.md) 。*
|
||||||
|
|
||||||
<b>注意: これはベータ版のため、バグが発生する可能性があります。もしバグが発生した場合、GitHub のリポジトリで Issue を開いてください。</b>
|
<b>注意: これはベータ版のため、バグが発生する可能性があります。もしバグが発生した場合、GitHub のリポジトリで Issue を開いてください。</b>
|
||||||
|
|
||||||
@@ -84,6 +83,7 @@ NewPipe は複数のサービスに対応しています。[ドキュメント](
|
|||||||
* SoundCloud \[ベータ\]
|
* SoundCloud \[ベータ\]
|
||||||
* media.ccc.de \[ベータ\]
|
* media.ccc.de \[ベータ\]
|
||||||
* PeerTube インスタンス \[ベータ\]
|
* PeerTube インスタンス \[ベータ\]
|
||||||
|
* Bandcamp \[ベータ\]
|
||||||
|
|
||||||
<!-- Hidden span to keep old links compatible. -->
|
<!-- Hidden span to keep old links compatible. -->
|
||||||
<span id="updates"></span>
|
<span id="updates"></span>
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
<p align="center"><a href="https://newpipe.net"><img src="assets/new_pipe_icon_5.png" width="150"></a></p>
|
<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>
|
<h2 align="center"><b>NewPipe</b></h2>
|
||||||
<h4 align="center">A libre lightweight streaming frontend for Android.</h4>
|
<h4 align="center">A libre lightweight streaming frontend for 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-ko.svg"></a></p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
<p align="center"><a href="https://newpipe.net">Website</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Press</a></p>
|
<p align="center"><a href="https://newpipe.net">Website</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Press</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
*Read this in other languages: [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).*
|
*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md).*
|
||||||
|
|
||||||
<b>경고: 이 버전은 베타 버전이므로, 버그가 발생할 수도 있습니다. 만약 버그가 발생하였다면, 우리의 GITHUB 저장소에서 ISSUE를 열람하여 주십시오.</b>
|
<b>경고: 이 버전은 베타 버전이므로, 버그가 발생할 수도 있습니다. 만약 버그가 발생하였다면, 우리의 GITHUB 저장소에서 ISSUE를 열람하여 주십시오.</b>
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@ NewPipe는 여러가지 서비스를 지원합니다. 우리의 [문서](https:/
|
|||||||
* SoundCloud \[beta\]
|
* SoundCloud \[beta\]
|
||||||
* media.ccc.de \[beta\]
|
* media.ccc.de \[beta\]
|
||||||
* PeerTube instances \[beta\]
|
* PeerTube instances \[beta\]
|
||||||
|
* Bandcamp \[beta\]
|
||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로 인해), 결국 릴리즈가 발생할 것입니다. 이것들의 형식은 x.xx.x 입니다.
|
NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로 인해), 결국 릴리즈가 발생할 것입니다. 이것들의 형식은 x.xx.x 입니다.
|
||||||
|
@@ -2,8 +2,7 @@
|
|||||||
<h2 align="center"><b>NewPipe</b></h2>
|
<h2 align="center"><b>NewPipe</b></h2>
|
||||||
<h4 align="center">A libre lightweight streaming frontend for Android.</h4>
|
<h4 align="center">A libre lightweight streaming frontend for Android.</h4>
|
||||||
|
|
||||||
<!-- F-Droid is extremely out of date, so we hide this for now. -->
|
<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://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png"></a></p> -->
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
||||||
@@ -18,7 +17,7 @@
|
|||||||
<p align="center"><a href="https://newpipe.net">Website</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Press</a></p>
|
<p align="center"><a href="https://newpipe.net">Website</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Press</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
*Read this in other languages: [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) .*
|
*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md) .*
|
||||||
|
|
||||||
<b>WARNING: THIS IS A BETA VERSION, THEREFORE YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE VIA OUR GITHUB REPOSITORY.</b>
|
<b>WARNING: THIS IS A BETA VERSION, THEREFORE YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE VIA OUR GITHUB REPOSITORY.</b>
|
||||||
|
|
||||||
@@ -81,6 +80,7 @@ NewPipe supports multiple services. Our [docs](https://teamnewpipe.github.io/doc
|
|||||||
* SoundCloud \[beta\]
|
* SoundCloud \[beta\]
|
||||||
* media.ccc.de \[beta\]
|
* media.ccc.de \[beta\]
|
||||||
* PeerTube instances \[beta\]
|
* PeerTube instances \[beta\]
|
||||||
|
* Bandcamp \[beta\]
|
||||||
|
|
||||||
<!-- Hidden span to keep old links compatible. -->
|
<!-- Hidden span to keep old links compatible. -->
|
||||||
<span id="updates"></span>
|
<span id="updates"></span>
|
||||||
@@ -89,7 +89,7 @@ NewPipe supports multiple services. Our [docs](https://teamnewpipe.github.io/doc
|
|||||||
You can install NewPipe using one of the following methods:
|
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.schabi.org/FAQ/tutorials/install-add-fdroid-repo/
|
1. Add our custom repo to F-Droid and install it from there. The instructions are here: https://newpipe.schabi.org/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. (**IMPORTANT**: as of the time of writing, an issue is preventing releases later than 0.20.1 from being published. Thus, till this issue is solved, if you want to use F-Droid, we recommend method 1.)
|
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.
|
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.
|
||||||
|
|
||||||
We recommend method 1 for most users. APKs installed using method 1 or 2 are compatible with each other, but not with those installed using method 3. This is due to the same signing key (ours) being used for 1 and 2, but a different signing key (F-Droid's) being used for 3. Building a debug APK using method 4 excludes a key entirely. Signing keys help ensure that a user isn't tricked into installing a malicious update to an app.
|
We recommend method 1 for most users. APKs installed using method 1 or 2 are compatible with each other, but not with those installed using method 3. This is due to the same signing key (ours) being used for 1 and 2, but a different signing key (F-Droid's) being used for 3. Building a debug APK using method 4 excludes a key entirely. Signing keys help ensure that a user isn't tricked into installing a malicious update to an app.
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
<p align="center"><a href="https://newpipe.net"><img src="assets/new_pipe_icon_5.png" width="150"></a></p>
|
<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>
|
<h2 align="center"><b>NewPipe</b></h2>
|
||||||
<h4 align="center">Uma interface de streaming leve e gratuita para Android.</h4>
|
<h4 align="center">Uma interface de streaming leve e gratuita 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-pt-br.svg"></a></p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
||||||
@@ -16,7 +18,7 @@
|
|||||||
<p align="center"><a href="https://newpipe.net">Site</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Press</a></p>
|
<p align="center"><a href="https://newpipe.net">Site</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Press</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
*Read this in other languages: [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).*
|
*Read this in other languages: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md).*
|
||||||
|
|
||||||
<b>AVISO: ESTA É UMA VERSÃO BETA, PORTANTO, VOCÊ PODE ENCONTRAR BUGS. ENCONTROU ALGUM, ABRA UM ISSUE ATRAVÉS DO NOSSO REPOSITÓRIO GITHUB.</b>
|
<b>AVISO: ESTA É UMA VERSÃO BETA, PORTANTO, VOCÊ PODE ENCONTRAR BUGS. ENCONTROU ALGUM, ABRA UM ISSUE ATRAVÉS DO NOSSO REPOSITÓRIO GITHUB.</b>
|
||||||
|
|
||||||
@@ -79,6 +81,7 @@ O NewPipe suporta vários serviços. Nosso [documentação](https://teamnewpipe.
|
|||||||
* SoundCloud \[beta\]
|
* SoundCloud \[beta\]
|
||||||
* media.ccc.de \[beta\]
|
* media.ccc.de \[beta\]
|
||||||
* PeerTube instances \[beta\]
|
* PeerTube instances \[beta\]
|
||||||
|
* Bandcamp \[beta\]
|
||||||
|
|
||||||
## Atualizações
|
## Atualizações
|
||||||
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:
|
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:
|
||||||
|
@@ -2,8 +2,7 @@
|
|||||||
<h2 align="center"><b>NewPipe</b></h2>
|
<h2 align="center"><b>NewPipe</b></h2>
|
||||||
<h4 align="center">Un front-end de streaming „uşor” liber, pentru Android.</h4>
|
<h4 align="center">Un front-end de streaming „uşor” liber, pentru Android.</h4>
|
||||||
|
|
||||||
<!-- F-Droid is extremely out of date, so we hide this for now. -->
|
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-ro.svg"></a></p>
|
||||||
<!-- <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">
|
<p align="center">
|
||||||
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
||||||
@@ -18,7 +17,7 @@
|
|||||||
<p align="center"><a href="https://newpipe.net">Website</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Presă</a></p>
|
<p align="center"><a href="https://newpipe.net">Website</a> • <a href="https://newpipe.net/blog/">Blog</a> • <a href="https://newpipe.net/FAQ/">FAQ</a> • <a href="https://newpipe.net/press/">Presă</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
*Citiţi în alte limbi: [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)*
|
*Citiţi în alte limbi: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md)*
|
||||||
|
|
||||||
<b>Atenţionare: ACEASTA ESTE O VERSIUNE BETA, AŞA CĂ S-AR PUTE SĂ ÎNTÂLNIŢI ERORI. DACĂ SE ÎNTÂMPLĂ ACEST LUCRU, DESCHIDEŢI UN ISSUE PRIN REPSITORY-UL NOSTRU GITHUB.</b>
|
<b>Atenţionare: ACEASTA ESTE O VERSIUNE BETA, AŞA CĂ S-AR PUTE SĂ ÎNTÂLNIŢI ERORI. DACĂ SE ÎNTÂMPLĂ ACEST LUCRU, DESCHIDEŢI UN ISSUE PRIN REPSITORY-UL NOSTRU GITHUB.</b>
|
||||||
|
|
||||||
@@ -81,6 +80,7 @@ NewPipe suportă servicii multiple. [Documentele](https://teamnewpipe.github.io/
|
|||||||
* SoundCloud \[beta\]
|
* SoundCloud \[beta\]
|
||||||
* media.ccc.de \[beta\]
|
* media.ccc.de \[beta\]
|
||||||
* Instanţe PeerTube \[beta\]
|
* Instanţe PeerTube \[beta\]
|
||||||
|
* Bandcamp \[beta\]
|
||||||
|
|
||||||
<!-- Hidden span to keep old links compatible. -->
|
<!-- Hidden span to keep old links compatible. -->
|
||||||
<span id="updates"></span>
|
<span id="updates"></span>
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
<p align="center"><a href="https://newpipe.net"><img src="assets/new_pipe_icon_5.png" width="150"></a></p>
|
<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>
|
<h2 align="center"><b>NewPipe</b></h2>
|
||||||
<h4 align="center">App bilaash ah oo fudud looguna talagalay in Android-ka wax loogu daawado.</h4>
|
<h4 align="center">App bilaash ah oo fudud looguna talagalay in Android-ka wax loogu daawado.</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-so.svg"></a></p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="Siidaynta GitHub "><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="Siidaynta GitHub "><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
||||||
@@ -16,7 +17,7 @@
|
|||||||
<p align="center"><a href="https://newpipe.net">Website-ka</a> • <a href="https://newpipe.net/blog/">Maqaalada</a> • <a href="https://newpipe.net/FAQ/">Su'aalaha Aalaa La-iswaydiiyo</a> • <a href="https://newpipe.net/press/">Warbaahinta</a></p>
|
<p align="center"><a href="https://newpipe.net">Website-ka</a> • <a href="https://newpipe.net/blog/">Maqaalada</a> • <a href="https://newpipe.net/FAQ/">Su'aalaha Aalaa La-iswaydiiyo</a> • <a href="https://newpipe.net/press/">Warbaahinta</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
*Ku akhri luuqad kale: [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).*
|
*Ku akhri luuqad kale: [English](README.md), [Español](README.es.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md).*
|
||||||
|
|
||||||
<b>DIGNIIN: MIDKAN, NOOCA APP-KA EE HADDA WALI TIJAABO AYUU KU JIRAA, SIDAA DARTEED CILLADO AYAAD LA KULMI KARTAA. HADAAD LA KULANTO, KA FUR ARIN SHARAXAYA QAYBTANADA ARRIMAHA EE GITHUB-KA.</b>
|
<b>DIGNIIN: MIDKAN, NOOCA APP-KA EE HADDA WALI TIJAABO AYUU KU JIRAA, SIDAA DARTEED CILLADO AYAAD LA KULMI KARTAA. HADAAD LA KULANTO, KA FUR ARIN SHARAXAYA QAYBTANADA ARRIMAHA EE GITHUB-KA.</b>
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@ NewPipe wuxuu taageeraa adeegyo badan. [warqadan](https://teamnewpipe.github.io/
|
|||||||
* SoundCloud \[tijaabo\]
|
* SoundCloud \[tijaabo\]
|
||||||
* media.ccc.de \[tijaabo\]
|
* media.ccc.de \[tijaabo\]
|
||||||
* PeerTube instances \[tijaabo\]
|
* PeerTube instances \[tijaabo\]
|
||||||
|
* Bandcamp \[tijaabo\]
|
||||||
|
|
||||||
## Kushubida iyo cusboonaysiinta
|
## Kushubida iyo cusboonaysiinta
|
||||||
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:
|
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,3 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
id "org.sonarqube" version "3.1.1"
|
||||||
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
apply plugin: 'kotlin-android-extensions'
|
||||||
@@ -13,8 +17,8 @@ android {
|
|||||||
resValue "string", "app_name", "NewPipe"
|
resValue "string", "app_name", "NewPipe"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 965
|
versionCode 967
|
||||||
versionName "0.20.11"
|
versionName "0.21.1"
|
||||||
|
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
@@ -96,7 +100,7 @@ ext {
|
|||||||
checkstyleVersion = '8.38'
|
checkstyleVersion = '8.38'
|
||||||
stethoVersion = '1.5.1'
|
stethoVersion = '1.5.1'
|
||||||
leakCanaryVersion = '2.5'
|
leakCanaryVersion = '2.5'
|
||||||
exoPlayerVersion = '2.11.8'
|
exoPlayerVersion = '2.12.3'
|
||||||
androidxLifecycleVersion = '2.2.0'
|
androidxLifecycleVersion = '2.2.0'
|
||||||
androidxRoomVersion = '2.3.0-alpha03'
|
androidxRoomVersion = '2.3.0-alpha03'
|
||||||
groupieVersion = '2.8.1'
|
groupieVersion = '2.8.1'
|
||||||
@@ -111,7 +115,7 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkstyle {
|
checkstyle {
|
||||||
configFile rootProject.file('checkstyle.xml')
|
configDir rootProject.file(".")
|
||||||
ignoreFailures false
|
ignoreFailures false
|
||||||
showViolations true
|
showViolations true
|
||||||
toolVersion = checkstyleVersion
|
toolVersion = checkstyleVersion
|
||||||
@@ -158,6 +162,14 @@ afterEvaluate {
|
|||||||
preDebugBuild.dependsOn formatKtlint, runCheckstyle, runKtlint
|
preDebugBuild.dependsOn formatKtlint, runCheckstyle, runKtlint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sonarqube {
|
||||||
|
properties {
|
||||||
|
property "sonar.projectKey", "TeamNewPipe_NewPipe"
|
||||||
|
property "sonar.organization", "teamnewpipe"
|
||||||
|
property "sonar.host.url", "https://sonarcloud.io"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
|
||||||
|
|
||||||
@@ -180,7 +192,7 @@ dependencies {
|
|||||||
|
|
||||||
// NewPipe dependencies
|
// NewPipe dependencies
|
||||||
// You can use a local version by uncommenting a few lines in settings.gradle
|
// You can use a local version by uncommenting a few lines in settings.gradle
|
||||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.20.11'
|
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.1'
|
||||||
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
|
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
|
||||||
|
|
||||||
implementation "org.jsoup:jsoup:1.13.1"
|
implementation "org.jsoup:jsoup:1.13.1"
|
||||||
@@ -233,7 +245,7 @@ dependencies {
|
|||||||
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
|
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
|
||||||
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
|
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
|
||||||
|
|
||||||
implementation "org.ocpsoft.prettytime:prettytime:4.0.6.Final"
|
implementation "org.ocpsoft.prettytime:prettytime:5.0.0.Final"
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.1'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
|
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
package org.schabi.newpipe.error;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.LargeTest;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented tests for {@link ErrorInfo}.
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@LargeTest
|
||||||
|
public class ErrorInfoTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void errorInfoTestParcelable() {
|
||||||
|
final ErrorInfo info = new ErrorInfo(new ParsingException("Hello"),
|
||||||
|
UserAction.USER_REPORT, "request", ServiceList.YouTube.getServiceId());
|
||||||
|
// Obtain a Parcel object and write the parcelable object to it:
|
||||||
|
final Parcel parcel = Parcel.obtain();
|
||||||
|
info.writeToParcel(parcel, 0);
|
||||||
|
parcel.setDataPosition(0);
|
||||||
|
final ErrorInfo infoFromParcel = (ErrorInfo) ErrorInfo.CREATOR.createFromParcel(parcel);
|
||||||
|
|
||||||
|
assertTrue(Arrays.toString(infoFromParcel.getStackTraces())
|
||||||
|
.contains(ErrorInfoTest.class.getSimpleName()));
|
||||||
|
assertEquals(UserAction.USER_REPORT, infoFromParcel.getUserAction());
|
||||||
|
assertEquals(ServiceList.YouTube.getServiceInfo().getName(),
|
||||||
|
infoFromParcel.getServiceName());
|
||||||
|
assertEquals("request", infoFromParcel.getRequest());
|
||||||
|
assertEquals(R.string.parsing_error, infoFromParcel.getMessageStringId());
|
||||||
|
|
||||||
|
parcel.recycle();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,38 +0,0 @@
|
|||||||
package org.schabi.newpipe.report;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
import androidx.test.filters.LargeTest;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.schabi.newpipe.R;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented tests for {@link ErrorInfo}.
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
@LargeTest
|
|
||||||
public class ErrorInfoTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void errorInfoTestParcelable() {
|
|
||||||
final ErrorInfo info = ErrorInfo.make(UserAction.USER_REPORT, "youtube", "request",
|
|
||||||
R.string.general_error);
|
|
||||||
// Obtain a Parcel object and write the parcelable object to it:
|
|
||||||
final Parcel parcel = Parcel.obtain();
|
|
||||||
info.writeToParcel(parcel, 0);
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
final ErrorInfo infoFromParcel = ErrorInfo.CREATOR.createFromParcel(parcel);
|
|
||||||
|
|
||||||
assertEquals(UserAction.USER_REPORT, infoFromParcel.getUserAction());
|
|
||||||
assertEquals("youtube", infoFromParcel.getServiceName());
|
|
||||||
assertEquals("request", infoFromParcel.getRequest());
|
|
||||||
assertEquals(R.string.general_error, infoFromParcel.getMessage());
|
|
||||||
|
|
||||||
parcel.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -85,7 +85,7 @@
|
|||||||
android:name=".ExitActivity"
|
android:name=".ExitActivity"
|
||||||
android:label="@string/general_error"
|
android:label="@string/general_error"
|
||||||
android:theme="@android:style/Theme.NoDisplay" />
|
android:theme="@android:style/Theme.NoDisplay" />
|
||||||
<activity android:name=".report.ErrorActivity" />
|
<activity android:name=".error.ErrorActivity" />
|
||||||
|
|
||||||
<!-- giga get related -->
|
<!-- giga get related -->
|
||||||
<activity
|
<activity
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ReCaptchaActivity"
|
android:name=".error.ReCaptchaActivity"
|
||||||
android:label="@string/recaptcha" />
|
android:label="@string/recaptcha" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
@@ -317,6 +317,22 @@
|
|||||||
<data android:pathPrefix="/accounts/" />
|
<data android:pathPrefix="/accounts/" />
|
||||||
<data android:pathPrefix="/video-channels/" />
|
<data android:pathPrefix="/video-channels/" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- Bandcamp filter -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
|
||||||
|
<data android:scheme="http"/>
|
||||||
|
<data android:scheme="https"/>
|
||||||
|
<data android:host="bandcamp.com"/>
|
||||||
|
<data android:host="*.bandcamp.com"/>
|
||||||
|
<data android:pathPrefix="/"/>
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<service
|
<service
|
||||||
android:name=".RouterActivity$FetcherService"
|
android:name=".RouterActivity$FetcherService"
|
||||||
|
@@ -1,47 +0,0 @@
|
|||||||
package org.schabi.newpipe;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Created by Christian Schabesberger on 24.12.15.
|
|
||||||
*
|
|
||||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
|
||||||
* ActivityCommunicator.java is part of NewPipe.
|
|
||||||
*
|
|
||||||
* NewPipe is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* NewPipe is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton:
|
|
||||||
* Used to send data between certain Activity/Services within the same process.
|
|
||||||
* This can be considered as an ugly hack inside the Android universe.
|
|
||||||
**/
|
|
||||||
public class ActivityCommunicator {
|
|
||||||
|
|
||||||
private static ActivityCommunicator activityCommunicator;
|
|
||||||
private volatile Class returnActivity;
|
|
||||||
|
|
||||||
public static ActivityCommunicator getCommunicator() {
|
|
||||||
if (activityCommunicator == null) {
|
|
||||||
activityCommunicator = new ActivityCommunicator();
|
|
||||||
}
|
|
||||||
return activityCommunicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class getReturnActivity() {
|
|
||||||
return returnActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReturnActivity(final Class returnActivity) {
|
|
||||||
this.returnActivity = returnActivity;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -20,12 +20,13 @@ import org.acra.ACRA;
|
|||||||
import org.acra.config.ACRAConfigurationException;
|
import org.acra.config.ACRAConfigurationException;
|
||||||
import org.acra.config.CoreConfiguration;
|
import org.acra.config.CoreConfiguration;
|
||||||
import org.acra.config.CoreConfigurationBuilder;
|
import org.acra.config.CoreConfigurationBuilder;
|
||||||
|
import org.schabi.newpipe.error.ErrorActivity;
|
||||||
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
|
import org.schabi.newpipe.error.ReCaptchaActivity;
|
||||||
|
import org.schabi.newpipe.error.UserAction;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.report.ErrorInfo;
|
|
||||||
import org.schabi.newpipe.report.UserAction;
|
|
||||||
import org.schabi.newpipe.settings.SettingsActivity;
|
import org.schabi.newpipe.settings.SettingsActivity;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.util.ServiceHelper;
|
import org.schabi.newpipe.util.ServiceHelper;
|
||||||
@@ -224,14 +225,10 @@ public class App extends MultiDexApplication {
|
|||||||
.setBuildConfigClass(BuildConfig.class)
|
.setBuildConfigClass(BuildConfig.class)
|
||||||
.build();
|
.build();
|
||||||
ACRA.init(this, acraConfig);
|
ACRA.init(this, acraConfig);
|
||||||
} catch (final ACRAConfigurationException ace) {
|
} catch (final ACRAConfigurationException exception) {
|
||||||
ace.printStackTrace();
|
exception.printStackTrace();
|
||||||
ErrorActivity.reportError(this,
|
ErrorActivity.reportError(this, new ErrorInfo(exception,
|
||||||
ace,
|
UserAction.SOMETHING_ELSE, "Could not initialize ACRA crash report"));
|
||||||
null,
|
|
||||||
null,
|
|
||||||
ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
|
||||||
"Could not initialize ACRA crash report", R.string.app_ui_crash));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,19 +10,22 @@ import android.content.pm.Signature;
|
|||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.rxjava3.core.Maybe;
|
import org.schabi.newpipe.error.ErrorActivity;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import org.schabi.newpipe.error.UserAction;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@@ -31,9 +34,11 @@ import java.security.cert.CertificateEncodingException;
|
|||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.report.ErrorInfo;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import io.reactivex.rxjava3.core.Maybe;
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
public final class CheckForNewAppVersion {
|
public final class CheckForNewAppVersion {
|
||||||
private CheckForNewAppVersion() { }
|
private CheckForNewAppVersion() { }
|
||||||
@@ -58,9 +63,8 @@ public final class CheckForNewAppVersion {
|
|||||||
packageInfo = application.getPackageManager().getPackageInfo(
|
packageInfo = application.getPackageManager().getPackageInfo(
|
||||||
application.getPackageName(), PackageManager.GET_SIGNATURES);
|
application.getPackageName(), PackageManager.GET_SIGNATURES);
|
||||||
} catch (final PackageManager.NameNotFoundException e) {
|
} catch (final PackageManager.NameNotFoundException e) {
|
||||||
ErrorActivity.reportError(application, e, null, null,
|
ErrorActivity.reportError(application, new ErrorInfo(e,
|
||||||
ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info"));
|
||||||
"Could not find package info", R.string.app_ui_crash));
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +76,8 @@ public final class CheckForNewAppVersion {
|
|||||||
final CertificateFactory cf = CertificateFactory.getInstance("X509");
|
final CertificateFactory cf = CertificateFactory.getInstance("X509");
|
||||||
c = (X509Certificate) cf.generateCertificate(input);
|
c = (X509Certificate) cf.generateCertificate(input);
|
||||||
} catch (final CertificateException e) {
|
} catch (final CertificateException e) {
|
||||||
ErrorActivity.reportError(application, e, null, null,
|
ErrorActivity.reportError(application, new ErrorInfo(e,
|
||||||
ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error"));
|
||||||
"Certificate error", R.string.app_ui_crash));
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,9 +86,8 @@ public final class CheckForNewAppVersion {
|
|||||||
final byte[] publicKey = md.digest(c.getEncoded());
|
final byte[] publicKey = md.digest(c.getEncoded());
|
||||||
return byte2HexFormatted(publicKey);
|
return byte2HexFormatted(publicKey);
|
||||||
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
|
||||||
ErrorActivity.reportError(application, e, null, null,
|
ErrorActivity.reportError(application, new ErrorInfo(e,
|
||||||
ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key"));
|
||||||
"Could not retrieve SHA1 key", R.string.app_ui_crash));
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.error.ReCaptchaActivity;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.extractor.downloader.Request;
|
import org.schabi.newpipe.extractor.downloader.Request;
|
||||||
import org.schabi.newpipe.extractor.downloader.Response;
|
import org.schabi.newpipe.extractor.downloader.Response;
|
||||||
@@ -43,7 +44,7 @@ import static org.schabi.newpipe.MainActivity.DEBUG;
|
|||||||
|
|
||||||
public final class DownloaderImpl extends Downloader {
|
public final class DownloaderImpl extends Downloader {
|
||||||
public static final String USER_AGENT
|
public static final String USER_AGENT
|
||||||
= "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0";
|
= "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0";
|
||||||
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE_KEY
|
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE_KEY
|
||||||
= "youtube_restricted_mode_key";
|
= "youtube_restricted_mode_key";
|
||||||
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE = "PREF=f2=8000000";
|
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE = "PREF=f2=8000000";
|
||||||
|
@@ -60,6 +60,7 @@ import org.schabi.newpipe.databinding.DrawerHeaderBinding;
|
|||||||
import org.schabi.newpipe.databinding.DrawerLayoutBinding;
|
import org.schabi.newpipe.databinding.DrawerLayoutBinding;
|
||||||
import org.schabi.newpipe.databinding.InstanceSpinnerLayoutBinding;
|
import org.schabi.newpipe.databinding.InstanceSpinnerLayoutBinding;
|
||||||
import org.schabi.newpipe.databinding.ToolbarLayoutBinding;
|
import org.schabi.newpipe.databinding.ToolbarLayoutBinding;
|
||||||
|
import org.schabi.newpipe.error.ErrorActivity;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
@@ -72,7 +73,6 @@ import org.schabi.newpipe.player.Player;
|
|||||||
import org.schabi.newpipe.player.event.OnKeyDownListener;
|
import org.schabi.newpipe.player.event.OnKeyDownListener;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHolder;
|
import org.schabi.newpipe.player.helper.PlayerHolder;
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.KioskTranslator;
|
import org.schabi.newpipe.util.KioskTranslator;
|
||||||
@@ -153,7 +153,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
try {
|
try {
|
||||||
setupDrawer();
|
setupDrawer();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiErrorInSnackbar(this, "Setting up drawer", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DeviceUtils.isTv(this)) {
|
if (DeviceUtils.isTv(this)) {
|
||||||
@@ -238,7 +238,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
try {
|
try {
|
||||||
tabSelected(item);
|
tabSelected(item);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiErrorInSnackbar(this, "Selecting main page tab", e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.menu_options_about_group:
|
case R.id.menu_options_about_group:
|
||||||
@@ -340,7 +340,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
try {
|
try {
|
||||||
showTabs();
|
showTabs();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiErrorInSnackbar(this, "Showing main page tabs", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,7 +487,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
drawerHeaderBinding.drawerHeaderActionButton.setContentDescription(
|
drawerHeaderBinding.drawerHeaderActionButton.setContentDescription(
|
||||||
getString(R.string.drawer_header_description) + selectedServiceName);
|
getString(R.string.drawer_header_description) + selectedServiceName);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiErrorInSnackbar(this, "Setting up service toggle", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
final SharedPreferences sharedPreferences
|
final SharedPreferences sharedPreferences
|
||||||
@@ -679,19 +679,16 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
|
Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
|
||||||
}
|
}
|
||||||
final int id = item.getItemId();
|
|
||||||
|
|
||||||
switch (id) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
case android.R.id.home:
|
onHomeButtonPressed();
|
||||||
onHomeButtonPressed();
|
return true;
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -799,7 +796,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
ErrorActivity.reportUiError(this, e);
|
ErrorActivity.reportUiErrorInSnackbar(this, "Handling intent", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,15 +33,29 @@ import androidx.preference.PreferenceManager;
|
|||||||
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
|
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
|
||||||
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
|
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
|
||||||
import org.schabi.newpipe.download.DownloadDialog;
|
import org.schabi.newpipe.download.DownloadDialog;
|
||||||
|
import org.schabi.newpipe.error.ErrorActivity;
|
||||||
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
|
import org.schabi.newpipe.error.ReCaptchaActivity;
|
||||||
|
import org.schabi.newpipe.error.UserAction;
|
||||||
import org.schabi.newpipe.extractor.Info;
|
import org.schabi.newpipe.extractor.Info;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.StreamingService.LinkType;
|
import org.schabi.newpipe.extractor.StreamingService.LinkType;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.PaidContentException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.PrivateContentException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||||
import org.schabi.newpipe.player.MainPlayer;
|
import org.schabi.newpipe.player.MainPlayer;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHolder;
|
import org.schabi.newpipe.player.helper.PlayerHolder;
|
||||||
@@ -49,7 +63,6 @@ import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
|||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
|
||||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
@@ -84,13 +97,6 @@ import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr;
|
|||||||
* Get the url from the intent and open it in the chosen preferred player.
|
* Get the url from the intent and open it in the chosen preferred player.
|
||||||
*/
|
*/
|
||||||
public class RouterActivity extends AppCompatActivity {
|
public class RouterActivity extends AppCompatActivity {
|
||||||
public static final String INTERNAL_ROUTE_KEY = "internalRoute";
|
|
||||||
/**
|
|
||||||
* Removes invisible separators (\p{Z}) and punctuation characters including
|
|
||||||
* brackets (\p{P}). See http://www.regular-expressions.info/unicode.html for
|
|
||||||
* more details.
|
|
||||||
*/
|
|
||||||
private static final String REGEX_REMOVE_FROM_URL = "[\\p{Z}\\p{P}]";
|
|
||||||
protected final CompositeDisposable disposables = new CompositeDisposable();
|
protected final CompositeDisposable disposables = new CompositeDisposable();
|
||||||
@State
|
@State
|
||||||
protected int currentServiceId = -1;
|
protected int currentServiceId = -1;
|
||||||
@@ -100,7 +106,6 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
protected int selectedRadioPosition = -1;
|
protected int selectedRadioPosition = -1;
|
||||||
protected int selectedPreviously = -1;
|
protected int selectedPreviously = -1;
|
||||||
protected String currentUrl;
|
protected String currentUrl;
|
||||||
protected boolean internalRoute = false;
|
|
||||||
private StreamingService currentService;
|
private StreamingService currentService;
|
||||||
private boolean selectionIsDownload = false;
|
private boolean selectionIsDownload = false;
|
||||||
|
|
||||||
@@ -123,7 +128,7 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(final Bundle outState) {
|
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
Icepick.saveInstanceState(this, outState);
|
Icepick.saveInstanceState(this, outState);
|
||||||
}
|
}
|
||||||
@@ -145,37 +150,79 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
private void handleUrl(final String url) {
|
private void handleUrl(final String url) {
|
||||||
disposables.add(Observable
|
disposables.add(Observable
|
||||||
.fromCallable(() -> {
|
.fromCallable(() -> {
|
||||||
if (currentServiceId == -1) {
|
try {
|
||||||
currentService = NewPipe.getServiceByUrl(url);
|
if (currentServiceId == -1) {
|
||||||
currentServiceId = currentService.getServiceId();
|
currentService = NewPipe.getServiceByUrl(url);
|
||||||
currentLinkType = currentService.getLinkTypeByUrl(url);
|
currentServiceId = currentService.getServiceId();
|
||||||
currentUrl = url;
|
currentLinkType = currentService.getLinkTypeByUrl(url);
|
||||||
} else {
|
currentUrl = url;
|
||||||
currentService = NewPipe.getService(currentServiceId);
|
} else {
|
||||||
}
|
currentService = NewPipe.getService(currentServiceId);
|
||||||
|
}
|
||||||
|
|
||||||
return currentLinkType != LinkType.NONE;
|
// return whether the url was found to be supported or not
|
||||||
|
return currentLinkType != LinkType.NONE;
|
||||||
|
} catch (final ExtractionException e) {
|
||||||
|
// this can be reached only when the url is completely unsupported
|
||||||
|
return false;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(result -> {
|
.subscribe(isUrlSupported -> {
|
||||||
if (result) {
|
if (isUrlSupported) {
|
||||||
onSuccess();
|
onSuccess();
|
||||||
} else {
|
} else {
|
||||||
showUnsupportedUrlDialog(url);
|
showUnsupportedUrlDialog(url);
|
||||||
}
|
}
|
||||||
}, throwable -> handleError(throwable, url)));
|
}, throwable -> handleError(this, new ErrorInfo(throwable,
|
||||||
|
UserAction.SHARE_TO_NEWPIPE, "Getting service from url: " + url))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleError(final Throwable throwable, final String url) {
|
/**
|
||||||
throwable.printStackTrace();
|
* @param context the context. It will be {@code finish()}ed at the end of the handling if it is
|
||||||
|
* an instance of {@link RouterActivity}.
|
||||||
|
* @param errorInfo the error information
|
||||||
|
*/
|
||||||
|
private static void handleError(final Context context, final ErrorInfo errorInfo) {
|
||||||
|
if (errorInfo.getThrowable() != null) {
|
||||||
|
errorInfo.getThrowable().printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
if (throwable instanceof ExtractionException) {
|
if (errorInfo.getThrowable() instanceof ReCaptchaException) {
|
||||||
showUnsupportedUrlDialog(url);
|
Toast.makeText(context, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
|
||||||
|
// Starting ReCaptcha Challenge Activity
|
||||||
|
final Intent intent = new Intent(context, ReCaptchaActivity.class);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
|
} else if (errorInfo.getThrowable() != null
|
||||||
|
&& ExceptionUtils.isNetworkRelated(errorInfo.getThrowable())) {
|
||||||
|
Toast.makeText(context, R.string.network_error, Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof AgeRestrictedContentException) {
|
||||||
|
Toast.makeText(context, R.string.restricted_video_no_stream,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof GeographicRestrictionException) {
|
||||||
|
Toast.makeText(context, R.string.georestricted_content, Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof PaidContentException) {
|
||||||
|
Toast.makeText(context, R.string.paid_content, Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof PrivateContentException) {
|
||||||
|
Toast.makeText(context, R.string.private_content, Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof SoundCloudGoPlusContentException) {
|
||||||
|
Toast.makeText(context, R.string.soundcloud_go_plus_content,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof YoutubeMusicPremiumContentException) {
|
||||||
|
Toast.makeText(context, R.string.youtube_music_premium_content,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof ContentNotAvailableException) {
|
||||||
|
Toast.makeText(context, R.string.content_not_available, Toast.LENGTH_LONG).show();
|
||||||
|
} else if (errorInfo.getThrowable() instanceof ContentNotSupportedException) {
|
||||||
|
Toast.makeText(context, R.string.content_not_supported, Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
ExtractorHelper.handleGeneralException(this, -1, url, throwable,
|
ErrorActivity.reportError(context, errorInfo);
|
||||||
UserAction.SOMETHING_ELSE, null);
|
}
|
||||||
finish();
|
|
||||||
|
if (context instanceof RouterActivity) {
|
||||||
|
((RouterActivity) context).finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +547,8 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
.subscribe(intent -> {
|
.subscribe(intent -> {
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
}, throwable -> handleError(throwable, currentUrl))
|
}, throwable -> handleError(this, new ErrorInfo(throwable,
|
||||||
|
UserAction.SHARE_TO_NEWPIPE, "Starting info activity: " + currentUrl)))
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -580,6 +628,7 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
this.playerChoice = playerChoice;
|
this.playerChoice = playerChoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return serviceId + ":" + url + " > " + linkType + " ::: " + playerChoice;
|
return serviceId + ":" + url + " > " + linkType + " ::: " + playerChoice;
|
||||||
@@ -646,9 +695,9 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
if (fetcher != null) {
|
if (fetcher != null) {
|
||||||
fetcher.dispose();
|
fetcher.dispose();
|
||||||
}
|
}
|
||||||
}, throwable -> ExtractorHelper.handleGeneralException(this,
|
}, throwable -> handleError(this, new ErrorInfo(throwable, finalUserAction,
|
||||||
choice.serviceId, choice.url, throwable, finalUserAction,
|
choice.url + " opened with " + choice.playerChoice,
|
||||||
", opened with " + choice.playerChoice));
|
choice.serviceId)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,6 @@ import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity
|
|||||||
import org.schabi.newpipe.database.stream.model.StreamEntity
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity
|
import org.schabi.newpipe.database.stream.model.StreamStateEntity
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||||
import kotlin.jvm.Throws
|
|
||||||
|
|
||||||
data class PlaylistStreamEntry(
|
data class PlaylistStreamEntry(
|
||||||
@Embedded
|
@Embedded
|
||||||
|
@@ -37,6 +37,9 @@ import org.schabi.newpipe.MainActivity;
|
|||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.RouterActivity;
|
import org.schabi.newpipe.RouterActivity;
|
||||||
import org.schabi.newpipe.databinding.DownloadDialogBinding;
|
import org.schabi.newpipe.databinding.DownloadDialogBinding;
|
||||||
|
import org.schabi.newpipe.error.ErrorActivity;
|
||||||
|
import org.schabi.newpipe.error.ErrorInfo;
|
||||||
|
import org.schabi.newpipe.error.UserAction;
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.localization.Localization;
|
import org.schabi.newpipe.extractor.localization.Localization;
|
||||||
@@ -45,9 +48,6 @@ import org.schabi.newpipe.extractor.stream.Stream;
|
|||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.report.ErrorInfo;
|
|
||||||
import org.schabi.newpipe.report.UserAction;
|
|
||||||
import org.schabi.newpipe.settings.NewPipeSettings;
|
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||||
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
||||||
import org.schabi.newpipe.util.FilenameUtils;
|
import org.schabi.newpipe.util.FilenameUtils;
|
||||||
@@ -61,7 +61,6 @@ import org.schabi.newpipe.util.ThemeHelper;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@@ -591,17 +590,6 @@ public class DownloadDialog extends DialogFragment
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showErrorActivity(final Exception e) {
|
|
||||||
ErrorActivity.reportError(
|
|
||||||
context,
|
|
||||||
Collections.singletonList(e),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
ErrorInfo
|
|
||||||
.make(UserAction.SOMETHING_ELSE, "-", "-", R.string.general_error)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareSelectedDownload() {
|
private void prepareSelectedDownload() {
|
||||||
final StoredDirectoryHelper mainStorage;
|
final StoredDirectoryHelper mainStorage;
|
||||||
final MediaFormat format;
|
final MediaFormat format;
|
||||||
@@ -684,6 +672,9 @@ public class DownloadDialog extends DialogFragment
|
|||||||
prefs.edit()
|
prefs.edit()
|
||||||
.putString(getString(R.string.last_used_download_type), selectedMediaType)
|
.putString(getString(R.string.last_used_download_type), selectedMediaType)
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
|
Toast.makeText(context, getString(R.string.download_has_started),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSelectedDownload(final StoredDirectoryHelper mainStorage,
|
private void checkSelectedDownload(final StoredDirectoryHelper mainStorage,
|
||||||
@@ -705,7 +696,8 @@ public class DownloadDialog extends DialogFragment
|
|||||||
mainStorage.getTag());
|
mainStorage.getTag());
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
showErrorActivity(e);
|
ErrorActivity.reportErrorInSnackbar(this,
|
||||||
|
new ErrorInfo(e, UserAction.DOWNLOAD_FAILED, "Getting storage"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
package org.schabi.newpipe.report;
|
package org.schabi.newpipe.error;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.acra.ReportField;
|
||||||
import org.acra.data.CrashReportData;
|
import org.acra.data.CrashReportData;
|
||||||
import org.acra.sender.ReportSender;
|
import org.acra.sender.ReportSender;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
@@ -32,8 +33,12 @@ public class AcraReportSender implements ReportSender {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(@NonNull final Context context, @NonNull final CrashReportData report) {
|
public void send(@NonNull final Context context, @NonNull final CrashReportData report) {
|
||||||
ErrorActivity.reportError(context, report,
|
ErrorActivity.reportError(context, new ErrorInfo(
|
||||||
ErrorInfo.make(UserAction.UI_ERROR, "none",
|
new String[]{report.getString(ReportField.STACK_TRACE)},
|
||||||
"App crash, UI failure", R.string.app_ui_crash));
|
UserAction.UI_ERROR,
|
||||||
|
ErrorInfo.SERVICE_NONE,
|
||||||
|
"ACRA report",
|
||||||
|
R.string.app_ui_crash,
|
||||||
|
null));
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe.report;
|
package org.schabi.newpipe.error;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
113
app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt
Normal file
113
app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package org.schabi.newpipe.error
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import org.schabi.newpipe.R
|
||||||
|
import org.schabi.newpipe.extractor.Info
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException
|
||||||
|
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor.DeobfuscateException
|
||||||
|
import org.schabi.newpipe.ktx.isNetworkRelated
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.io.StringWriter
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class ErrorInfo(
|
||||||
|
val stackTraces: Array<String>,
|
||||||
|
val userAction: UserAction,
|
||||||
|
val serviceName: String,
|
||||||
|
val request: String,
|
||||||
|
val messageStringId: Int,
|
||||||
|
@Transient // no need to store throwable, all data for report is in other variables
|
||||||
|
var throwable: Throwable? = null
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
private constructor(
|
||||||
|
throwable: Throwable,
|
||||||
|
userAction: UserAction,
|
||||||
|
serviceName: String,
|
||||||
|
request: String
|
||||||
|
) : this(
|
||||||
|
throwableToStringList(throwable),
|
||||||
|
userAction,
|
||||||
|
serviceName,
|
||||||
|
request,
|
||||||
|
getMessageStringId(throwable, userAction),
|
||||||
|
throwable
|
||||||
|
)
|
||||||
|
|
||||||
|
private constructor(
|
||||||
|
throwable: List<Throwable>,
|
||||||
|
userAction: UserAction,
|
||||||
|
serviceName: String,
|
||||||
|
request: String
|
||||||
|
) : this(
|
||||||
|
throwableListToStringList(throwable),
|
||||||
|
userAction,
|
||||||
|
serviceName,
|
||||||
|
request,
|
||||||
|
getMessageStringId(throwable.firstOrNull(), userAction),
|
||||||
|
throwable.firstOrNull()
|
||||||
|
)
|
||||||
|
|
||||||
|
// constructors with single throwable
|
||||||
|
constructor(throwable: Throwable, userAction: UserAction, request: String) :
|
||||||
|
this(throwable, userAction, SERVICE_NONE, request)
|
||||||
|
constructor(throwable: Throwable, userAction: UserAction, request: String, serviceId: Int) :
|
||||||
|
this(throwable, userAction, NewPipe.getNameOfService(serviceId), request)
|
||||||
|
constructor(throwable: Throwable, userAction: UserAction, request: String, info: Info?) :
|
||||||
|
this(throwable, userAction, getInfoServiceName(info), request)
|
||||||
|
|
||||||
|
// constructors with list of throwables
|
||||||
|
constructor(throwable: List<Throwable>, userAction: UserAction, request: String) :
|
||||||
|
this(throwable, userAction, SERVICE_NONE, request)
|
||||||
|
constructor(throwable: List<Throwable>, userAction: UserAction, request: String, serviceId: Int) :
|
||||||
|
this(throwable, userAction, NewPipe.getNameOfService(serviceId), request)
|
||||||
|
constructor(throwable: List<Throwable>, userAction: UserAction, request: String, info: Info?) :
|
||||||
|
this(throwable, userAction, getInfoServiceName(info), request)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val SERVICE_NONE = "none"
|
||||||
|
|
||||||
|
private fun getStackTrace(throwable: Throwable): String {
|
||||||
|
StringWriter().use { stringWriter ->
|
||||||
|
PrintWriter(stringWriter, true).use { printWriter ->
|
||||||
|
throwable.printStackTrace(printWriter)
|
||||||
|
return stringWriter.buffer.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun throwableToStringList(throwable: Throwable) = arrayOf(getStackTrace(throwable))
|
||||||
|
|
||||||
|
fun throwableListToStringList(throwable: List<Throwable>) =
|
||||||
|
Array(throwable.size) { i -> getStackTrace(throwable[i]) }
|
||||||
|
|
||||||
|
private fun getInfoServiceName(info: Info?) =
|
||||||
|
if (info == null) SERVICE_NONE else NewPipe.getNameOfService(info.serviceId)
|
||||||
|
|
||||||
|
@StringRes
|
||||||
|
private fun getMessageStringId(
|
||||||
|
throwable: Throwable?,
|
||||||
|
action: UserAction
|
||||||
|
): Int {
|
||||||
|
return when {
|
||||||
|
throwable is ContentNotAvailableException -> R.string.content_not_available
|
||||||
|
throwable != null && throwable.isNetworkRelated -> R.string.network_error
|
||||||
|
throwable is ContentNotSupportedException -> R.string.content_not_supported
|
||||||
|
throwable is DeobfuscateException -> R.string.youtube_signature_deobfuscation_error
|
||||||
|
throwable is ExtractionException -> R.string.parsing_error
|
||||||
|
action == UserAction.UI_ERROR -> R.string.app_ui_crash
|
||||||
|
action == UserAction.REQUESTED_COMMENTS -> R.string.error_unable_to_load_comments
|
||||||
|
action == UserAction.SUBSCRIPTION_CHANGE -> R.string.subscription_change_failed
|
||||||
|
action == UserAction.SUBSCRIPTION_UPDATE -> R.string.subscription_update_failed
|
||||||
|
action == UserAction.LOAD_IMAGE -> R.string.could_not_load_thumbnails
|
||||||
|
action == UserAction.DOWNLOAD_OPEN_DIALOG -> R.string.could_not_setup_download_menu
|
||||||
|
else -> R.string.general_error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
132
app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt
Normal file
132
app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package org.schabi.newpipe.error
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.jakewharton.rxbinding4.view.clicks
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
|
import org.schabi.newpipe.MainActivity
|
||||||
|
import org.schabi.newpipe.R
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.PaidContentException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.PrivateContentException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException
|
||||||
|
import org.schabi.newpipe.ktx.animate
|
||||||
|
import org.schabi.newpipe.ktx.isInterruptedCaused
|
||||||
|
import org.schabi.newpipe.ktx.isNetworkRelated
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class ErrorPanelHelper(
|
||||||
|
private val fragment: Fragment,
|
||||||
|
rootView: View,
|
||||||
|
onRetry: Runnable
|
||||||
|
) {
|
||||||
|
private val context: Context = rootView.context!!
|
||||||
|
private val errorPanelRoot: View = rootView.findViewById(R.id.error_panel)
|
||||||
|
private val errorTextView: TextView = errorPanelRoot.findViewById(R.id.error_message_view)
|
||||||
|
private val errorButtonAction: Button = errorPanelRoot.findViewById(R.id.error_button_action)
|
||||||
|
private val errorButtonRetry: Button = errorPanelRoot.findViewById(R.id.error_button_retry)
|
||||||
|
|
||||||
|
private var errorDisposable: Disposable? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
errorDisposable = errorButtonRetry.clicks()
|
||||||
|
.debounce(300, TimeUnit.MILLISECONDS)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { onRetry.run() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showError(errorInfo: ErrorInfo) {
|
||||||
|
|
||||||
|
if (errorInfo.throwable != null && errorInfo.throwable!!.isInterruptedCaused) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.w(TAG, "onError() isInterruptedCaused! = [$errorInfo.throwable]")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
errorButtonAction.isVisible = true
|
||||||
|
if (errorInfo.throwable is ReCaptchaException) {
|
||||||
|
errorButtonAction.setText(R.string.recaptcha_solve)
|
||||||
|
errorButtonAction.setOnClickListener {
|
||||||
|
// Starting ReCaptcha Challenge Activity
|
||||||
|
val intent = Intent(context, ReCaptchaActivity::class.java)
|
||||||
|
intent.putExtra(
|
||||||
|
ReCaptchaActivity.RECAPTCHA_URL_EXTRA,
|
||||||
|
(errorInfo.throwable as ReCaptchaException).url
|
||||||
|
)
|
||||||
|
fragment.startActivityForResult(intent, ReCaptchaActivity.RECAPTCHA_REQUEST)
|
||||||
|
errorButtonAction.setOnClickListener(null)
|
||||||
|
}
|
||||||
|
errorTextView.setText(R.string.recaptcha_request_toast)
|
||||||
|
errorButtonRetry.isVisible = true
|
||||||
|
} else {
|
||||||
|
errorButtonAction.setText(R.string.error_snackbar_action)
|
||||||
|
errorButtonAction.setOnClickListener {
|
||||||
|
ErrorActivity.reportError(context, errorInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide retry button by default, then show only if not unavailable/unsupported content
|
||||||
|
errorButtonRetry.isVisible = false
|
||||||
|
errorTextView.setText(
|
||||||
|
when (errorInfo.throwable) {
|
||||||
|
is AgeRestrictedContentException -> R.string.restricted_video_no_stream
|
||||||
|
is GeographicRestrictionException -> R.string.georestricted_content
|
||||||
|
is PaidContentException -> R.string.paid_content
|
||||||
|
is PrivateContentException -> R.string.private_content
|
||||||
|
is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content
|
||||||
|
is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content
|
||||||
|
is ContentNotAvailableException -> R.string.content_not_available
|
||||||
|
is ContentNotSupportedException -> R.string.content_not_supported
|
||||||
|
else -> {
|
||||||
|
// show retry button only for content which is not unavailable or unsupported
|
||||||
|
errorButtonRetry.isVisible = true
|
||||||
|
if (errorInfo.throwable != null && errorInfo.throwable!!.isNetworkRelated) {
|
||||||
|
R.string.network_error
|
||||||
|
} else {
|
||||||
|
R.string.error_snackbar_message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
errorPanelRoot.animate(true, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showTextError(errorString: String) {
|
||||||
|
errorButtonAction.isVisible = false
|
||||||
|
errorButtonRetry.isVisible = false
|
||||||
|
errorTextView.text = errorString
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hide() {
|
||||||
|
errorButtonAction.setOnClickListener(null)
|
||||||
|
errorPanelRoot.animate(false, 150)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isVisible(): Boolean {
|
||||||
|
return errorPanelRoot.isVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
errorButtonAction.setOnClickListener(null)
|
||||||
|
errorButtonRetry.setOnClickListener(null)
|
||||||
|
errorDisposable?.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val TAG: String = ErrorPanelHelper::class.simpleName!!
|
||||||
|
val DEBUG: Boolean = MainActivity.DEBUG
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.error;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -20,6 +20,9 @@ import androidx.preference.PreferenceManager;
|
|||||||
import androidx.webkit.WebViewClientCompat;
|
import androidx.webkit.WebViewClientCompat;
|
||||||
|
|
||||||
import org.schabi.newpipe.databinding.ActivityRecaptchaBinding;
|
import org.schabi.newpipe.databinding.ActivityRecaptchaBinding;
|
||||||
|
import org.schabi.newpipe.DownloaderImpl;
|
||||||
|
import org.schabi.newpipe.MainActivity;
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
@@ -1,4 +1,4 @@
|
|||||||
package org.schabi.newpipe.report;
|
package org.schabi.newpipe.error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user actions that can cause an error.
|
* The user actions that can cause an error.
|
||||||
@@ -6,9 +6,12 @@ package org.schabi.newpipe.report;
|
|||||||
public enum UserAction {
|
public enum UserAction {
|
||||||
USER_REPORT("user report"),
|
USER_REPORT("user report"),
|
||||||
UI_ERROR("ui error"),
|
UI_ERROR("ui error"),
|
||||||
SUBSCRIPTION("subscription"),
|
SUBSCRIPTION_CHANGE("subscription change"),
|
||||||
|
SUBSCRIPTION_UPDATE("subscription update"),
|
||||||
|
SUBSCRIPTION_GET("get subscription"),
|
||||||
|
SUBSCRIPTION_IMPORT_EXPORT("subscription import or export"),
|
||||||
LOAD_IMAGE("load image"),
|
LOAD_IMAGE("load image"),
|
||||||
SOMETHING_ELSE("something"),
|
SOMETHING_ELSE("something else"),
|
||||||
SEARCHED("searched"),
|
SEARCHED("searched"),
|
||||||
GET_SUGGESTIONS("get suggestions"),
|
GET_SUGGESTIONS("get suggestions"),
|
||||||
REQUESTED_STREAM("requested stream"),
|
REQUESTED_STREAM("requested stream"),
|
||||||
@@ -17,11 +20,15 @@ public enum UserAction {
|
|||||||
REQUESTED_KIOSK("requested kiosk"),
|
REQUESTED_KIOSK("requested kiosk"),
|
||||||
REQUESTED_COMMENTS("requested comments"),
|
REQUESTED_COMMENTS("requested comments"),
|
||||||
REQUESTED_FEED("requested feed"),
|
REQUESTED_FEED("requested feed"),
|
||||||
|
REQUESTED_BOOKMARK("bookmark"),
|
||||||
DELETE_FROM_HISTORY("delete from history"),
|
DELETE_FROM_HISTORY("delete from history"),
|
||||||
PLAY_STREAM("Play stream"),
|
PLAY_STREAM("play stream"),
|
||||||
|
DOWNLOAD_OPEN_DIALOG("download open dialog"),
|
||||||
DOWNLOAD_POSTPROCESSING("download post-processing"),
|
DOWNLOAD_POSTPROCESSING("download post-processing"),
|
||||||
DOWNLOAD_FAILED("download failed"),
|
DOWNLOAD_FAILED("download failed"),
|
||||||
PREFERENCES_MIGRATION("migration of preferences");
|
PREFERENCES_MIGRATION("migration of preferences"),
|
||||||
|
SHARE_TO_NEWPIPE("share to newpipe"),
|
||||||
|
CHECK_FOR_NEW_APP_VERSION("check for new app version");
|
||||||
|
|
||||||
|
|
||||||
private final String message;
|
private final String message;
|
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,18 @@ import org.schabi.newpipe.BaseFragment;
|
|||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
|
||||||
public class EmptyFragment extends BaseFragment {
|
public class EmptyFragment extends BaseFragment {
|
||||||
|
final boolean showMessage;
|
||||||
|
|
||||||
|
public EmptyFragment(final boolean showMessage) {
|
||||||
|
this.showMessage = showMessage;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
final Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.fragment_empty, container, false);
|
final View view = inflater.inflate(R.layout.fragment_empty, container, false);
|
||||||
|
view.findViewById(R.id.empty_state_view).setVisibility(
|
||||||
|
showMessage ? View.VISIBLE : View.GONE);
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,6 @@ import android.view.ViewGroup;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
|
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
|
||||||
@@ -25,10 +24,8 @@ import com.google.android.material.tabs.TabLayout;
|
|||||||
import org.schabi.newpipe.BaseFragment;
|
import org.schabi.newpipe.BaseFragment;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.databinding.FragmentMainBinding;
|
import org.schabi.newpipe.databinding.FragmentMainBinding;
|
||||||
|
import org.schabi.newpipe.error.ErrorActivity;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.report.ErrorInfo;
|
|
||||||
import org.schabi.newpipe.report.UserAction;
|
|
||||||
import org.schabi.newpipe.settings.tabs.Tab;
|
import org.schabi.newpipe.settings.tabs.Tab;
|
||||||
import org.schabi.newpipe.settings.tabs.TabsManager;
|
import org.schabi.newpipe.settings.tabs.TabsManager;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
@@ -128,7 +125,8 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
public void onCreateOptionsMenu(@NonNull final Menu menu,
|
||||||
|
@NonNull final MenuInflater inflater) {
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "onCreateOptionsMenu() called with: "
|
Log.d(TAG, "onCreateOptionsMenu() called with: "
|
||||||
@@ -144,15 +142,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
if (item.getItemId() == R.id.action_search) {
|
||||||
case R.id.action_search:
|
try {
|
||||||
try {
|
NavigationHelper.openSearchFragment(getFM(),
|
||||||
NavigationHelper.openSearchFragment(getFM(),
|
ServiceHelper.getSelectedServiceId(activity), "");
|
||||||
ServiceHelper.getSelectedServiceId(activity), "");
|
} catch (final Exception e) {
|
||||||
} catch (final Exception e) {
|
ErrorActivity.reportUiErrorInSnackbar(this, "Opening search fragment", e);
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
}
|
||||||
}
|
return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
@@ -241,8 +238,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
ErrorActivity.reportError(context, throwable, null, null, ErrorInfo
|
ErrorActivity.reportUiErrorInSnackbar(context, "Getting fragment item", throwable);
|
||||||
.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash));
|
|
||||||
return new BlankFragment();
|
return new BlankFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +250,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemPosition(final Object object) {
|
public int getItemPosition(@NonNull final Object object) {
|
||||||
// Causes adapter to reload all Fragments when
|
// Causes adapter to reload all Fragments when
|
||||||
// notifyDataSetChanged is called
|
// notifyDataSetChanged is called
|
||||||
return POSITION_NONE;
|
return POSITION_NONE;
|
||||||
|
@@ -7,7 +7,7 @@ public interface ViewContract<I> {
|
|||||||
|
|
||||||
void showEmptyState();
|
void showEmptyState();
|
||||||
|
|
||||||
void showError(String message, boolean showRetryButton);
|
|
||||||
|
|
||||||
void handleResult(I result);
|
void handleResult(I result);
|
||||||
|
|
||||||
|
void handleError();
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user