mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-28 06:00:50 +02:00
Compare commits
248 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c5d1271894 | ||
![]() |
050d3058f9 | ||
![]() |
2ae99afa21 | ||
![]() |
b094c9190f | ||
![]() |
1a9e1e6f7c | ||
![]() |
8c94926693 | ||
![]() |
880a176e65 | ||
![]() |
8de1b5f3d9 | ||
![]() |
178f4546fc | ||
![]() |
7564a49344 | ||
![]() |
c7941a85ed | ||
![]() |
fab5f26e09 | ||
![]() |
3599ab3caf | ||
![]() |
6035be9ce6 | ||
![]() |
ccd0f7d9cc | ||
![]() |
8746e7c9ad | ||
![]() |
e2aa36d083 | ||
![]() |
51434a39f8 | ||
![]() |
3e2031be7c | ||
![]() |
ea4e8805b7 | ||
![]() |
b9042c37f9 | ||
![]() |
9f4a7e664f | ||
![]() |
38eb75b13f | ||
![]() |
0ad56874b4 | ||
![]() |
c1168693fa | ||
![]() |
feb8c27f1f | ||
![]() |
c20ebd66e5 | ||
![]() |
4d78d530dc | ||
![]() |
22b20c15de | ||
![]() |
c69b224c65 | ||
![]() |
805d328d6c | ||
![]() |
b8293f134d | ||
![]() |
7e9bcff0f3 | ||
![]() |
eba3b32708 | ||
![]() |
e911dbb9d4 | ||
![]() |
e26d123f67 | ||
![]() |
22e3cddd91 | ||
![]() |
f3d4d4747a | ||
![]() |
5bbb0cd666 | ||
![]() |
7b5ba3bdc2 | ||
![]() |
d647555e3a | ||
![]() |
84976a65e0 | ||
![]() |
fef9d541ed | ||
![]() |
6784522195 | ||
![]() |
f42d077f30 | ||
![]() |
eaca47ebc6 | ||
![]() |
4d57223847 | ||
![]() |
d9ab96236b | ||
![]() |
2856fb029f | ||
![]() |
8fb945312a | ||
![]() |
25d6806ebd | ||
![]() |
51070d9afd | ||
![]() |
1048caa496 | ||
![]() |
0cd7ac05aa | ||
![]() |
2793c42d91 | ||
![]() |
2eaa7288e4 | ||
![]() |
0df8d13020 | ||
![]() |
d27622de1e | ||
![]() |
47c3da131c | ||
![]() |
64f9228ee3 | ||
![]() |
b462b7fcc4 | ||
![]() |
b34f9d7fd3 | ||
![]() |
57732c3e5f | ||
![]() |
eb1f56488f | ||
![]() |
5825843f68 | ||
![]() |
86f82c0e61 | ||
![]() |
45fea983b9 | ||
![]() |
642b499e70 | ||
![]() |
5c5575bb72 | ||
![]() |
fba0a8036b | ||
![]() |
d82274f5d4 | ||
![]() |
3cf81230b2 | ||
![]() |
17bab456e4 | ||
![]() |
e1cc006db7 | ||
![]() |
7e95dd3c76 | ||
![]() |
ff3ce46a26 | ||
![]() |
4d61c2c5e0 | ||
![]() |
afaba7ccdf | ||
![]() |
ccb3ceae4f | ||
![]() |
d0d93f6d2d | ||
![]() |
67f091c731 | ||
![]() |
fa3aebb7b1 | ||
![]() |
988251deb6 | ||
![]() |
d99a389c49 | ||
![]() |
7508f9d3bb | ||
![]() |
b2512d7aee | ||
![]() |
eb74e1e3b2 | ||
![]() |
bd91e82b17 | ||
![]() |
bae60acfe7 | ||
![]() |
426cefe8ee | ||
![]() |
a36fe3ef21 | ||
![]() |
ee0756c7c0 | ||
![]() |
44b96121e4 | ||
![]() |
8add777b34 | ||
![]() |
6932b15144 | ||
![]() |
c09edda797 | ||
![]() |
0e86010565 | ||
![]() |
6fe3fdce11 | ||
![]() |
90769a12b1 | ||
![]() |
1d49b725b6 | ||
![]() |
204feb97ce | ||
![]() |
e12389a748 | ||
![]() |
907e5a10d6 | ||
![]() |
670591e221 | ||
![]() |
8006a7d578 | ||
![]() |
8b9078b82e | ||
![]() |
56d4edd3ae | ||
![]() |
a7f5ea865e | ||
![]() |
2a62144abd | ||
![]() |
c7ea7a4f65 | ||
![]() |
7ea090ba8d | ||
![]() |
9294e353d3 | ||
![]() |
71c50c58ee | ||
![]() |
e322299fda | ||
![]() |
06602a568a | ||
![]() |
a0f0529ad8 | ||
![]() |
c371d863d9 | ||
![]() |
16d8c75953 | ||
![]() |
fa48c0e76b | ||
![]() |
2d17cfaf2b | ||
![]() |
f379de0a3a | ||
![]() |
d3fcb0aa6a | ||
![]() |
046740f10b | ||
![]() |
ffae2eda83 | ||
![]() |
8334b8fe46 | ||
![]() |
c6c6e58d28 | ||
![]() |
2ff0d6665c | ||
![]() |
dc6108c970 | ||
![]() |
6f52f9b4af | ||
![]() |
b6eb896f0b | ||
![]() |
adf861c36d | ||
![]() |
4e1bcdf209 | ||
![]() |
d107fe19f7 | ||
![]() |
fa03ff51d4 | ||
![]() |
f6c6536b48 | ||
![]() |
38e4249182 | ||
![]() |
2dd8c0beee | ||
![]() |
6a35494ef1 | ||
![]() |
bf1c42e085 | ||
![]() |
0ef6bf8067 | ||
![]() |
9d63e2ae97 | ||
![]() |
fdd8060296 | ||
![]() |
ebbb23ffbb | ||
![]() |
0e413109bd | ||
![]() |
f7e29c1e00 | ||
![]() |
42f777d49a | ||
![]() |
efb8ea4c25 | ||
![]() |
52bf5690c0 | ||
![]() |
607dff9263 | ||
![]() |
0510db75fb | ||
![]() |
859eecabc0 | ||
![]() |
7a0253631b | ||
![]() |
c12a60c1ad | ||
![]() |
df9dbd6130 | ||
![]() |
a98e745116 | ||
![]() |
61f1b10a06 | ||
![]() |
4bcb2a5c9d | ||
![]() |
7e48648f9e | ||
![]() |
bcc97d1aa7 | ||
![]() |
49f9d36718 | ||
![]() |
f9cb258a5e | ||
![]() |
97381a4908 | ||
![]() |
7a15acc546 | ||
![]() |
0265de2137 | ||
![]() |
595b9910f5 | ||
![]() |
f4d4d2cc35 | ||
![]() |
b4fb4d7dcf | ||
![]() |
1a375fb523 | ||
![]() |
658c0ff5c4 | ||
![]() |
6092f06d46 | ||
![]() |
4671b956b3 | ||
![]() |
552ba6999a | ||
![]() |
b86bc4455f | ||
![]() |
b6d36ee117 | ||
![]() |
5d57f864dc | ||
![]() |
c6ee2816db | ||
![]() |
0aa898b13f | ||
![]() |
b22e82c8ce | ||
![]() |
63dee1e1ac | ||
![]() |
91c87ac301 | ||
![]() |
42371a6e8d | ||
![]() |
d7aae849f6 | ||
![]() |
4fe9413662 | ||
![]() |
37bf51cebf | ||
![]() |
eee9cb8b87 | ||
![]() |
1724bca5f0 | ||
![]() |
ae6581fb55 | ||
![]() |
0c632307ea | ||
![]() |
479887eb84 | ||
![]() |
af280a7343 | ||
![]() |
802b26e870 | ||
![]() |
0ab86937d2 | ||
![]() |
3ab06bf383 | ||
![]() |
5db0cc5241 | ||
![]() |
a588ec084b | ||
![]() |
5660b5ddc6 | ||
![]() |
27fbe69033 | ||
![]() |
1672ecb892 | ||
![]() |
784e01347c | ||
![]() |
5cc21a831b | ||
![]() |
dcb9380b50 | ||
![]() |
b1957773bb | ||
![]() |
c4f4583f20 | ||
![]() |
440cdbdb23 | ||
![]() |
58bfde33a9 | ||
![]() |
7c33e49ef6 | ||
![]() |
3bf318e2b7 | ||
![]() |
f56193ac18 | ||
![]() |
31efa7a8f8 | ||
![]() |
372932abaf | ||
![]() |
4c6dd2cdf2 | ||
![]() |
6d04e39151 | ||
![]() |
afa257e79a | ||
![]() |
97555645f8 | ||
![]() |
e350f43adc | ||
![]() |
2257f3484d | ||
![]() |
f4ba8df02b | ||
![]() |
99ebf03876 | ||
![]() |
995d79e373 | ||
![]() |
0cd153ab61 | ||
![]() |
b24baa68ba | ||
![]() |
d4c1b8d321 | ||
![]() |
1e53d6bfab | ||
![]() |
5931cd6af7 | ||
![]() |
a1be03543c | ||
![]() |
b1a5547de2 | ||
![]() |
ee4942dfd7 | ||
![]() |
8aef24be1e | ||
![]() |
fb25f6c7ac | ||
![]() |
fbd983217d | ||
![]() |
ce21fe2087 | ||
![]() |
17cd395712 | ||
![]() |
bfe9de05cd | ||
![]() |
4326354ca6 | ||
![]() |
4208c852e1 | ||
![]() |
7330b4532e | ||
![]() |
1e0f6f9e41 | ||
![]() |
216e2367c6 | ||
![]() |
f4416fe007 | ||
![]() |
510591ef0f | ||
![]() |
a5e89d1dd1 | ||
![]() |
b48c251b36 | ||
![]() |
181a14ce59 | ||
![]() |
b9ea7ce066 | ||
![]() |
f2f275512d | ||
![]() |
5150c2ee62 | ||
![]() |
0b7593ad28 | ||
![]() |
a68823491c |
46
.github/CONTRIBUTING.md
vendored
46
.github/CONTRIBUTING.md
vendored
@@ -5,44 +5,64 @@ PLEASE READ THESE GUIDELINES CAREFULLY BEFORE ANY CONTRIBUTION!
|
|||||||
|
|
||||||
## Crash reporting
|
## Crash reporting
|
||||||
|
|
||||||
Do not report crashes in the GitHub issue tracker. NewPipe has an automated crash report system that will ask you to send a report via e-mail when a crash occurs. This contains all the data we need for debugging, and allows you to even add a comment to it. You'll see exactly what is sent, the system is 100% transparent.
|
Do not report crashes in the GitHub issue tracker. NewPipe has an automated crash report system that will ask you to
|
||||||
|
send a report via e-mail when a crash occurs. This contains all the data we need for debugging, and allows you to even
|
||||||
|
add a comment to it. You'll see exactly what is sent, the system is 100% transparent.
|
||||||
|
|
||||||
## Issue reporting/feature requests
|
## Issue reporting/feature requests
|
||||||
|
|
||||||
* Search the [existing issues](https://github.com/TeamNewPipe/NewPipe/issues) first to make sure your issue/feature hasn't been reported/requested before
|
* Search the [existing issues](https://github.com/TeamNewPipe/NewPipe/issues) first to make sure your issue/feature
|
||||||
|
hasn't been reported/requested before
|
||||||
* Check whether your issue/feature is already fixed/implemented
|
* Check whether your issue/feature is already fixed/implemented
|
||||||
* Check if the issue still exists in the latest release/beta version
|
* Check if the issue still exists in the latest release/beta version
|
||||||
* If you are an Android/Java developer, you are always welcome to fix/implement an issue/a feature yourself. PRs welcome!
|
* If you are an Android/Java developer, you are always welcome to fix/implement an issue/a feature yourself. PRs welcome!
|
||||||
* We use English for development. Issues in other languages will be closed and ignored.
|
* We use English for development. Issues in other languages will be closed and ignored.
|
||||||
* Please only add *one* issue at a time. Do not put multiple issues into one thread.
|
* Please only add *one* issue at a time. Do not put multiple issues into one thread.
|
||||||
* When reporting a bug please give us a context, and a description how to reproduce it.
|
* When reporting a bug please give us a context, and a description how to reproduce it.
|
||||||
* Issues that only contain a generated bug report, but no describtion might be closed.
|
* Issues that only contain a generated bug report, but no description might be closed.
|
||||||
|
|
||||||
## Bug Fixing
|
## Bug Fixing
|
||||||
* If you want to help NewPipe to become free of bugs (this is our utopic goal for NewPipe), you can send us an email to tnp@newpipe.schabi.org to let me know that you intend to help. We'll send you further instructions. You may, on request, register at our [Sentry](https://sentry.schabi.org) instance (see section "Crash reporting" for more information.
|
* If you want to help NewPipe to become free of bugs (this is our utopic goal for NewPipe), you can send us an email to
|
||||||
|
tnp@newpipe.schabi.org to let me know that you intend to help. We'll send you further instructions. You may, on request,
|
||||||
|
register at our [Sentry](https://sentry.schabi.org) instance (see section "Crash reporting" for more information.
|
||||||
|
|
||||||
## Translation
|
## Translation
|
||||||
|
|
||||||
* NewPipe can be translated via [Weblate](https://hosted.weblate.org/projects/newpipe/strings/). You can log in there with your GitHub account.
|
* NewPipe can be translated via [Weblate](https://hosted.weblate.org/projects/newpipe/strings/). You can log in there
|
||||||
|
with your GitHub account.
|
||||||
|
|
||||||
## Code contribution
|
## Code contribution
|
||||||
|
|
||||||
* Stick to NewPipe's style conventions (well, just look the other code and then do it the same way :))
|
* Stick to NewPipe's style conventions (well, just look the other code and then do it the same way :))
|
||||||
* Do not bring non-free software (e.g., binary blobs) into the project. Also, make sure you do not introduce Google libraries.
|
* Do not bring non-free software (e.g., binary blobs) into the project. Also, make sure you do not introduce Google
|
||||||
|
libraries.
|
||||||
* Stick to [F-Droid contribution guidelines](https://f-droid.org/wiki/page/Inclusion_Policy)
|
* Stick to [F-Droid contribution guidelines](https://f-droid.org/wiki/page/Inclusion_Policy)
|
||||||
* Make changes on a separate branch, not on the master branch. This is commonly known as *feature branch workflow*. You may then send your changes as a pull request on GitHub. Patches to the email address mentioned in this document might not be considered, GitHub is the primary platform. (This only affects you if you are a member of TeamNewPipe)
|
* Make changes on a separate branch, not on the master branch. This is commonly known as *feature branch workflow*. You
|
||||||
* When submitting changes, you confirm that your code is licensed under the terms of the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.html).
|
may then send your changes as a pull request on GitHub. Patches to the email address mentioned in this document might
|
||||||
* Please test (compile and run) your code before you submit changes! Ideally, provide test feedback in the PR description. Untested code will **not** be merged!
|
not be considered, GitHub is the primary platform. (This only affects you if you are a member of TeamNewPipe)
|
||||||
|
* When submitting changes, you confirm that your code is licensed under the terms of the
|
||||||
|
[GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
* Please test (compile and run) your code before you submit changes! Ideally, provide test feedback in the PR
|
||||||
|
description. Untested code will **not** be merged!
|
||||||
* Try to figure out yourself why builds on our CI fail.
|
* Try to figure out yourself why builds on our CI fail.
|
||||||
* Make sure your PR is up-to-date with the rest of the code. Often, a simple click on "Update branch" will do the job, but if not, you are asked to merge the master branch manually and resolve the problems on your own. That will make the maintainers' jobs way easier.
|
* Make sure your PR is up-to-date with the rest of the code. Often, a simple click on "Update branch" will do the job,
|
||||||
* Please show intention to maintain your features and code after you contributed it. Unmaintained code is a hassle for the core developers, and just adds work. If you do not intend to maintain features you contributed, please think again about submission, or clearly state that in the description of your PR.
|
but if not, you are asked to merge the master branch manually and resolve the problems on your own. That will make the
|
||||||
|
maintainers' jobs way easier.
|
||||||
|
* Please show intention to maintain your features and code after you contributed it. Unmaintained code is a hassle for
|
||||||
|
the core developers, and just adds work. If you do not intend to maintain features you contributed, please think again
|
||||||
|
about submission, or clearly state that in the description of your PR.
|
||||||
* Respond yourselves if someone requests changes or otherwise raises issues about your PRs.
|
* Respond yourselves if someone requests changes or otherwise raises issues about your PRs.
|
||||||
* Check if your contributions align with the [fdroid inclusion guidelines](https://f-droid.org/en/docs/Inclusion_Policy/).
|
* Check if your contributions align with the [fdroid inclusion guidelines](https://f-droid.org/en/docs/Inclusion_Policy/).
|
||||||
* Check if your submission can be build with the current fdroid build server setup.
|
* Check if your submission can be build with the current fdroid build server setup.
|
||||||
|
* Send PR that only cover one specific issue/solution/bug. Do not send PRs that are huge and consists of multiple
|
||||||
|
independent solutions.
|
||||||
|
|
||||||
## Communication
|
## Communication
|
||||||
|
|
||||||
* WE DO NOW HAVE A MAILING LIST: [newpipe@list.schabi.org](https://list.schabi.org/cgi-bin/mailman/listinfo/newpipe).
|
* WE DO NOW HAVE A MAILING LIST: [newpipe@list.schabi.org](https://list.schabi.org/cgi-bin/mailman/listinfo/newpipe).
|
||||||
* There is an IRC channel on Freenode which is regularly visited by the core team and other developers: [#newpipe](irc:irc.freenode.net/newpipe). [Click here for Webchat](https://webchat.freenode.net/?channels=newpipe)!
|
* There is an IRC channel on Freenode which is regularly visited by the core team and other developers:
|
||||||
* If you want to get in touch with the core team or one of our other contributors you can send an email to tnp(at)schabi.org. Please do not send issue reports, they will be ignored and remain unanswered! Use the GitHub issue tracker described above!
|
[#newpipe](irc:irc.freenode.net/newpipe). [Click here for Webchat](https://webchat.freenode.net/?channels=newpipe)!
|
||||||
|
* If you want to get in touch with the core team or one of our other contributors you can send an email to
|
||||||
|
tnp(at)schabi.org. Please do not send issue reports, they will be ignored and remain unanswered! Use the GitHub issue
|
||||||
|
tracker described above!
|
||||||
* Feel free to post suggestions, changes, ideas etc. on GitHub, IRC or the mailing list!
|
* Feel free to post suggestions, changes, ideas etc. on GitHub, IRC or the mailing list!
|
||||||
|
@@ -5,13 +5,13 @@ android:
|
|||||||
components:
|
components:
|
||||||
# The BuildTools version used by NewPipe
|
# The BuildTools version used by NewPipe
|
||||||
- tools
|
- tools
|
||||||
- build-tools-27.0.3
|
- build-tools-28.0.3
|
||||||
|
|
||||||
# The SDK version used to compile NewPipe
|
# The SDK version used to compile NewPipe
|
||||||
- android-27
|
- android-28
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- yes | sdkmanager "platforms;android-27"
|
- yes | sdkmanager "platforms;android-28"
|
||||||
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
|
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
|
||||||
|
|
||||||
licenses:
|
licenses:
|
||||||
|
92
README.md
92
README.md
@@ -1,74 +1,77 @@
|
|||||||
<p align="center"><a href="https://newpipe.schabi.org"><img src="assets/new_pipe_icon_5.png" width="150"/></a></p>
|
<p align="center"><a href="https://newpipe.schabi.org"><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 free lightweight YouTube 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://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" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" /></a>
|
<a href="https://github.com/TeamNewPipe/NewPipe" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
|
||||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPL v3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg" /></a>
|
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||||
<a href="https://travis-ci.org/TeamNewPipe/NewPipe" alt="Build Status"><img src="https://travis-ci.org/TeamNewPipe/NewPipe.svg" /></a>
|
<a href="https://travis-ci.org/TeamNewPipe/NewPipe" alt="Build Status"><img src="https://travis-ci.org/TeamNewPipe/NewPipe.svg"></a>
|
||||||
<a href="https://hosted.weblate.org/engage/NewPipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg" /></a>
|
<a href="https://hosted.weblate.org/engage/NewPipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg"></a>
|
||||||
<a href="http://webchat.freenode.net/?channels=%23newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg" /></a>
|
<a href="http://webchat.freenode.net/?channels=%23newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"/></a>
|
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr>
|
||||||
<p align="center"><a href="#screenshots">Screenshots</a> • <a href="#description">Description</a> • <a href="#features">Features</a> • <a href="#contribution">Contribution</a> • <a href="#donate">Donate</a> • <a href="#license">License</a></p>
|
<p align="center"><a href="#screenshots">Screenshots</a> • <a href="#description">Description</a> • <a href="#features">Features</a> • <a href="#contribution">Contribution</a> • <a href="#donate">Donate</a> • <a href="#license">License</a></p>
|
||||||
<p align="center"><a href="https://newpipe.schabi.org">Website</a> • <a href="https://newpipe.schabi.org/blog/">Blog</a> • <a href="https://newpipe.schabi.org/press/">Press</a></p>
|
<p align="center"><a href="https://newpipe.schabi.org">Website</a> • <a href="https://newpipe.schabi.org/blog/">Blog</a> • <a href="https://newpipe.schabi.org/press/">Press</a></p>
|
||||||
<hr />
|
<hr>
|
||||||
WARNING: PUTTING NEWPIPE OR ANY FORK OF IT INTO GOOGLE PLAYSTORE VIOLATES THEIR TERMS OF CONDITIONS.
|
|
||||||
|
<b>WARNING: PUTTING NEWPIPE OR ANY FORK OF IT INTO GOOGLE PLAYSTORE VIOLATES THEIR TERMS OF CONDITIONS.</b>
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_1.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_1.png)
|
[<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_2.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_2.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_3.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_3.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_4.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_4.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_5.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_5.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_6.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_6.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_7.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_7.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_8.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_8.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_9.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_9.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/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)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
NewPipe does not use any Google framework libraries, or the YouTube API. It only parses the website in order to gain the information it needs. Therefore this app can be used on devices without Google Services installed. Also, you don't need a YouTube account to use NewPipe, and it's FLOSS.
|
NewPipe does not use any Google framework libraries, nor the YouTube API. Websites are only parsed to fetch required info, so this app can be used on devices without Google services installed. Also, you don't need a YouTube account to use NewPipe, which is copylefted libre software.
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* Search videos
|
* Search videos
|
||||||
* Display general information about a video
|
* Display general info about videos
|
||||||
* Watch YouTube videos
|
* Watch YouTube videos
|
||||||
* Listen to YouTube videos
|
* Listen to YouTube videos
|
||||||
* Popup mode (floating player)
|
* Popup mode (floating player)
|
||||||
* Select the streaming player to watch the video with
|
* Select streaming player to watch video with
|
||||||
* Download videos
|
* Download videos
|
||||||
* Download audio only
|
* Download audio only
|
||||||
* Open a video in Kodi
|
* Open a video in Kodi
|
||||||
* Show Next/Related videos
|
* Show next/related videos
|
||||||
* Search YouTube in a specific language
|
* Search YouTube in a specific language
|
||||||
* Watch/Block age restricted material
|
* Watch/Block age restricted material
|
||||||
* Display general information about channels
|
* Display general info about channels
|
||||||
* Search channels
|
* Search channels
|
||||||
* Watch videos from a channel
|
* Watch videos from a channel
|
||||||
* Orbot/Tor support (not yet directly)
|
* Orbot/Tor support (not yet directly)
|
||||||
* 1080p/2k/4k support
|
* 1080p/2K/4K support
|
||||||
* View history
|
* View history
|
||||||
* Subscribe to channels
|
* Subscribe to channels
|
||||||
* Search history
|
* Search history
|
||||||
* Search/Watch Playlists
|
* Search/watch playlists
|
||||||
* Watch as queues Playlists
|
* Watch as enqueued playlists
|
||||||
* Queuing videos
|
* Enqueue videos
|
||||||
* Local playlists
|
* Local playlists
|
||||||
* Subtitles
|
* Subtitles
|
||||||
* Multi-service support (eg. SoundCloud in NewPipe Beta)
|
* Multi-service support (e.g. SoundCloud \[beta\])
|
||||||
|
* Livestream support
|
||||||
|
|
||||||
### Coming Features
|
### Coming Features
|
||||||
|
|
||||||
* Livestream support
|
|
||||||
* Cast to UPnP and Cast
|
* Cast to UPnP and Cast
|
||||||
* Show comments
|
* Show comments
|
||||||
* ... and many more
|
* … and many more
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
Whether you have ideas, translations, design changes, code cleaning, or real heavy code changes, help is always welcome.
|
Whether you have ideas, translations, design changes, code cleaning, or real heavy code changes, help is always welcome.
|
||||||
@@ -77,26 +80,31 @@ The more is done the better it gets!
|
|||||||
If you'd like to get involved, check our [contribution notes](.github/CONTRIBUTING.md).
|
If you'd like to get involved, check our [contribution notes](.github/CONTRIBUTING.md).
|
||||||
|
|
||||||
## Donate
|
## Donate
|
||||||
If you like NewPipe we'd be happy about a donation. You can either donate via Bitcoin, Bountysource or Liberapay. For further information about donating to NewPipe, please visit our [website](https://newpipe.schabi.org/donate).
|
If you like NewPipe we'd be happy about a donation. You can either send bitcoin or donate via Bountysource or Liberapay. For further info on donating to NewPipe, please visit our [website](https://newpipe.schabi.org/donate).
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://bitcoin.org/img/icons/logotop.svg" alt="Bitcoin" /></td>
|
<td><img src="https://bitcoin.org/img/icons/logotop.svg" alt="Bitcoin"></td>
|
||||||
<td><img src="assets/bitcoin_qr_code.png" alt="Bitcoin QR Code" width="100px"/></td>
|
<td><img src="assets/bitcoin_qr_code.png" alt="Bitcoin QR code" width="100px"></td>
|
||||||
<td><samp>16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh</samp></td>
|
<td><samp>16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh</samp></td>
|
||||||
</tr>
|
</tr>
|
||||||
<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="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/"><img src="assets/liberapay_qr_code.png" alt="Visit NewPipe at liberapay.com" width="100px"></a></td>
|
||||||
<td><a href="https://liberapay.com/TeamNewPipe/donate"><img src="assets/liberapay_donate_button.svg" alt="Donate via Liberapay" height="35px" /></a></td>
|
<td><a href="https://liberapay.com/TeamNewPipe/donate"><img src="assets/liberapay_donate_button.svg" alt="Donate via Liberapay" height="35px"></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<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="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"><img src="assets/bountysource_qr_code.png" alt="Visit NewPipe at bountysource.com" width="100px"></a></td>
|
||||||
<td><a href="https://www.bountysource.com/teams/newpipe/issues"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f" height="30px" alt="Check out how many bounties you can earn." /></a></td>
|
<td><a href="https://www.bountysource.com/teams/newpipe/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>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
## Privacy Policy
|
||||||
|
|
||||||
|
The NewPipe project aims to provide a private, anonymous experience for using media web services.
|
||||||
|
Therefore, the app does not collect any data without your consent. NewPipe's privacy policy explains in detail what data is sent and stored when you send a crash report, or comment in our blog. You can find the document [here](https://newpipe.schabi.org/legal/privacy/).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[](http://www.gnu.org/licenses/gpl-3.0.en.html)
|
[](http://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdkVersion 28
|
||||||
buildToolsVersion '27.0.3'
|
buildToolsVersion '28.0.3'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.schabi.newpipe"
|
applicationId "org.schabi.newpipe"
|
||||||
minSdkVersion 15
|
minSdkVersion 19
|
||||||
targetSdkVersion 27
|
targetSdkVersion 28
|
||||||
versionCode 68
|
versionCode 70
|
||||||
versionName "0.14.1"
|
versionName "0.15.0"
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@@ -22,7 +22,6 @@ android {
|
|||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
|
|
||||||
debuggable true
|
debuggable true
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
}
|
}
|
||||||
@@ -41,62 +40,61 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
supportLibVersion = '27.1.1'
|
supportLibVersion = '28.0.0'
|
||||||
exoPlayerLibVersion = '2.8.2'
|
exoPlayerLibVersion = '2.8.4' //2.9.0
|
||||||
roomDbLibVersion = '1.1.1'
|
roomDbLibVersion = '1.1.1'
|
||||||
leakCanaryLibVersion = '1.5.4'
|
leakCanaryLibVersion = '1.5.4' //1.6.1
|
||||||
okHttpLibVersion = '3.10.0'
|
okHttpLibVersion = '3.11.0'
|
||||||
icepickLibVersion = '3.2.0'
|
icepickLibVersion = '3.2.0'
|
||||||
stethoLibVersion = '1.5.0'
|
stethoLibVersion = '1.5.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2') {
|
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', {
|
||||||
exclude module: 'support-annotations'
|
exclude module: 'support-annotations'
|
||||||
}
|
})
|
||||||
|
|
||||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:66c3c3f45241d4b0c909'
|
implementation 'com.github.TeamNewPipe:NewPipeExtractor:99915e4527c0'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation 'org.mockito:mockito-core:2.8.9'
|
testImplementation 'org.mockito:mockito-core:2.23.0'
|
||||||
|
|
||||||
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
implementation "com.android.support:appcompat-v7:${supportLibVersion}"
|
||||||
implementation "com.android.support:support-v4:$supportLibVersion"
|
implementation "com.android.support:support-v4:${supportLibVersion}"
|
||||||
implementation "com.android.support:design:$supportLibVersion"
|
implementation "com.android.support:design:${supportLibVersion}"
|
||||||
implementation "com.android.support:recyclerview-v7:$supportLibVersion"
|
implementation "com.android.support:recyclerview-v7:${supportLibVersion}"
|
||||||
implementation "com.android.support:preference-v14:$supportLibVersion"
|
implementation "com.android.support:preference-v14:${supportLibVersion}"
|
||||||
|
implementation "com.android.support:cardview-v7:${supportLibVersion}"
|
||||||
|
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||||
|
|
||||||
implementation 'ch.acra:acra:4.9.2'
|
implementation 'ch.acra:acra:4.9.2' //4.11
|
||||||
|
|
||||||
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||||
implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1'
|
implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1'
|
||||||
implementation 'com.nononsenseapps:filepicker:4.2.1'
|
implementation 'com.nononsenseapps:filepicker:4.2.1'
|
||||||
|
|
||||||
implementation "com.google.android.exoplayer:exoplayer:$exoPlayerLibVersion"
|
implementation "com.google.android.exoplayer:exoplayer:${exoPlayerLibVersion}"
|
||||||
implementation "com.google.android.exoplayer:extension-mediasession:$exoPlayerLibVersion"
|
implementation "com.google.android.exoplayer:extension-mediasession:${exoPlayerLibVersion}"
|
||||||
|
|
||||||
debugImplementation "com.facebook.stetho:stetho:$stethoLibVersion"
|
debugImplementation "com.facebook.stetho:stetho:${stethoLibVersion}"
|
||||||
debugImplementation "com.facebook.stetho:stetho-urlconnection:$stethoLibVersion"
|
debugImplementation "com.facebook.stetho:stetho-urlconnection:${stethoLibVersion}"
|
||||||
debugImplementation 'com.android.support:multidex:1.0.3'
|
debugImplementation 'com.android.support:multidex:1.0.3'
|
||||||
|
|
||||||
implementation 'io.reactivex.rxjava2:rxjava:2.1.14'
|
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
|
||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
|
||||||
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
|
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
|
||||||
|
|
||||||
implementation "android.arch.persistence.room:runtime:$roomDbLibVersion"
|
implementation "android.arch.persistence.room:runtime:${roomDbLibVersion}"
|
||||||
implementation "android.arch.persistence.room:rxjava2:$roomDbLibVersion"
|
implementation "android.arch.persistence.room:rxjava2:${roomDbLibVersion}"
|
||||||
annotationProcessor "android.arch.persistence.room:compiler:$roomDbLibVersion"
|
annotationProcessor "android.arch.persistence.room:compiler:${roomDbLibVersion}"
|
||||||
|
|
||||||
implementation "frankiesardo:icepick:$icepickLibVersion"
|
implementation "frankiesardo:icepick:${icepickLibVersion}"
|
||||||
annotationProcessor "frankiesardo:icepick-processor:$icepickLibVersion"
|
annotationProcessor "frankiesardo:icepick-processor:${icepickLibVersion}"
|
||||||
|
|
||||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryLibVersion"
|
debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakCanaryLibVersion}"
|
||||||
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryLibVersion"
|
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryLibVersion}"
|
||||||
|
|
||||||
|
implementation "com.squareup.okhttp3:okhttp:${okHttpLibVersion}"
|
||||||
implementation "com.squareup.okhttp3:okhttp:$okHttpLibVersion"
|
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoLibVersion}"
|
||||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:$stethoLibVersion"
|
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
|
||||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
|
@@ -5,6 +5,7 @@ import android.app.NotificationChannel;
|
|||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ import org.acra.config.ConfigurationBuilder;
|
|||||||
import org.acra.sender.ReportSenderFactory;
|
import org.acra.sender.ReportSenderFactory;
|
||||||
import org.schabi.newpipe.extractor.Downloader;
|
import org.schabi.newpipe.extractor.Downloader;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.utils.Localization;
|
||||||
import org.schabi.newpipe.report.AcraReportSenderFactory;
|
import org.schabi.newpipe.report.AcraReportSenderFactory;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
@@ -65,7 +67,8 @@ public class App extends Application {
|
|||||||
private RefWatcher refWatcher;
|
private RefWatcher refWatcher;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static final Class<? extends ReportSenderFactory>[] reportSenderFactoryClasses = new Class[]{AcraReportSenderFactory.class};
|
private static final Class<? extends ReportSenderFactory>[]
|
||||||
|
reportSenderFactoryClasses = new Class[]{AcraReportSenderFactory.class};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void attachBaseContext(Context base) {
|
protected void attachBaseContext(Context base) {
|
||||||
@@ -88,7 +91,8 @@ public class App extends Application {
|
|||||||
// Initialize settings first because others inits can use its values
|
// Initialize settings first because others inits can use its values
|
||||||
SettingsActivity.initSettings(this);
|
SettingsActivity.initSettings(this);
|
||||||
|
|
||||||
NewPipe.init(getDownloader());
|
NewPipe.init(getDownloader(),
|
||||||
|
org.schabi.newpipe.util.Localization.getPreferredExtractorLocal(this));
|
||||||
StateSaver.init(this);
|
StateSaver.init(this);
|
||||||
initNotificationChannel();
|
initNotificationChannel();
|
||||||
|
|
||||||
@@ -106,7 +110,7 @@ public class App extends Application {
|
|||||||
// https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling
|
// https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling
|
||||||
RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
|
RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(@NonNull Throwable throwable) throws Exception {
|
public void accept(@NonNull Throwable throwable) {
|
||||||
Log.e(TAG, "RxJavaPlugins.ErrorHandler called with -> : " +
|
Log.e(TAG, "RxJavaPlugins.ErrorHandler called with -> : " +
|
||||||
"throwable = [" + throwable.getClass().getName() + "]");
|
"throwable = [" + throwable.getClass().getName() + "]");
|
||||||
|
|
||||||
@@ -180,7 +184,11 @@ public class App extends Application {
|
|||||||
ACRA.init(this, acraConfig);
|
ACRA.init(this, acraConfig);
|
||||||
} catch (ACRAConfigurationException ace) {
|
} catch (ACRAConfigurationException ace) {
|
||||||
ace.printStackTrace();
|
ace.printStackTrace();
|
||||||
ErrorActivity.reportError(this, ace, null, null, ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
ErrorActivity.reportError(this,
|
||||||
|
ace,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||||
"Could not initialize ACRA crash report", R.string.app_ui_crash));
|
"Could not initialize ACRA crash report", R.string.app_ui_crash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +208,8 @@ public class App extends Application {
|
|||||||
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
|
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
|
||||||
mChannel.setDescription(description);
|
mChannel.setDescription(description);
|
||||||
|
|
||||||
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager mNotificationManager =
|
||||||
|
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
mNotificationManager.createNotificationChannel(mChannel);
|
mNotificationManager.createNotificationChannel(mChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,14 +12,12 @@ import android.view.View;
|
|||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.squareup.leakcanary.RefWatcher;
|
import com.squareup.leakcanary.RefWatcher;
|
||||||
|
|
||||||
import org.schabi.newpipe.report.UserAction;
|
|
||||||
|
|
||||||
import icepick.Icepick;
|
import icepick.Icepick;
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
|
|
||||||
public abstract class BaseFragment extends Fragment {
|
public abstract class BaseFragment extends Fragment {
|
||||||
protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
|
protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
|
||||||
protected boolean DEBUG = MainActivity.DEBUG;
|
protected final boolean DEBUG = MainActivity.DEBUG;
|
||||||
|
|
||||||
protected AppCompatActivity activity;
|
protected AppCompatActivity activity;
|
||||||
public static final ImageLoader imageLoader = ImageLoader.getInstance();
|
public static final ImageLoader imageLoader = ImageLoader.getInstance();
|
||||||
|
@@ -4,6 +4,7 @@ import android.support.annotation.Nullable;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||||
|
import org.schabi.newpipe.extractor.utils.Localization;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -43,7 +44,7 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader {
|
|||||||
|
|
||||||
private static Downloader instance;
|
private static Downloader instance;
|
||||||
private String mCookies;
|
private String mCookies;
|
||||||
private OkHttpClient client;
|
private final OkHttpClient client;
|
||||||
|
|
||||||
private Downloader(OkHttpClient.Builder builder) {
|
private Downloader(OkHttpClient.Builder builder) {
|
||||||
this.client = builder
|
this.client = builder
|
||||||
@@ -88,7 +89,8 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader {
|
|||||||
.build();
|
.build();
|
||||||
response = client.newCall(request).execute();
|
response = client.newCall(request).execute();
|
||||||
|
|
||||||
return Long.parseLong(response.header("Content-Length"));
|
String contentLength = response.header("Content-Length");
|
||||||
|
return contentLength == null ? -1 : Long.parseLong(contentLength);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new IOException("Invalid content length", e);
|
throw new IOException("Invalid content length", e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -103,13 +105,13 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader {
|
|||||||
* but set the HTTP header field "Accept-Language" to the supplied string.
|
* but set the HTTP header field "Accept-Language" to the supplied string.
|
||||||
*
|
*
|
||||||
* @param siteUrl the URL of the text file to return the contents of
|
* @param siteUrl the URL of the text file to return the contents of
|
||||||
* @param language the language (usually a 2-character code) to set as the preferred language
|
* @param localization the language and country (usually a 2-character code) to set
|
||||||
* @return the contents of the specified text file
|
* @return the contents of the specified text file
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String download(String siteUrl, String language) throws IOException, ReCaptchaException {
|
public String download(String siteUrl, Localization localization) throws IOException, ReCaptchaException {
|
||||||
Map<String, String> requestProperties = new HashMap<>();
|
Map<String, String> requestProperties = new HashMap<>();
|
||||||
requestProperties.put("Accept-Language", language);
|
requestProperties.put("Accept-Language", localization.getLanguage());
|
||||||
return download(siteUrl, requestProperties);
|
return download(siteUrl, requestProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,7 +23,6 @@ package org.schabi.newpipe;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -66,8 +65,6 @@ import org.schabi.newpipe.util.ServiceHelper;
|
|||||||
import org.schabi.newpipe.util.StateSaver;
|
import org.schabi.newpipe.util.StateSaver;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.InfoItem.InfoType.PLAYLIST;
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||||
|
@@ -85,7 +85,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ReCaptchaWebViewClient extends WebViewClient {
|
private class ReCaptchaWebViewClient extends WebViewClient {
|
||||||
private Activity context;
|
private final Activity context;
|
||||||
private String mCookies;
|
private String mCookies;
|
||||||
|
|
||||||
ReCaptchaWebViewClient(Activity ctx) {
|
ReCaptchaWebViewClient(Activity ctx) {
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.FragmentManager;
|
|
||||||
import android.app.IntentService;
|
import android.app.IntentService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -13,7 +12,6 @@ import android.preference.PreferenceManager;
|
|||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
@@ -38,7 +36,6 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
|||||||
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.fragments.detail.VideoDetailFragment;
|
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||||
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
@@ -51,14 +48,12 @@ import org.schabi.newpipe.util.NavigationHelper;
|
|||||||
import org.schabi.newpipe.util.PermissionHelper;
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observer;
|
|
||||||
|
|
||||||
import icepick.Icepick;
|
import icepick.Icepick;
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
@@ -86,7 +81,7 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
protected int selectedPreviously = -1;
|
protected int selectedPreviously = -1;
|
||||||
|
|
||||||
protected String currentUrl;
|
protected String currentUrl;
|
||||||
protected CompositeDisposable disposables = new CompositeDisposable();
|
protected final CompositeDisposable disposables = new CompositeDisposable();
|
||||||
|
|
||||||
private boolean selectionIsDownload = false;
|
private boolean selectionIsDownload = false;
|
||||||
|
|
||||||
@@ -184,12 +179,16 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
if (selectedChoiceKey.equals(alwaysAskKey)) {
|
if (selectedChoiceKey.equals(alwaysAskKey)) {
|
||||||
final List<AdapterChoiceItem> choices = getChoicesForService(currentService, currentLinkType);
|
final List<AdapterChoiceItem> choices = getChoicesForService(currentService, currentLinkType);
|
||||||
|
|
||||||
if (choices.size() == 1) {
|
switch (choices.size()) {
|
||||||
handleChoice(choices.get(0).key);
|
case 1:
|
||||||
} else if (choices.size() == 0) {
|
handleChoice(choices.get(0).key);
|
||||||
handleChoice(showInfoKey);
|
break;
|
||||||
} else {
|
case 0:
|
||||||
showDialog(choices);
|
handleChoice(showInfoKey);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
showDialog(choices);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (selectedChoiceKey.equals(showInfoKey)) {
|
} else if (selectedChoiceKey.equals(showInfoKey)) {
|
||||||
handleChoice(showInfoKey);
|
handleChoice(showInfoKey);
|
||||||
@@ -543,8 +542,7 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
boolean isExtVideoEnabled = preferences.getBoolean(getString(R.string.use_external_video_player_key), false);
|
boolean isExtVideoEnabled = preferences.getBoolean(getString(R.string.use_external_video_player_key), false);
|
||||||
boolean isExtAudioEnabled = preferences.getBoolean(getString(R.string.use_external_audio_player_key), false);
|
boolean isExtAudioEnabled = preferences.getBoolean(getString(R.string.use_external_audio_player_key), false);;
|
||||||
boolean useOldVideoPlayer = PlayerHelper.isUsingOldPlayer(this);
|
|
||||||
|
|
||||||
PlayQueue playQueue;
|
PlayQueue playQueue;
|
||||||
String playerChoice = choice.playerChoice;
|
String playerChoice = choice.playerChoice;
|
||||||
@@ -556,9 +554,6 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
} else if (playerChoice.equals(videoPlayerKey) && isExtVideoEnabled) {
|
} else if (playerChoice.equals(videoPlayerKey) && isExtVideoEnabled) {
|
||||||
NavigationHelper.playOnExternalVideoPlayer(this, (StreamInfo) info);
|
NavigationHelper.playOnExternalVideoPlayer(this, (StreamInfo) info);
|
||||||
|
|
||||||
} else if (playerChoice.equals(videoPlayerKey) && useOldVideoPlayer) {
|
|
||||||
NavigationHelper.playOnOldVideoPlayer(this, (StreamInfo) info);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
playQueue = new SinglePlayQueue((StreamInfo) info);
|
playQueue = new SinglePlayQueue((StreamInfo) info);
|
||||||
|
|
||||||
|
@@ -4,7 +4,6 @@ import android.app.Activity;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
@@ -17,7 +16,7 @@ import java.lang.ref.WeakReference;
|
|||||||
|
|
||||||
public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
|
public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
|
||||||
|
|
||||||
WeakReference<Activity> weakReference;
|
final WeakReference<Activity> weakReference;
|
||||||
private License license;
|
private License license;
|
||||||
|
|
||||||
public LicenseFragmentHelper(@Nullable Activity activity) {
|
public LicenseFragmentHelper(@Nullable Activity activity) {
|
||||||
@@ -78,18 +77,18 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
|
|||||||
throw new NullPointerException("license is null");
|
throw new NullPointerException("license is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
String licenseContent = "";
|
StringBuilder licenseContent = new StringBuilder();
|
||||||
String webViewData;
|
String webViewData;
|
||||||
try {
|
try {
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(context.getAssets().open(license.getFilename()), "UTF-8"));
|
BufferedReader in = new BufferedReader(new InputStreamReader(context.getAssets().open(license.getFilename()), "UTF-8"));
|
||||||
String str;
|
String str;
|
||||||
while ((str = in.readLine()) != null) {
|
while ((str = in.readLine()) != null) {
|
||||||
licenseContent += str;
|
licenseContent.append(str);
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
// split the HTML file and insert the stylesheet into the HEAD of the file
|
// split the HTML file and insert the stylesheet into the HEAD of the file
|
||||||
String[] insert = licenseContent.split("</head>");
|
String[] insert = licenseContent.toString().split("</head>");
|
||||||
webViewData = insert[0] + "<style type=\"text/css\">"
|
webViewData = insert[0] + "<style type=\"text/css\">"
|
||||||
+ getLicenseStylesheet(context) + "</style></head>"
|
+ getLicenseStylesheet(context) + "</style></head>"
|
||||||
+ insert[1];
|
+ insert[1];
|
||||||
|
@@ -30,7 +30,7 @@ public interface BasicDAO<Entity> {
|
|||||||
|
|
||||||
/* Deletes */
|
/* Deletes */
|
||||||
@Delete
|
@Delete
|
||||||
int delete(final Entity entity);
|
void delete(final Entity entity);
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
int delete(final Collection<Entity> entities);
|
int delete(final Collection<Entity> entities);
|
||||||
@@ -42,5 +42,5 @@ public interface BasicDAO<Entity> {
|
|||||||
int update(final Entity entity);
|
int update(final Entity entity);
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
int update(final Collection<Entity> entities);
|
void update(final Collection<Entity> entities);
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ import android.arch.persistence.room.Dao;
|
|||||||
import android.arch.persistence.room.Query;
|
import android.arch.persistence.room.Query;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.schabi.newpipe.database.BasicDAO;
|
|
||||||
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
|
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@@ -5,7 +5,6 @@ import android.arch.persistence.room.Dao;
|
|||||||
import android.arch.persistence.room.Query;
|
import android.arch.persistence.room.Query;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.schabi.newpipe.database.BasicDAO;
|
|
||||||
import org.schabi.newpipe.database.history.model.StreamHistoryEntry;
|
import org.schabi.newpipe.database.history.model.StreamHistoryEntry;
|
||||||
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
||||||
import org.schabi.newpipe.database.history.model.StreamHistoryEntity;
|
import org.schabi.newpipe.database.history.model.StreamHistoryEntity;
|
||||||
|
@@ -2,7 +2,6 @@ package org.schabi.newpipe.database.playlist.dao;
|
|||||||
|
|
||||||
import android.arch.persistence.room.Dao;
|
import android.arch.persistence.room.Dao;
|
||||||
import android.arch.persistence.room.Query;
|
import android.arch.persistence.room.Query;
|
||||||
import android.arch.persistence.room.Transaction;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.database.BasicDAO;
|
import org.schabi.newpipe.database.BasicDAO;
|
||||||
import org.schabi.newpipe.database.playlist.model.PlaylistEntity;
|
import org.schabi.newpipe.database.playlist.model.PlaylistEntity;
|
||||||
@@ -12,7 +11,6 @@ import java.util.List;
|
|||||||
import io.reactivex.Flowable;
|
import io.reactivex.Flowable;
|
||||||
|
|
||||||
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID;
|
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID;
|
||||||
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME;
|
|
||||||
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE;
|
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE;
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@@ -8,7 +8,6 @@ import org.schabi.newpipe.database.BasicDAO;
|
|||||||
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
||||||
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
||||||
import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity;
|
import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity;
|
||||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@@ -5,8 +5,6 @@ import android.arch.persistence.room.Entity;
|
|||||||
import android.arch.persistence.room.Index;
|
import android.arch.persistence.room.Index;
|
||||||
import android.arch.persistence.room.PrimaryKey;
|
import android.arch.persistence.room.PrimaryKey;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME;
|
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME;
|
||||||
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE;
|
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE;
|
||||||
|
|
||||||
|
@@ -6,7 +6,6 @@ import android.arch.persistence.room.Ignore;
|
|||||||
import android.arch.persistence.room.Index;
|
import android.arch.persistence.room.Index;
|
||||||
import android.arch.persistence.room.PrimaryKey;
|
import android.arch.persistence.room.PrimaryKey;
|
||||||
|
|
||||||
import org.schabi.newpipe.database.LocalItem;
|
|
||||||
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
|
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
|
@@ -10,7 +10,6 @@ import org.schabi.newpipe.database.BasicDAO;
|
|||||||
import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity;
|
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.history.model.StreamHistoryEntity;
|
import org.schabi.newpipe.database.history.model.StreamHistoryEntity;
|
||||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -23,7 +22,6 @@ import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_SERVI
|
|||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
|
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL;
|
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL;
|
||||||
import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_HISTORY_TABLE;
|
import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_HISTORY_TABLE;
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
|
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
public abstract class StreamDAO implements BasicDAO<StreamEntity> {
|
public abstract class StreamDAO implements BasicDAO<StreamEntity> {
|
||||||
|
@@ -1,158 +0,0 @@
|
|||||||
package org.schabi.newpipe.download;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.design.widget.BaseTransientBottomBar;
|
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import io.reactivex.Completable;
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import io.reactivex.subjects.PublishSubject;
|
|
||||||
import us.shandian.giga.get.DownloadManager;
|
|
||||||
import us.shandian.giga.get.DownloadMission;
|
|
||||||
|
|
||||||
public class DeleteDownloadManager {
|
|
||||||
|
|
||||||
private static final String KEY_STATE = "delete_manager_state";
|
|
||||||
|
|
||||||
private View mView;
|
|
||||||
private HashSet<String> mPendingMap;
|
|
||||||
private List<Disposable> mDisposableList;
|
|
||||||
private DownloadManager mDownloadManager;
|
|
||||||
private PublishSubject<DownloadMission> publishSubject = PublishSubject.create();
|
|
||||||
|
|
||||||
DeleteDownloadManager(Activity activity) {
|
|
||||||
mPendingMap = new HashSet<>();
|
|
||||||
mDisposableList = new ArrayList<>();
|
|
||||||
mView = activity.findViewById(android.R.id.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<DownloadMission> getUndoObservable() {
|
|
||||||
return publishSubject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(@NonNull DownloadMission mission) {
|
|
||||||
return mPendingMap.contains(mission.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(@NonNull DownloadMission mission) {
|
|
||||||
mPendingMap.add(mission.url);
|
|
||||||
|
|
||||||
if (mPendingMap.size() == 1) {
|
|
||||||
showUndoDeleteSnackbar(mission);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloadManager(@NonNull DownloadManager downloadManager) {
|
|
||||||
mDownloadManager = downloadManager;
|
|
||||||
|
|
||||||
if (mPendingMap.size() < 1) return;
|
|
||||||
|
|
||||||
showUndoDeleteSnackbar();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void restoreState(@Nullable Bundle savedInstanceState) {
|
|
||||||
if (savedInstanceState == null) return;
|
|
||||||
|
|
||||||
List<String> list = savedInstanceState.getStringArrayList(KEY_STATE);
|
|
||||||
if (list != null) {
|
|
||||||
mPendingMap.addAll(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveState(@Nullable Bundle outState) {
|
|
||||||
if (outState == null) return;
|
|
||||||
|
|
||||||
for (Disposable disposable : mDisposableList) {
|
|
||||||
disposable.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
outState.putStringArrayList(KEY_STATE, new ArrayList<>(mPendingMap));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showUndoDeleteSnackbar() {
|
|
||||||
if (mPendingMap.size() < 1) return;
|
|
||||||
|
|
||||||
String url = mPendingMap.iterator().next();
|
|
||||||
|
|
||||||
for (int i = 0; i < mDownloadManager.getCount(); i++) {
|
|
||||||
DownloadMission mission = mDownloadManager.getMission(i);
|
|
||||||
if (url.equals(mission.url)) {
|
|
||||||
showUndoDeleteSnackbar(mission);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showUndoDeleteSnackbar(@NonNull DownloadMission mission) {
|
|
||||||
final Snackbar snackbar = Snackbar.make(mView, mission.name, Snackbar.LENGTH_INDEFINITE);
|
|
||||||
final Disposable disposable = Observable.timer(3, TimeUnit.SECONDS)
|
|
||||||
.subscribeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(l -> snackbar.dismiss());
|
|
||||||
|
|
||||||
mDisposableList.add(disposable);
|
|
||||||
|
|
||||||
snackbar.setAction(R.string.undo, v -> {
|
|
||||||
mPendingMap.remove(mission.url);
|
|
||||||
publishSubject.onNext(mission);
|
|
||||||
disposable.dispose();
|
|
||||||
snackbar.dismiss();
|
|
||||||
});
|
|
||||||
|
|
||||||
snackbar.addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
|
|
||||||
@Override
|
|
||||||
public void onDismissed(Snackbar transientBottomBar, int event) {
|
|
||||||
if (!disposable.isDisposed()) {
|
|
||||||
Completable.fromAction(() -> deletePending(mission))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.subscribe();
|
|
||||||
}
|
|
||||||
mPendingMap.remove(mission.url);
|
|
||||||
snackbar.removeCallback(this);
|
|
||||||
mDisposableList.remove(disposable);
|
|
||||||
showUndoDeleteSnackbar();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
snackbar.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deletePending() {
|
|
||||||
if (mPendingMap.size() < 1) return;
|
|
||||||
|
|
||||||
HashSet<Integer> idSet = new HashSet<>();
|
|
||||||
for (int i = 0; i < mDownloadManager.getCount(); i++) {
|
|
||||||
if (contains(mDownloadManager.getMission(i))) {
|
|
||||||
idSet.add(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Integer id : idSet) {
|
|
||||||
mDownloadManager.deleteMission(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
mPendingMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deletePending(@NonNull DownloadMission mission) {
|
|
||||||
for (int i = 0; i < mDownloadManager.getCount(); i++) {
|
|
||||||
if (mission.url.equals(mDownloadManager.getMission(i).url)) {
|
|
||||||
mDownloadManager.deleteMission(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -15,16 +15,12 @@ import org.schabi.newpipe.R;
|
|||||||
import org.schabi.newpipe.settings.SettingsActivity;
|
import org.schabi.newpipe.settings.SettingsActivity;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import io.reactivex.Completable;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import us.shandian.giga.service.DownloadManagerService;
|
import us.shandian.giga.service.DownloadManagerService;
|
||||||
import us.shandian.giga.ui.fragment.AllMissionsFragment;
|
|
||||||
import us.shandian.giga.ui.fragment.MissionsFragment;
|
import us.shandian.giga.ui.fragment.MissionsFragment;
|
||||||
|
|
||||||
public class DownloadActivity extends AppCompatActivity {
|
public class DownloadActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag";
|
private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag";
|
||||||
private DeleteDownloadManager mDeleteDownloadManager;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -47,32 +43,17 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
actionBar.setDisplayShowTitleEnabled(true);
|
actionBar.setDisplayShowTitleEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDeleteDownloadManager = new DeleteDownloadManager(this);
|
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
mDeleteDownloadManager.restoreState(savedInstanceState);
|
@Override
|
||||||
|
public void onGlobalLayout() {
|
||||||
MissionsFragment fragment = (MissionsFragment) getFragmentManager().findFragmentByTag(MISSIONS_FRAGMENT_TAG);
|
updateFragments();
|
||||||
if (fragment != null) {
|
getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||||
fragment.setDeleteManager(mDeleteDownloadManager);
|
}
|
||||||
} else {
|
});
|
||||||
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
|
||||||
@Override
|
|
||||||
public void onGlobalLayout() {
|
|
||||||
updateFragments();
|
|
||||||
getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
|
||||||
mDeleteDownloadManager.saveState(outState);
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFragments() {
|
private void updateFragments() {
|
||||||
MissionsFragment fragment = new AllMissionsFragment();
|
MissionsFragment fragment = new MissionsFragment();
|
||||||
fragment.setDeleteManager(mDeleteDownloadManager);
|
|
||||||
|
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
.replace(R.id.frame, fragment, MISSIONS_FRAGMENT_TAG)
|
.replace(R.id.frame, fragment, MISSIONS_FRAGMENT_TAG)
|
||||||
@@ -99,7 +80,6 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
case R.id.action_settings: {
|
case R.id.action_settings: {
|
||||||
Intent intent = new Intent(this, SettingsActivity.class);
|
Intent intent = new Intent(this, SettingsActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
deletePending();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -108,14 +88,7 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onRestoreInstanceState(Bundle inState){
|
||||||
super.onBackPressed();
|
super.onRestoreInstanceState(inState);
|
||||||
deletePending();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deletePending() {
|
|
||||||
Completable.fromAction(mDeleteDownloadManager::deletePending)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.subscribe();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.functions.Consumer;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ package org.schabi.newpipe.fragments;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@@ -3,9 +3,9 @@ package org.schabi.newpipe.fragments.detail;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
class StackItem implements Serializable {
|
class StackItem implements Serializable {
|
||||||
private int serviceId;
|
private final int serviceId;
|
||||||
private String title;
|
private String title;
|
||||||
private String url;
|
private final String url;
|
||||||
|
|
||||||
StackItem(int serviceId, String url, String title) {
|
StackItem(int serviceId, String url, String title) {
|
||||||
this.serviceId = serviceId;
|
this.serviceId = serviceId;
|
||||||
|
@@ -33,12 +33,14 @@ import android.view.MenuItem;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewParent;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@@ -61,22 +63,20 @@ 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.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
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.fragments.BackPressable;
|
import org.schabi.newpipe.fragments.BackPressable;
|
||||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
|
||||||
import org.schabi.newpipe.util.StreamItemAdapter;
|
|
||||||
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
|
|
||||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||||
|
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
||||||
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.player.MainVideoPlayer;
|
import org.schabi.newpipe.player.MainVideoPlayer;
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||||
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||||
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
@@ -87,6 +87,8 @@ import org.schabi.newpipe.util.Localization;
|
|||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
import org.schabi.newpipe.util.OnClickGesture;
|
import org.schabi.newpipe.util.OnClickGesture;
|
||||||
import org.schabi.newpipe.util.PermissionHelper;
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
|
import org.schabi.newpipe.util.StreamItemAdapter;
|
||||||
|
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -154,6 +156,7 @@ public class VideoDetailFragment
|
|||||||
|
|
||||||
private View videoTitleRoot;
|
private View videoTitleRoot;
|
||||||
private TextView videoTitleTextView;
|
private TextView videoTitleTextView;
|
||||||
|
@Nullable
|
||||||
private ImageView videoTitleToggleArrow;
|
private ImageView videoTitleToggleArrow;
|
||||||
private TextView videoCountView;
|
private TextView videoCountView;
|
||||||
|
|
||||||
@@ -368,14 +371,14 @@ public class VideoDetailFragment
|
|||||||
Log.w(TAG, "Can't open channel because we got no channel URL");
|
Log.w(TAG, "Can't open channel because we got no channel URL");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
NavigationHelper.openChannelFragment(
|
NavigationHelper.openChannelFragment(
|
||||||
getFragmentManager(),
|
getFragmentManager(),
|
||||||
currentInfo.getServiceId(),
|
currentInfo.getServiceId(),
|
||||||
currentInfo.getUploaderUrl(),
|
currentInfo.getUploaderUrl(),
|
||||||
currentInfo.getUploaderName());
|
currentInfo.getUploaderName());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.detail_thumbnail_root_layout:
|
case R.id.detail_thumbnail_root_layout:
|
||||||
@@ -415,14 +418,16 @@ public class VideoDetailFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void toggleTitleAndDescription() {
|
private void toggleTitleAndDescription() {
|
||||||
if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) {
|
if (videoTitleToggleArrow != null) { //it is null for tablets
|
||||||
videoTitleTextView.setMaxLines(1);
|
if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) {
|
||||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
videoTitleTextView.setMaxLines(1);
|
||||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||||
} else {
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
||||||
videoTitleTextView.setMaxLines(10);
|
} else {
|
||||||
videoDescriptionRootLayout.setVisibility(View.VISIBLE);
|
videoTitleTextView.setMaxLines(10);
|
||||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_up);
|
videoDescriptionRootLayout.setVisibility(View.VISIBLE);
|
||||||
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_up);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,8 +627,11 @@ public class VideoDetailFragment
|
|||||||
relatedStreamsView.addView(
|
relatedStreamsView.addView(
|
||||||
infoItemBuilder.buildView(relatedStreamsView, info.getNextVideo()));
|
infoItemBuilder.buildView(relatedStreamsView, info.getNextVideo()));
|
||||||
relatedStreamsView.addView(getSeparatorView());
|
relatedStreamsView.addView(getSeparatorView());
|
||||||
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
setRelatedStreamsVisibility(View.VISIBLE);
|
||||||
} else nextStreamTitle.setVisibility(View.GONE);
|
} else {
|
||||||
|
nextStreamTitle.setVisibility(View.GONE);
|
||||||
|
setRelatedStreamsVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
if (info.getRelatedStreams() != null
|
if (info.getRelatedStreams() != null
|
||||||
&& !info.getRelatedStreams().isEmpty() && showRelatedStreams) {
|
&& !info.getRelatedStreams().isEmpty() && showRelatedStreams) {
|
||||||
@@ -639,13 +647,13 @@ public class VideoDetailFragment
|
|||||||
}
|
}
|
||||||
//if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms");
|
//if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms");
|
||||||
|
|
||||||
relatedStreamRootLayout.setVisibility(View.VISIBLE);
|
setRelatedStreamsVisibility(View.VISIBLE);
|
||||||
relatedStreamExpandButton.setVisibility(View.VISIBLE);
|
relatedStreamExpandButton.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(
|
relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(
|
||||||
activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand)));
|
||||||
} else {
|
} else {
|
||||||
if (info.getNextVideo() == null) relatedStreamRootLayout.setVisibility(View.GONE);
|
if (info.getNextVideo() == null) setRelatedStreamsVisibility(View.GONE);
|
||||||
relatedStreamExpandButton.setVisibility(View.GONE);
|
relatedStreamExpandButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -737,7 +745,7 @@ public class VideoDetailFragment
|
|||||||
sortedVideoStreams = ListHelper.getSortedStreamVideosList(activity, info.getVideoStreams(), info.getVideoOnlyStreams(), false);
|
sortedVideoStreams = ListHelper.getSortedStreamVideosList(activity, info.getVideoStreams(), info.getVideoOnlyStreams(), false);
|
||||||
selectedVideoStreamIndex = ListHelper.getDefaultResolutionIndex(activity, sortedVideoStreams);
|
selectedVideoStreamIndex = ListHelper.getDefaultResolutionIndex(activity, sortedVideoStreams);
|
||||||
|
|
||||||
final StreamItemAdapter<VideoStream> streamsAdapter = new StreamItemAdapter<>(activity, new StreamSizeWrapper<>(sortedVideoStreams), isExternalPlayerEnabled);
|
final StreamItemAdapter<VideoStream, Stream> streamsAdapter = new StreamItemAdapter<>(activity, new StreamSizeWrapper<>(sortedVideoStreams, activity), isExternalPlayerEnabled);
|
||||||
spinnerToolbar.setAdapter(streamsAdapter);
|
spinnerToolbar.setAdapter(streamsAdapter);
|
||||||
spinnerToolbar.setSelection(selectedVideoStreamIndex);
|
spinnerToolbar.setSelection(selectedVideoStreamIndex);
|
||||||
spinnerToolbar.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
spinnerToolbar.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@@ -760,7 +768,7 @@ public class VideoDetailFragment
|
|||||||
* Stack that contains the "navigation history".<br>
|
* Stack that contains the "navigation history".<br>
|
||||||
* The peek is the current video.
|
* The peek is the current video.
|
||||||
*/
|
*/
|
||||||
protected LinkedList<StackItem> stack = new LinkedList<>();
|
protected final LinkedList<StackItem> stack = new LinkedList<>();
|
||||||
|
|
||||||
public void clearHistory() {
|
public void clearHistory() {
|
||||||
stack.clear();
|
stack.clear();
|
||||||
@@ -913,7 +921,7 @@ public class VideoDetailFragment
|
|||||||
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
||||||
startOnExternalPlayer(activity, currentInfo, selectedVideoStream);
|
startOnExternalPlayer(activity, currentInfo, selectedVideoStream);
|
||||||
} else {
|
} else {
|
||||||
openNormalPlayer(selectedVideoStream);
|
openNormalPlayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -926,24 +934,13 @@ public class VideoDetailFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openNormalPlayer(VideoStream selectedVideoStream) {
|
private void openNormalPlayer() {
|
||||||
Intent mIntent;
|
Intent mIntent;
|
||||||
boolean useOldPlayer = PlayerHelper.isUsingOldPlayer(activity) || (Build.VERSION.SDK_INT < 16);
|
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
||||||
if (!useOldPlayer) {
|
mIntent = NavigationHelper.getPlayerIntent(activity,
|
||||||
// ExoPlayer
|
MainVideoPlayer.class,
|
||||||
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
playQueue,
|
||||||
mIntent = NavigationHelper.getPlayerIntent(activity,
|
getSelectedVideoStream().getResolution());
|
||||||
MainVideoPlayer.class,
|
|
||||||
playQueue,
|
|
||||||
getSelectedVideoStream().getResolution());
|
|
||||||
} else {
|
|
||||||
// Internal Player
|
|
||||||
mIntent = new Intent(activity, PlayVideoActivity.class)
|
|
||||||
.putExtra(PlayVideoActivity.VIDEO_TITLE, currentInfo.getName())
|
|
||||||
.putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.getUrl())
|
|
||||||
.putExtra(PlayVideoActivity.VIDEO_URL, currentInfo.getUrl())
|
|
||||||
.putExtra(PlayVideoActivity.START_POSITION, currentInfo.getStartPosition());
|
|
||||||
}
|
|
||||||
startActivity(mIntent);
|
startActivity(mIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1114,8 +1111,16 @@ public class VideoDetailFragment
|
|||||||
animateView(videoTitleTextView, true, 0);
|
animateView(videoTitleTextView, true, 0);
|
||||||
|
|
||||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
if (videoTitleToggleArrow != null) { //phone
|
||||||
videoTitleToggleArrow.setVisibility(View.GONE);
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
||||||
|
videoTitleToggleArrow.setVisibility(View.GONE);
|
||||||
|
} else { //tablet
|
||||||
|
final View related = (View) relatedStreamRootLayout.getParent();
|
||||||
|
//don`t need to hide it if related streams are disabled
|
||||||
|
if (related.getVisibility() == View.VISIBLE) {
|
||||||
|
related.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
videoTitleRoot.setClickable(false);
|
videoTitleRoot.setClickable(false);
|
||||||
|
|
||||||
imageLoader.cancelDisplayTask(thumbnailImageView);
|
imageLoader.cancelDisplayTask(thumbnailImageView);
|
||||||
@@ -1190,11 +1195,15 @@ public class VideoDetailFragment
|
|||||||
detailDurationView.setVisibility(View.GONE);
|
detailDurationView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
videoTitleRoot.setClickable(true);
|
|
||||||
videoTitleToggleArrow.setVisibility(View.VISIBLE);
|
|
||||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
|
||||||
videoDescriptionView.setVisibility(View.GONE);
|
videoDescriptionView.setVisibility(View.GONE);
|
||||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
if (videoTitleToggleArrow != null) {
|
||||||
|
videoTitleRoot.setClickable(true);
|
||||||
|
videoTitleToggleArrow.setVisibility(View.VISIBLE);
|
||||||
|
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
||||||
|
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
videoDescriptionRootLayout.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
if (!TextUtils.isEmpty(info.getUploadDate())) {
|
if (!TextUtils.isEmpty(info.getUploadDate())) {
|
||||||
videoUploadDateView.setText(Localization.localizeDate(activity, info.getUploadDate()));
|
videoUploadDateView.setText(Localization.localizeDate(activity, info.getUploadDate()));
|
||||||
}
|
}
|
||||||
@@ -1242,6 +1251,11 @@ public class VideoDetailFragment
|
|||||||
// Only auto play in the first open
|
// Only auto play in the first open
|
||||||
autoPlayEnabled = false;
|
autoPlayEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ViewParent related = relatedStreamRootLayout.getParent();
|
||||||
|
if (related instanceof ScrollView) {
|
||||||
|
((ScrollView) related).scrollTo(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1251,6 +1265,7 @@ public class VideoDetailFragment
|
|||||||
downloadDialog.setVideoStreams(sortedVideoStreams);
|
downloadDialog.setVideoStreams(sortedVideoStreams);
|
||||||
downloadDialog.setAudioStreams(currentInfo.getAudioStreams());
|
downloadDialog.setAudioStreams(currentInfo.getAudioStreams());
|
||||||
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
||||||
|
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
|
||||||
|
|
||||||
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -1299,4 +1314,13 @@ public class VideoDetailFragment
|
|||||||
|
|
||||||
showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema);
|
showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setRelatedStreamsVisibility(int visibility) {
|
||||||
|
final ViewParent parent = relatedStreamRootLayout.getParent();
|
||||||
|
if (parent instanceof ScrollView) {
|
||||||
|
((ScrollView) parent).setVisibility(visibility);
|
||||||
|
} else {
|
||||||
|
relatedStreamRootLayout.setVisibility(visibility);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -3,10 +3,15 @@ package org.schabi.newpipe.fragments.list;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -21,9 +26,9 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
|||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
|
||||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||||
import org.schabi.newpipe.info_list.InfoListAdapter;
|
import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||||
|
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
||||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
@@ -36,7 +41,7 @@ import java.util.Queue;
|
|||||||
|
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||||
|
|
||||||
public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implements ListViewContract<I, N>, StateSaver.WriteRead {
|
public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implements ListViewContract<I, N>, StateSaver.WriteRead, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Views
|
// Views
|
||||||
@@ -44,6 +49,9 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
|
|
||||||
protected InfoListAdapter infoListAdapter;
|
protected InfoListAdapter infoListAdapter;
|
||||||
protected RecyclerView itemsList;
|
protected RecyclerView itemsList;
|
||||||
|
private int updateFlags = 0;
|
||||||
|
|
||||||
|
private static final int LIST_MODE_UPDATE_FLAG = 0x32;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// LifeCycle
|
// LifeCycle
|
||||||
@@ -59,12 +67,31 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
|
.registerOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
StateSaver.onDestroy(savedState);
|
StateSaver.onDestroy(savedState);
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
|
.unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
if (updateFlags != 0) {
|
||||||
|
if ((updateFlags & LIST_MODE_UPDATE_FLAG) != 0) {
|
||||||
|
final boolean useGrid = isGridLayout();
|
||||||
|
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||||
|
infoListAdapter.setGridItemVariants(useGrid);
|
||||||
|
infoListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
updateFlags = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -119,13 +146,25 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
return new LinearLayoutManager(activity);
|
return new LinearLayoutManager(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected RecyclerView.LayoutManager getGridLayoutManager() {
|
||||||
|
final Resources resources = activity.getResources();
|
||||||
|
int width = resources.getDimensionPixelSize(R.dimen.video_item_grid_thumbnail_image_width);
|
||||||
|
width += (24 * resources.getDisplayMetrics().density);
|
||||||
|
final int spanCount = (int) Math.floor(resources.getDisplayMetrics().widthPixels / (double)width);
|
||||||
|
final GridLayoutManager lm = new GridLayoutManager(activity, spanCount);
|
||||||
|
lm.setSpanSizeLookup(infoListAdapter.getSpanSizeLookup(spanCount));
|
||||||
|
return lm;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initViews(View rootView, Bundle savedInstanceState) {
|
protected void initViews(View rootView, Bundle savedInstanceState) {
|
||||||
super.initViews(rootView, savedInstanceState);
|
super.initViews(rootView, savedInstanceState);
|
||||||
|
|
||||||
|
final boolean useGrid = isGridLayout();
|
||||||
itemsList = rootView.findViewById(R.id.items_list);
|
itemsList = rootView.findViewById(R.id.items_list);
|
||||||
itemsList.setLayoutManager(getListLayoutManager());
|
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||||
|
|
||||||
|
infoListAdapter.setGridItemVariants(useGrid);
|
||||||
infoListAdapter.setFooter(getListFooter());
|
infoListAdapter.setFooter(getListFooter());
|
||||||
infoListAdapter.setHeader(getListHeader());
|
infoListAdapter.setHeader(getListHeader());
|
||||||
|
|
||||||
@@ -308,4 +347,22 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
public void handleNextItems(N result) {
|
public void handleNextItems(N result) {
|
||||||
isLoading.set(false);
|
isLoading.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
|
if (key.equals(getString(R.string.list_view_mode_key))) {
|
||||||
|
updateFlags |= LIST_MODE_UPDATE_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isGridLayout() {
|
||||||
|
final String list_mode = PreferenceManager.getDefaultSharedPreferences(activity).getString(getString(R.string.list_view_mode_key), getString(R.string.list_view_mode_value));
|
||||||
|
if ("auto".equals(list_mode)) {
|
||||||
|
final Configuration configuration = getResources().getConfiguration();
|
||||||
|
return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
&& configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
|
||||||
|
} else {
|
||||||
|
return "grid".equals(list_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,9 +8,6 @@ import android.view.View;
|
|||||||
|
|
||||||
import org.schabi.newpipe.extractor.ListExtractor;
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
import org.schabi.newpipe.extractor.ListInfo;
|
import org.schabi.newpipe.extractor.ListInfo;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
|
||||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
|
||||||
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
|
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@@ -19,7 +16,6 @@ import icepick.State;
|
|||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.functions.Consumer;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public abstract class BaseListInfoFragment<I extends ListInfo>
|
public abstract class BaseListInfoFragment<I extends ListInfo>
|
||||||
|
@@ -68,7 +68,7 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|||||||
|
|
||||||
public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||||
|
|
||||||
private CompositeDisposable disposables = new CompositeDisposable();
|
private final CompositeDisposable disposables = new CompositeDisposable();
|
||||||
private Disposable subscribeButtonMonitor;
|
private Disposable subscribeButtonMonitor;
|
||||||
private SubscriptionService subscriptionService;
|
private SubscriptionService subscriptionService;
|
||||||
|
|
||||||
@@ -90,8 +90,6 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
|||||||
|
|
||||||
private MenuItem menuRssButton;
|
private MenuItem menuRssButton;
|
||||||
|
|
||||||
private boolean mIsVisibleToUser = false;
|
|
||||||
|
|
||||||
public static ChannelFragment getInstance(int serviceId, String url, String name) {
|
public static ChannelFragment getInstance(int serviceId, String url, String name) {
|
||||||
ChannelFragment instance = new ChannelFragment();
|
ChannelFragment instance = new ChannelFragment();
|
||||||
instance.setInitialData(serviceId, url, name);
|
instance.setInitialData(serviceId, url, name);
|
||||||
@@ -105,7 +103,6 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
|||||||
@Override
|
@Override
|
||||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
mIsVisibleToUser = isVisibleToUser;
|
|
||||||
if(activity != null
|
if(activity != null
|
||||||
&& useAsFrontPage
|
&& useAsFrontPage
|
||||||
&& isVisibleToUser) {
|
&& isVisibleToUser) {
|
||||||
|
@@ -5,7 +5,6 @@ import android.preference.PreferenceManager;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -19,8 +18,6 @@ import org.schabi.newpipe.extractor.StreamingService;
|
|||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
|
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
|
||||||
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
|
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
@@ -131,26 +128,16 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<KioskInfo> loadResult(boolean forceReload) {
|
public Single<KioskInfo> loadResult(boolean forceReload) {
|
||||||
String contentCountry = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(activity)
|
|
||||||
.getString(getString(R.string.content_country_key),
|
|
||||||
getString(R.string.default_country_value));
|
|
||||||
return ExtractorHelper.getKioskInfo(serviceId,
|
return ExtractorHelper.getKioskInfo(serviceId,
|
||||||
url,
|
url,
|
||||||
contentCountry,
|
|
||||||
forceReload);
|
forceReload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic() {
|
public Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic() {
|
||||||
String contentCountry = PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(activity)
|
|
||||||
.getString(getString(R.string.content_country_key),
|
|
||||||
getString(R.string.default_country_value));
|
|
||||||
return ExtractorHelper.getMoreKioskItems(serviceId,
|
return ExtractorHelper.getMoreKioskItems(serviceId,
|
||||||
url,
|
url,
|
||||||
currentNextPageUrl,
|
currentNextPageUrl);
|
||||||
contentCountry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
@@ -20,7 +20,6 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import org.reactivestreams.Subscriber;
|
import org.reactivestreams.Subscriber;
|
||||||
import org.reactivestreams.Subscription;
|
import org.reactivestreams.Subscription;
|
||||||
import org.schabi.newpipe.App;
|
|
||||||
import org.schabi.newpipe.NewPipeDatabase;
|
import org.schabi.newpipe.NewPipeDatabase;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
||||||
@@ -30,7 +29,6 @@ import org.schabi.newpipe.extractor.NewPipe;
|
|||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user