1
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-09-20 11:20:52 +02:00

Compare commits

..

183 Commits

Author SHA1 Message Date
Tobias Groza
1670751c94 Merge pull request #2312 from TeamNewPipe/release_v0.16.2
Release v0.16.2
2019-05-31 23:30:39 +02:00
Tobias Groza
0c354c4fdb Remove old strings
Remove strings which have been deleted from the English strings file during development, but were translated via Weblate, which failed to pull and push our upstream repo.
2019-05-27 00:11:37 +02:00
Tobias Groza
bd7413119a Merge branch 'weblate' into release_v0.16.2
Update translations
2019-05-26 22:58:53 +02:00
Davide Palma
f26915aab6 Translated using Weblate (Italian)
Currently translated at 99.8% (442 of 443 strings)
2019-05-25 04:49:13 +02:00
Tobias Groza
f6068dc69d Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-05-25 04:49:11 +02:00
Marc Riera
bd2c65cd94 Translated using Weblate (Catalan)
Currently translated at 96.8% (429 of 443 strings)
2019-05-15 11:49:29 +02:00
Tobias Groza
4777910644 Update changelog for 0.16.2 2019-05-14 23:17:04 +02:00
Tobias Groza
66b26e52ce Update extractor version 2019-05-14 23:16:43 +02:00
Tolstovka
a758267d72 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (443 of 443 strings)
2019-05-13 10:53:20 +02:00
Tolstovka
72eae64698 Translated using Weblate (Russian)
Currently translated at 100.0% (443 of 443 strings)
2019-05-13 10:53:18 +02:00
84436
d63c18f7f0 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (443 of 443 strings)
2019-05-10 10:19:35 +02:00
Eduardo Caron
b05e3ca8d8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (443 of 443 strings)
2019-05-10 10:17:50 +02:00
gabriellluz
0a88100b67 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (443 of 443 strings)
2019-05-08 16:49:07 +02:00
abvgeej
55d6825f63 Translated using Weblate (Russian)
Currently translated at 99.5% (441 of 443 strings)
2019-05-06 14:48:53 +02:00
Jonathan Tavares
e4f9af7076 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.6% (437 of 443 strings)
2019-05-06 14:48:49 +02:00
Tobias Groza
ff52fe4884 Add changelog for NewPipe 0.16.2 2019-05-03 07:58:46 +02:00
Snow K1ng
0ab29b7c1f Translated using Weblate (Romanian)
Currently translated at 75.8% (336 of 443 strings)
2019-04-29 13:48:19 +02:00
yunna
d742ed7b65 Translated using Weblate (Japanese)
Currently translated at 100.0% (443 of 443 strings)
2019-04-29 13:46:50 +02:00
Jesper Hertel
a684e380b7 Translated using Weblate (Danish)
Currently translated at 98.9% (438 of 443 strings)
2019-04-29 13:45:08 +02:00
AB
c90feaf3db Translated using Weblate (Ukrainian)
Currently translated at 100.0% (443 of 443 strings)
2019-04-28 21:49:00 +02:00
Chandra Mohan Jha
460610f672 Translated using Weblate (Hindi)
Currently translated at 77.2% (342 of 443 strings)
2019-04-28 21:49:00 +02:00
Jesper Hertel
46511533aa Translated using Weblate (Danish)
Currently translated at 88.7% (393 of 443 strings)
2019-04-28 21:48:59 +02:00
Tobias Groza
40efed6580 Update version code and name to NewPipe 0.16.2 2019-04-28 03:34:47 +02:00
Tobias Groza
78b1c1eb4a Merge remote-tracking branch 'TeamNewPipe/master' into dev 2019-04-28 03:34:38 +02:00
Tobias Groza
5a59a3dd50 Merge pull request #2311 from Redirion/FixSubs
Readd CustomTrackSelector
2019-04-28 02:29:20 +02:00
Robin
0763280196 Readd CustomTrackSelector 2019-04-28 01:45:19 +02:00
Chandra Mohan Jha
e7d0685ebc Translated using Weblate (Hindi)
Currently translated at 74.5% (330 of 443 strings)
2019-04-27 09:58:33 +02:00
sXp
aadbfe1eed Translated using Weblate (Hindi)
Currently translated at 74.5% (330 of 443 strings)
2019-04-27 09:58:31 +02:00
Chandra Mohan Jha
4a54fbb872 Translated using Weblate (Hindi)
Currently translated at 74.5% (330 of 443 strings)
2019-04-27 09:58:09 +02:00
sXp
8b1836d699 Translated using Weblate (Hindi)
Currently translated at 74.5% (330 of 443 strings)
2019-04-27 09:58:08 +02:00
Chandra Mohan Jha
c47d4fd35a Translated using Weblate (Hindi)
Currently translated at 74.5% (330 of 443 strings)
2019-04-27 09:58:08 +02:00
pjammo
a58af1275c Translated using Weblate (Italian)
Currently translated at 99.5% (441 of 443 strings)
2019-04-26 19:48:45 +02:00
Marc Riera
1d63b39553 Translated using Weblate (Catalan)
Currently translated at 91.6% (406 of 443 strings)
2019-04-26 19:48:44 +02:00
Jesper Hertel
c300d52b29 Translated using Weblate (Danish)
Currently translated at 87.1% (386 of 443 strings)
2019-04-25 14:48:56 +02:00
Sören Strecke
5314e275bc Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-04-24 11:37:07 +02:00
yunna
08f8b9770a Translated using Weblate (Japanese)
Currently translated at 100.0% (443 of 443 strings)
2019-04-23 22:48:54 +02:00
YONGLE
a9c64b2fec Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (443 of 443 strings)
2019-04-23 22:48:50 +02:00
Kristjan Räts
1df8af35d4 Translated using Weblate (Estonian)
Currently translated at 100.0% (443 of 443 strings)
2019-04-16 21:05:04 +02:00
Tobias Groza
049cd2d236 Merge pull request #1969 from nv95/close_button
Show close button when playing completed
2019-04-14 11:47:33 +02:00
Tobias Groza
e99714eba6 Merge remote-tracking branch 'TeamNewPipe/dev' into close_button 2019-04-13 18:18:17 +02:00
Lambda Monad
4751075e87 Translated using Weblate (Indonesian)
Currently translated at 99.3% (440 of 443 strings)
2019-04-12 21:04:47 +02:00
Tobias Groza
416e0fb609 Merge pull request #2271 from Stypox/dev
Add "share at current time" button to the main video player
2019-04-11 19:18:52 +02:00
minsk21
f96a371464 Translated using Weblate (Belarusian)
Currently translated at 74.5% (330 of 443 strings)
2019-04-10 04:04:47 +02:00
___
e423192265 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (443 of 443 strings)
2019-04-09 03:16:34 +02:00
minsk21
e9444e058c Translated using Weblate (Belarusian)
Currently translated at 74.3% (329 of 443 strings)
2019-04-09 03:16:28 +02:00
Yaron Shahrabani
037632fbf0 Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-07 15:59:53 +02:00
Yoav
6cdea85a49 Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-07 15:59:49 +02:00
Yaron Shahrabani
f86d755890 Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-07 15:59:49 +02:00
Stypox
98cc97251a Merge branch 'dev' into dev 2019-04-07 08:18:39 +02:00
Tobias Groza
562f414e3e Merge pull request #2237 from epitron/dev
Fixed English translations for Play/Enqueue commands
2019-04-06 23:32:05 +02:00
Tobias Groza
1afc301432 Merge branch 'dev' into dev 2019-04-06 23:23:15 +02:00
Yaron Shahrabani
115b44585b Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 21:10:05 +02:00
artik banana
3ff47623d5 Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 21:10:03 +02:00
Yaron Shahrabani
943e03f9d8 Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 21:10:03 +02:00
AB
f7a534a0d0 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 20:59:53 +02:00
Yaron Shahrabani
72e30d8e40 Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 20:59:50 +02:00
Yehuda Levy
eb265300fc Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 20:59:48 +02:00
artik banana
704b8f61dd Translated using Weblate (Hebrew)
Currently translated at 100.0% (443 of 443 strings)
2019-04-06 20:59:47 +02:00
Stypox
40957c445f Implemented share button in MainVideoPlayer
Android Studio also decided to change the indentation of some lines
2019-04-06 20:27:13 +02:00
Stypox
8eead9fda2 Add share button to main player layout
Placed under "more options"
2019-04-06 20:21:32 +02:00
Stypox
aadc8168be Remove share utilities from BaseStateFragment
Replaced by ShareUtils
2019-04-06 20:17:04 +02:00
Stypox
cb33f04bfc Add ShareUtils class to share videos or open urls in browser. 2019-04-06 20:11:23 +02:00
Florian
82cb71bf3f Translated using Weblate (French)
Currently translated at 99.8% (442 of 443 strings)
2019-04-06 09:53:58 +02:00
Stjepan
c37b88a239 Translated using Weblate (Croatian)
Currently translated at 99.3% (440 of 443 strings)
2019-04-06 09:53:57 +02:00
___
de59bf695d Translated using Weblate (Ukrainian)
Currently translated at 99.8% (442 of 443 strings)
2019-04-06 09:53:55 +02:00
Tobias Groza
592627b013 Merge pull request #2247 from yausername/preferredTabState
preferred tab based on selected state, fixes #2238
2019-04-04 16:16:51 +02:00
Tobias Groza
9ed1fb2588 Merge branch 'dev' into preferredTabState 2019-04-04 15:22:57 +02:00
Tobias Groza
8232a92653 Translated using Weblate (Romanian)
Currently translated at 75.6% (335 of 443 strings)
2019-04-03 17:04:43 +02:00
Tobias Groza
09eeaa92d1 Merge pull request #2207 from yausername/timestampClickFix
seek on clicking timestamp links in comments
2019-04-03 16:04:31 +02:00
Igor Nedoboy
1e4b1a2c70 Translated using Weblate (Russian)
Currently translated at 100.0% (443 of 443 strings)
2019-03-31 22:58:10 +02:00
Marco Ieni
0a1e7a7c86 Translated using Weblate (Italian)
Currently translated at 99.3% (440 of 443 strings)
2019-03-31 22:16:38 +02:00
nautilusx
e5f3b2bf6e Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-03-31 22:16:37 +02:00
Florian
29183c10ff Translated using Weblate (French)
Currently translated at 99.1% (439 of 443 strings)
2019-03-31 22:16:37 +02:00
Stjepan
46b8bdace7 Translated using Weblate (Croatian)
Currently translated at 99.3% (440 of 443 strings)
2019-03-31 22:16:36 +02:00
Igor Nedoboy
9b6924ec9f Translated using Weblate (Russian)
Currently translated at 100.0% (443 of 443 strings)
2019-03-31 22:16:19 +02:00
Stjepan
c69de107e5 Translated using Weblate (Croatian)
Currently translated at 68.8% (305 of 443 strings)
2019-03-29 00:36:30 +01:00
Igor Nedoboy
c4d451e420 Translated using Weblate (Russian)
Currently translated at 100.0% (443 of 443 strings)
2019-03-29 00:36:25 +01:00
sherlockbeard
be6bce5771 Translated using Weblate (Hindi)
Currently translated at 74.3% (329 of 443 strings)
2019-03-27 21:04:26 +01:00
Tobias Groza
bf845be727 Merge branch 'dev' into timestampClickFix 2019-03-26 23:20:55 +01:00
Ahanaf Taskin Ar-Rafee
e92a5414d1 Translated using Weblate (Bengali (Bangladesh))
Currently translated at 30.5% (135 of 443 strings)
2019-03-25 06:38:50 +01:00
yausername
657125f43c save selected tab sate in stream detail fragment, fixes #2238 2019-03-24 06:31:28 +05:30
Christian Schabesberger
e98f68e93b Merge pull request #2242 from yausername/fixMissingAuthorName
fix empty author endpoint
2019-03-23 23:43:05 +01:00
Florian
bef84e9eec Translated using Weblate (French)
Currently translated at 97.3% (431 of 443 strings)
2019-03-23 20:38:52 +01:00
Le Poisson Libre
6a5f2402c7 Translated using Weblate (French)
Currently translated at 97.3% (431 of 443 strings)
2019-03-23 20:38:49 +01:00
yausername
d6cc6ba144 fix empty author endpoint 2019-03-23 00:22:59 +05:30
yausername
07f8dcb3ca use ellipsis character 2019-03-22 05:56:56 +05:30
yausername
a026143a84 linkify optimizations 2019-03-22 04:57:33 +05:30
Andrea Gelmini
73a5b6738d Translated using Weblate (Italian)
Currently translated at 99.1% (439 of 443 strings)
2019-03-21 18:03:59 +01:00
epitron
3e2b12ae4a Fixed English translations for Play/Enqueue commands 2019-03-21 11:24:52 -04:00
naofum
8073364b7a Translated using Weblate (Japanese)
Currently translated at 100.0% (443 of 443 strings)
2019-03-20 03:14:37 +01:00
Osoitz
b141d96e7c Translated using Weblate (Basque)
Currently translated at 100.0% (443 of 443 strings)
2019-03-20 03:14:36 +01:00
Serdar Sağlam
a86e8b98fe Translated using Weblate (Turkish)
Currently translated at 100.0% (443 of 443 strings)
2019-03-20 03:14:34 +01:00
WaldiS
a7d77716f3 Translated using Weblate (Polish)
Currently translated at 100.0% (443 of 443 strings)
2019-03-18 09:39:23 +01:00
Igor Nedoboy
b017e439b1 Translated using Weblate (Russian)
Currently translated at 100.0% (443 of 443 strings)
2019-03-17 21:06:17 +01:00
ssantos
a7156f665a Translated using Weblate (Portuguese)
Currently translated at 100.0% (443 of 443 strings)
2019-03-16 12:54:18 +01:00
WaldiS
44e34d084e Translated using Weblate (Polish)
Currently translated at 99.8% (442 of 443 strings)
2019-03-16 12:54:18 +01:00
C. Rüdinger
065820ffa4 Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-03-16 12:54:17 +01:00
Jeff Huang
26991928ae Translated using Weblate (Chinese (Traditional))
Currently translated at 99.8% (442 of 443 strings)
2019-03-16 12:54:16 +01:00
ssantos
f4fa68c390 Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-03-16 12:54:09 +01:00
Gontzal Manuel Pujana Onaindia
8b86f9ea6d Translated using Weblate (Basque)
Currently translated at 100.0% (443 of 443 strings)
2019-03-14 19:00:35 +01:00
Christian Schabesberger
48f966e7db add changelog for 730 2019-03-14 09:24:02 +01:00
Christian Schabesberger
d8746dc592 hotfix decrypt function and move on to version v0.16.1 2019-03-14 09:20:37 +01:00
Ritvik Saraf
6421d3017e seek on clicking timestamp links in comments 2019-03-13 07:01:24 +05:30
Tobias Groza
f9e771f8f7 Merge pull request #2198 from Redirion/directOnBackground
Directplay on Background
2019-03-12 13:42:43 +01:00
Tobias Groza
09456ce421 Merge branch 'dev' into directOnBackground 2019-03-12 13:36:14 +01:00
dextro67
716f7e722b Translated using Weblate (Hindi)
Currently translated at 73.6% (326 of 443 strings)
2019-03-12 04:03:54 +01:00
Der_Floh
ffa4b1483f Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-03-12 04:03:53 +01:00
Christian Schabesberger
6651aa924f Merge pull request #2184 from Redirion/exoplayerupdate
Update ExoPlayer to 2.9.6
2019-03-11 20:43:28 +01:00
Olexandr Nesterenko
70238fd773 Translated using Weblate (Ukrainian)
Currently translated at 98.4% (436 of 443 strings)
2019-03-10 20:09:04 +01:00
WaldiS
fc4e007cc4 Translated using Weblate (Polish)
Currently translated at 100.0% (443 of 443 strings)
2019-03-10 20:09:00 +01:00
Nathan Follens
b7667ce97a Translated using Weblate (Flemish)
Currently translated at 100.0% (443 of 443 strings)
2019-03-10 20:08:59 +01:00
ssantos
1315da0da7 Translated using Weblate (German)
Currently translated at 100.0% (443 of 443 strings)
2019-03-10 20:08:57 +01:00
84436
c4d8eae547 Translated using Weblate (Vietnamese)
Currently translated at 99.3% (440 of 443 strings)
2019-03-09 17:04:15 +01:00
Pj Pj
b01fc1be62 Translated using Weblate (Telugu)
Currently translated at 28.7% (127 of 443 strings)
2019-03-09 17:04:13 +01:00
marciozomb13
c46e3cf5cb Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.5% (441 of 443 strings)
2019-03-09 17:04:12 +01:00
WaldiS
1a6b915112 Translated using Weblate (Polish)
Currently translated at 100.0% (443 of 443 strings)
2019-03-09 17:04:11 +01:00
Terry Louwers
2f38943488 Translated using Weblate (Dutch)
Currently translated at 100.0% (443 of 443 strings)
2019-03-09 17:04:09 +01:00
Marco Szeto
06711dc6c3 Translated using Weblate (Chinese (Hong Kong))
Currently translated at 31.8% (141 of 443 strings)
2019-03-09 17:04:08 +01:00
Robin
cc7e342ab7 Merge remote-tracking branch 'upstream/dev' into directOnBackground 2019-03-08 23:02:47 +01:00
Robin
5b64743987 Directplay on Background 2019-03-08 22:52:17 +01:00
Robin
a84ad031d9 Merge remote-tracking branch 'upstream/dev' into exoplayerupdate 2019-03-07 16:06:02 +01:00
Tobias Groza
c4c2fe2a9c Merge pull request #1963 from Klearchos-K/dev
Issue #1951 - Search shared text
2019-03-07 15:50:51 +01:00
Tobias Groza
8ccaef454c Merge branch 'dev' into dev 2019-03-07 15:20:42 +01:00
Marian Hanzel
27579dff37 Translated using Weblate (Slovak)
Currently translated at 88.3% (391 of 443 strings)
2019-03-06 22:13:04 +01:00
Nikola Perović
389d08c233 Translated using Weblate (Serbian)
Currently translated at 47.4% (210 of 443 strings)
2019-03-06 22:12:59 +01:00
Michalis Nikolaidis
5412a087fe Translated using Weblate (Greek)
Currently translated at 100.0% (443 of 443 strings)
2019-03-06 22:12:59 +01:00
Konstantinos Giannopoulos
dd0f3ac651 Translated using Weblate (Greek)
Currently translated at 100.0% (443 of 443 strings)
2019-03-06 22:12:58 +01:00
YONGLE
4d4d776e4d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (443 of 443 strings)
2019-03-06 22:12:51 +01:00
Robin
7877b107c1 Merge branch 'exoplayerupdate' of https://github.com/Redirion/NewPipe into exoplayerupdate 2019-03-06 09:38:17 +01:00
Robin
a2aa0aa9a8 Fix for wrong case after language normalization 2019-03-06 09:37:55 +01:00
Redirion
b3475d30c0 Merge branch 'dev' into exoplayerupdate 2019-03-05 21:44:27 +01:00
Tobias Groza
6484c8d636 Merge pull request #2183 from Redirion/Cleanup
delete unused files
2019-03-05 21:38:19 +01:00
Tobias Groza
587cf554f2 Merge branch 'dev' into Cleanup 2019-03-05 21:30:48 +01:00
Tobias Groza
1d4e4eb6b3 Merge pull request #2178 from Redirion/patch-1
Cache duration String to improve performance of background player
2019-03-05 21:06:22 +01:00
Tobias Groza
31c4ed7d0e Update app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java
Co-Authored-By: Redirion <redirion@web.de>
2019-03-05 20:57:05 +01:00
Robin
7f246b2d3d Removed unused import 2019-03-05 19:54:37 +01:00
Robin
7d68cff700 NOTE for legacy version: Removed Lint markers and completely dropped Jelly Bean workarounds 2019-03-05 19:48:39 +01:00
Robin
4d80bdcc9f Update ExoPlayer to 2.9.6, including httook dependency and deprecations 2019-03-05 18:05:44 +01:00
Robin
8b4a94e5aa delete unused files 2019-03-05 18:01:11 +01:00
Redirion
111ad14ad3 Merge branch 'dev' into patch-1 2019-03-05 17:57:52 +01:00
Tobias Groza
aec3f19d23 Merge pull request #2179 from Redirion/patch-2
Improve performance of getTimeString
2019-03-04 19:16:43 +01:00
Redirion
d8b80f961a Improved performance of getTimeString
This pull requests complements pull request  #2178 by reducing general computational time for the method getTimeString.

On my local machine (Desktop PC with Java) my tests with a sample size of 10000 calls to the method with param 86400001 showed a performance improvement of about 50%.

See sample code below to reproduce:

    private static final StringBuilder stringBuilder = new StringBuilder();
    private static final Formatter stringFormatter = new Formatter(stringBuilder, Locale.getDefault());
    
    public static String getTimeString(int milliSeconds) {
        int seconds = (milliSeconds % 60000) / 1000;
        int minutes = (milliSeconds % 3600000) / 60000;
        int hours = (milliSeconds % 86400000) / 3600000;
        int days = (milliSeconds % (86400000 * 7)) / 86400000;

        stringBuilder.setLength(0);
        return days > 0 ? stringFormatter.format("%d:%02d:%02d:%02d", days, hours, minutes, seconds).toString()
                : hours > 0 ? stringFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
                : stringFormatter.format("%02d:%02d", minutes, seconds).toString();
    }
    
    public static String getTimeStringL(int milliSeconds) {
        long seconds = (milliSeconds % 60000L) / 1000L;
        long minutes = (milliSeconds % 3600000L) / 60000L;
        long hours = (milliSeconds % 86400000L) / 3600000L;
        long days = (milliSeconds % (86400000L * 7L)) / 86400000L;

        stringBuilder.setLength(0);
        return days > 0 ? stringFormatter.format("%d:%02d:%02d:%02d", days, hours, minutes, seconds).toString()
                : hours > 0 ? stringFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
                : stringFormatter.format("%02d:%02d", minutes, seconds).toString();
    }
    
	public static void main(String[] args) throws Exception {
		final int SAMPLE_SIZE = 25000;
		long[] results = new long[SAMPLE_SIZE];
		for(int i = 0; i < SAMPLE_SIZE; i++) {
			long now = System.nanoTime();
			getTimeString(86400001);
			results[i] = System.nanoTime() - now;
		}
		long sum = 0;
		for(int i = 0; i < SAMPLE_SIZE; i++) {
			sum += results[i];
		}
		System.out.println("Average execution time: " + (sum/SAMPLE_SIZE));
		results = new long[SAMPLE_SIZE];
		for(int i = 0; i < SAMPLE_SIZE; i++) {
			long now = System.nanoTime();
			getTimeStringL(86400001);
			results[i] = System.nanoTime() - now;
		}
		sum = 0;
		for(int i = 0; i < SAMPLE_SIZE; i++) {
			sum += results[i];
		}
		System.out.println("Average execution time: " + (sum/SAMPLE_SIZE));
2019-03-04 15:45:59 +01:00
rimasx
891bb7fa40 Translated using Weblate (Estonian)
Currently translated at 100.0% (443 of 443 strings)
2019-03-04 11:58:31 +01:00
Rex_sa
0e3af45466 Translated using Weblate (Arabic)
Currently translated at 100.0% (443 of 443 strings)
2019-03-04 11:58:24 +01:00
Redirion
6aebbc3109 Cache duration String to improve performance
In VideoPlayer the Duration String is cached effectively by setting it to the playbackSeekBar. As the playbackSeekBar doesn't exist in BackgroundPlayer, using two addition variables will reduce performance impact of notification updates by almost 50% and thus perform similar to VideoPlayer.

This addresses issue #2170
2019-03-04 10:24:08 +01:00
Christian Schabesberger
15eb7f3186 Merge pull request #2023 from dotvirus/enqueue-playlist
Add playlist to queue when long clicking on 'Background'
2019-03-03 20:59:15 +01:00
Christian Schabesberger
fb4cd98014 Merge branch 'dev' into enqueue-playlist 2019-03-03 20:53:17 +01:00
Christian Schabesberger
eb692dea59 Merge pull request #2168 from yausername/commentSizeAndLinks
make links in comments clickable, increase text size
2019-03-03 20:52:11 +01:00
Christian Schabesberger
d8039fb542 Merge branch 'dev' into enqueue-playlist 2019-03-03 20:50:00 +01:00
Christian Schabesberger
5e06d19d77 Merge branch 'dev' into commentSizeAndLinks 2019-03-03 20:46:03 +01:00
Christian Schabesberger
963f390336 Merge pull request #2176 from yausername/fixScrollOnBlank
fixed scroll w/ comments and related streams disabled
2019-03-03 20:41:07 +01:00
Ritvik Saraf
2309e15261 fixed scroll w/ comments and related streams disabled 2019-03-03 18:20:15 +05:30
Ritvik Saraf
8491035b2f updated extractor 2019-03-03 04:34:50 +05:30
Ritvik Saraf
4d4107aefc Merge remote-tracking branch 'upstream/dev' into commentSizeAndLinks 2019-03-03 04:32:19 +05:30
Ritvik Saraf
67d2b9131e handling timestamp links in comments 2019-03-02 05:12:06 +05:30
Christian Schabesberger
da8644168c Merge branch 'master' into dev 2019-03-01 09:53:43 +01:00
Ritvik Saraf
c0004e988a make links in comments clickable, increase text size 2019-03-01 13:28:32 +05:30
Javi
b9187445e0 Translated using Weblate (Spanish)
Currently translated at 100.0% (443 of 443 strings)
2019-02-27 22:28:31 +01:00
Christian Schabesberger
554ebf7ab9 Merge pull request #2161 from Redirion/patch-1
Fixed CheckForNewAppVersionTask being executed when it shouldn't
2019-02-27 22:14:53 +01:00
Redirion
3e54cd7284 Update CheckForNewAppVersionTask.java 2019-02-26 19:33:01 +01:00
Redirion
a7afc23a9a Fixed Asynctask being executed when it shouldn't
#1 check if cancel was called in onPrepare
#2 if we currently don't have a Connection, don't show crash report dialogue to user
2019-02-26 19:23:54 +01:00
abvgeej
fa3a047519 Translated using Weblate (Russian)
Currently translated at 100.0% (443 of 443 strings)
2019-02-25 23:18:20 +01:00
Christian Schabesberger
f4d215664e Merge pull request #2117 from nv95/patch1_ui
Small ux improve
2019-02-24 22:34:12 +01:00
Christian Schabesberger
84894a557a Merge branch 'dev' into patch1_ui 2019-02-24 22:27:06 +01:00
Christian Schabesberger
ffad6e4c61 Merge pull request #2148 from yausername/commentsAndRelatedUx
added top padding for comments and related videos
2019-02-24 22:26:46 +01:00
Christian Schabesberger
93b266e6be Merge branch 'dev' into commentsAndRelatedUx 2019-02-24 22:19:47 +01:00
Christian Schabesberger
f92ea28581 Merge pull request #2151 from nv95/fix_leak
Fix AudioManager memory leak
2019-02-24 22:19:27 +01:00
Christian Schabesberger
85213e4b6c Merge branch 'dev' into patch1_ui 2019-02-24 22:18:06 +01:00
Christian Schabesberger
4e46119e18 Merge branch 'dev' into commentsAndRelatedUx 2019-02-24 22:17:24 +01:00
Christian Schabesberger
fdc6e9f1c3 Merge branch 'dev' into fix_leak 2019-02-24 22:12:46 +01:00
Christian Schabesberger
cb20f1e212 Merge pull request #2153 from TeamNewPipe/fix_url
fix invalid channel url for commends
2019-02-24 22:10:40 +01:00
Christian Schabesberger
e3fccd7125 fix invalid channel url for commends 2019-02-24 22:10:16 +01:00
Vasiliy
15142c1ec3 Fix AudioManager memory leak 2019-02-24 10:51:30 +02:00
Ritvik Saraf
49fe8a427a added top padding for comments and related videos 2019-02-24 02:21:11 +05:30
Vasiliy
4587428d13 Merge branch 'dev' into close_button 2019-02-23 13:19:09 +02:00
Vasiliy
5318e77035 Merge branch 'dev' into patch1_ui 2019-02-23 13:18:14 +02:00
Vasiliy
0cb5197ccf Merge remote-tracking branch 'upstream/dev' into patch1_ui 2019-02-12 10:21:03 +02:00
dotvirus
c0aca723da Update PlaylistFragment.java 2019-01-18 23:58:24 +01:00
dotvirus
28e5ee51ec Add playlist to queue when long click on 'Background' 2019-01-18 23:16:02 +01:00
Vasily
7ab10aeb80 Remove search history items using swipe 2018-12-29 20:55:24 +02:00
Vasily
9316962e47 Clear history option menu item 2018-12-29 20:55:10 +02:00
Vasily
505c528194 Show close button when playing completed 2018-12-27 16:51:48 +02:00
Klearchos-K
e4409e8ea4 Update RouterActivity.java
Add dunction handleText() for #1951 issue
2018-12-24 20:11:21 +02:00
105 changed files with 2508 additions and 3246 deletions

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 19
targetSdkVersion 28
versionCode 720
versionName "0.16.0"
versionCode 740
versionName "0.16.2"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
@@ -44,10 +44,10 @@ android {
ext {
supportLibVersion = '28.0.0'
exoPlayerLibVersion = '2.8.4' //2.9.0
exoPlayerLibVersion = '2.9.6'
roomDbLibVersion = '1.1.1'
leakCanaryLibVersion = '1.5.4' //1.6.1
okHttpLibVersion = '3.11.0'
okHttpLibVersion = '3.12.1'
icepickLibVersion = '3.2.0'
stethoLibVersion = '1.5.0'
}
@@ -57,7 +57,7 @@ dependencies {
exclude module: 'support-annotations'
})
implementation 'com.github.TeamNewPipe:NewPipeExtractor:8de53111d9'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:2ac713e'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.23.0'

View File

@@ -2,11 +2,13 @@ package org.schabi.newpipe;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
@@ -68,6 +70,8 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
if(isCancelled() || !isConnected()) return null;
// Make a network request to get latest NewPipe data.
if (client == null) {
@@ -227,4 +231,12 @@ public class CheckForNewAppVersionTask extends AsyncTask<Void, Void, String> {
return getCertificateSHA1Fingerprint().equals(GITHUB_APK_SHA1);
}
private boolean isConnected() {
ConnectivityManager cm =
(ConnectivityManager) app.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isConnected();
}
}

View File

@@ -36,12 +36,12 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
@@ -81,10 +81,13 @@ public class RouterActivity extends AppCompatActivity {
protected int selectedPreviously = -1;
protected String currentUrl;
protected boolean internalRoute = false;
protected final CompositeDisposable disposables = new CompositeDisposable();
private boolean selectionIsDownload = false;
public static final String internalRouteKey = "internalRoute";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -94,11 +97,13 @@ public class RouterActivity extends AppCompatActivity {
currentUrl = getUrl(getIntent());
if (TextUtils.isEmpty(currentUrl)) {
Toast.makeText(this, R.string.invalid_url_toast, Toast.LENGTH_LONG).show();
handleText();
finish();
}
}
internalRoute = getIntent().getBooleanExtra(internalRouteKey, false);
setTheme(ThemeHelper.isLightThemeSelected(this)
? R.style.RouterActivityThemeLight : R.style.RouterActivityThemeDark);
}
@@ -112,7 +117,7 @@ public class RouterActivity extends AppCompatActivity {
@Override
protected void onStart() {
super.onStart();
handleUrl(currentUrl);
}
@@ -353,6 +358,15 @@ public class RouterActivity extends AppCompatActivity {
positiveButton.setEnabled(state);
}
private void handleText(){
String searchString = getIntent().getStringExtra(Intent.EXTRA_TEXT);
int serviceId = getIntent().getIntExtra(Constants.KEY_SERVICE_ID, 0);
Intent intent = new Intent(getThemeWrapperContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
NavigationHelper.openSearch(getThemeWrapperContext(),serviceId,searchString);
}
private void handleChoice(final String selectedChoiceKey) {
final List<String> validChoicesList = Arrays.asList(getResources().getStringArray(R.array.preferred_open_action_values_list));
if (validChoicesList.contains(selectedChoiceKey)) {
@@ -383,8 +397,10 @@ public class RouterActivity extends AppCompatActivity {
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(intent -> {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
if(!internalRoute){
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
startActivity(intent);
finish();

View File

@@ -47,7 +47,7 @@ public class DownloadActivity extends AppCompatActivity {
@Override
public void onGlobalLayout() {
updateFragments();
getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}

View File

@@ -230,21 +230,4 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
ErrorActivity.reportError(getContext(), exception, MainActivity.class, rootView,
ErrorActivity.ErrorInfo.make(userAction, serviceName, request, errorId));
}
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
protected void openUrlInBrowser(String url) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
}
protected void shareUrl(String subject, String url) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, url);
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
}
}

View File

@@ -0,0 +1,17 @@
package org.schabi.newpipe.fragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.schabi.newpipe.BaseFragment;
import org.schabi.newpipe.R;
public class EmptyFragment extends BaseFragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_empty, container, false);
}
}

View File

@@ -1,5 +1,6 @@
package org.schabi.newpipe.fragments.detail;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
@@ -61,6 +62,18 @@ public class TabAdaptor extends FragmentPagerAdapter {
else return POSITION_NONE;
}
public int getItemPositionByTitle(String title) {
return mFragmentTitleList.indexOf(title);
}
@Nullable
public String getItemTitle(int position) {
if (position < 0 || position >= mFragmentTitleList.size()) {
return null;
}
return mFragmentTitleList.get(position);
}
public void notifyDataSetUpdate(){
notifyDataSetChanged();
}

View File

@@ -65,6 +65,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.fragments.EmptyFragment;
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment;
import org.schabi.newpipe.info_list.InfoItemDialog;
@@ -85,6 +86,7 @@ import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.StreamItemAdapter;
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
@@ -121,6 +123,7 @@ public class VideoDetailFragment
private boolean autoPlayEnabled;
private boolean showRelatedStreams;
private boolean showComments;
private String selectedTabTag;
@State
protected int serviceId = Constants.NO_SERVICE_ID;
@@ -179,6 +182,7 @@ public class VideoDetailFragment
private static final String COMMENTS_TAB_TAG = "COMMENTS";
private static final String RELATED_TAB_TAG = "NEXT VIDEO";
private static final String EMPTY_TAB_TAG = "EMPTY TAB";
private AppBarLayout appBarLayout;
private ViewPager viewPager;
@@ -211,6 +215,9 @@ public class VideoDetailFragment
showComments = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(getString(R.string.show_comments_key), true);
selectedTabTag = PreferenceManager.getDefaultSharedPreferences(activity)
.getString(getString(R.string.stream_info_selected_tab_key), COMMENTS_TAB_TAG);
PreferenceManager.getDefaultSharedPreferences(activity)
.registerOnSharedPreferenceChangeListener(this);
}
@@ -224,6 +231,10 @@ public class VideoDetailFragment
public void onPause() {
super.onPause();
if (currentWorker != null) currentWorker.dispose();
PreferenceManager.getDefaultSharedPreferences(getContext())
.edit()
.putString(getString(R.string.stream_info_selected_tab_key), pageAdapter.getItemTitle(viewPager.getCurrentItem()))
.apply();
}
@Override
@@ -537,7 +548,7 @@ public class VideoDetailFragment
}
break;
case 3:
shareUrl(item.getName(), item.getUrl());
ShareUtils.shareUrl(this.getContext(), item.getName(), item.getUrl());
break;
default:
break;
@@ -626,13 +637,13 @@ public class VideoDetailFragment
switch (id) {
case R.id.menu_item_share: {
if (currentInfo != null) {
shareUrl(currentInfo.getName(), currentInfo.getOriginalUrl());
ShareUtils.shareUrl(this.getContext(), currentInfo.getName(), currentInfo.getOriginalUrl());
}
return true;
}
case R.id.menu_item_openInBrowser: {
if (currentInfo != null) {
openUrlInBrowser(currentInfo.getOriginalUrl());
ShareUtils.openUrlInBrowser(this.getContext(), currentInfo.getOriginalUrl());
}
return true;
}
@@ -813,6 +824,9 @@ public class VideoDetailFragment
}
private void initTabs() {
if (pageAdapter.getCount() != 0) {
selectedTabTag = pageAdapter.getItemTitle(viewPager.getCurrentItem());
}
pageAdapter.clearAllItems();
if(shouldShowComments()){
@@ -824,11 +838,17 @@ public class VideoDetailFragment
pageAdapter.addFragment(new Fragment(), RELATED_TAB_TAG);
}
if(pageAdapter.getCount() == 0){
pageAdapter.addFragment(new EmptyFragment(), EMPTY_TAB_TAG);
}
pageAdapter.notifyDataSetUpdate();
if(pageAdapter.getCount() < 2){
tabLayout.setVisibility(View.GONE);
}else{
int position = pageAdapter.getItemPositionByTitle(selectedTabTag);
if(position != -1) viewPager.setCurrentItem(position);
tabLayout.setVisibility(View.VISIBLE);
}
}

View File

@@ -34,6 +34,7 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.StateSaver;
import java.util.Collections;
@@ -255,6 +256,7 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
if (context == null || context.getResources() == null || getActivity() == null) return;
final String[] commands = new String[]{
context.getResources().getString(R.string.direct_on_background),
context.getResources().getString(R.string.enqueue_on_background),
context.getResources().getString(R.string.enqueue_on_popup),
context.getResources().getString(R.string.append_playlist),
@@ -264,19 +266,22 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
switch (i) {
case 0:
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
NavigationHelper.playOnBackgroundPlayer(context, new SinglePlayQueue(item));
break;
case 1:
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
break;
case 2:
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
break;
case 3:
if (getFragmentManager() != null) {
PlaylistAppendDialog.fromStreamInfoItems(Collections.singletonList(item))
.show(getFragmentManager(), TAG);
}
break;
case 3:
shareUrl(item.getName(), item.getUrl());
case 4:
ShareUtils.shareUrl(this.getContext(), item.getName(), item.getUrl());
break;
default:
break;

View File

@@ -46,6 +46,7 @@ import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ShareUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -190,7 +191,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
}
break;
case 6:
shareUrl(item.getName(), item.getUrl());
ShareUtils.shareUrl(this.getContext(), item.getName(), item.getUrl());
break;
default:
break;
@@ -233,10 +234,10 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
openRssFeed();
break;
case R.id.menu_item_openInBrowser:
openUrlInBrowser(currentInfo.getOriginalUrl());
ShareUtils.openUrlInBrowser(this.getContext(), currentInfo.getOriginalUrl());
break;
case R.id.menu_item_share:
shareUrl(name, currentInfo.getOriginalUrl());
ShareUtils.shareUrl(this.getContext(), name, currentInfo.getOriginalUrl());
break;
default:
return super.onOptionsItemSelected(item);

View File

@@ -40,6 +40,7 @@ import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.ThemeHelper;
import java.util.ArrayList;
@@ -168,7 +169,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
break;
case 5:
shareUrl(item.getName(), item.getUrl());
ShareUtils.shareUrl(this.getContext(), item.getName(), item.getUrl());
break;
default:
break;
@@ -230,10 +231,10 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_openInBrowser:
openUrlInBrowser(url);
ShareUtils.openUrlInBrowser(this.getContext(), url);
break;
case R.id.menu_item_share:
shareUrl(name, url);
ShareUtils.shareUrl(this.getContext(), name, url);
break;
case R.id.menu_item_bookmark:
onBookmarkClicked();
@@ -305,6 +306,16 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()));
headerBackgroundButton.setOnClickListener(view ->
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()));
headerPopupButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue());
return true;
});
headerBackgroundButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue());
return true;
});
}
private PlayQueue getPlayQueue() {

View File

@@ -12,6 +12,7 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.TooltipCompat;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -45,10 +46,9 @@ import org.schabi.newpipe.fragments.list.BaseListFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.LayoutManagerSmoothScroller;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ServiceHelper;
@@ -73,8 +73,8 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import static android.support.v7.widget.helper.ItemTouchHelper.Callback.makeMovementFlags;
import static java.util.Arrays.asList;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
public class SearchFragment
@@ -298,7 +298,23 @@ public class SearchFragment
suggestionsPanel = rootView.findViewById(R.id.suggestions_panel);
suggestionsRecyclerView = rootView.findViewById(R.id.suggestions_list);
suggestionsRecyclerView.setAdapter(suggestionListAdapter);
suggestionsRecyclerView.setLayoutManager(new LayoutManagerSmoothScroller(activity));
new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
return getSuggestionMovementFlags(recyclerView, viewHolder);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder,
@NonNull RecyclerView.ViewHolder viewHolder1) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
onSuggestionItemSwiped(viewHolder, i);
}
}).attachToRecyclerView(suggestionsRecyclerView);
searchToolbarContainer = activity.findViewById(R.id.toolbar_search_container);
searchEditText = searchToolbarContainer.findViewById(R.id.toolbar_search_edit_text);
@@ -901,4 +917,28 @@ public class SearchFragment
return true;
}
/*//////////////////////////////////////////////////////////////////////////
// Suggestion item touch helper
//////////////////////////////////////////////////////////////////////////*/
public int getSuggestionMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
final int position = viewHolder.getAdapterPosition();
final SuggestionItem item = suggestionListAdapter.getItem(position);
return item.fromHistory ? makeMovementFlags(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) : 0;
}
public void onSuggestionItemSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
final int position = viewHolder.getAdapterPosition();
final String query = suggestionListAdapter.getItem(position).query;
final Disposable onDelete = historyRecordManager.deleteSearchHistory(query)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
howManyDeleted -> suggestionPublisher
.onNext(searchEditText.getText().toString()),
throwable -> showSnackBarError(throwable,
UserAction.DELETE_FROM_HISTORY, "none",
"Deleting item failed", R.string.general_error));
disposables.add(onDelete);
}
}

View File

@@ -75,7 +75,7 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
});
}
private SuggestionItem getItem(int position) {
SuggestionItem getItem(int position) {
return items.get(position);
}

View File

@@ -1,19 +1,24 @@
package org.schabi.newpipe.info_list.holder;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.util.Linkify;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.jsoup.helper.StringUtil;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.CommentTextOnTouchListener;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.NavigationHelper;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.hdodenhof.circleimageview.CircleImageView;
public class CommentsMiniInfoItemHolder extends InfoItemHolder {
@@ -26,6 +31,25 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
private static final int commentDefaultLines = 2;
private static final int commentExpandedLines = 1000;
private String commentText;
private String streamUrl;
private static final Pattern pattern = Pattern.compile("(\\d+:)?(\\d+)?:(\\d+)");
private final Linkify.TransformFilter timestampLink = new Linkify.TransformFilter() {
@Override
public String transformUrl(Matcher match, String url) {
int timestamp = 0;
String hours = match.group(1);
String minutes = match.group(2);
String seconds = match.group(3);
if(hours != null) timestamp += (Integer.parseInt(hours.replace(":", ""))*3600);
if(minutes != null) timestamp += (Integer.parseInt(minutes.replace(":", ""))*60);
if(seconds != null) timestamp += (Integer.parseInt(seconds));
return streamUrl + url.replace(match.group(0), "#timestamp=" + String.valueOf(timestamp));
}
};
CommentsMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) {
super(infoItemBuilder, layoutId, parent);
@@ -53,6 +77,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
itemThumbnailView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(StringUtil.isBlank(item.getAuthorEndpoint())) return;
try {
final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext();
NavigationHelper.openChannelFragment(
@@ -66,34 +91,60 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
}
});
// ellipsize if not already ellipsized
if (null == itemContentView.getEllipsize()) {
itemContentView.setEllipsize(TextUtils.TruncateAt.END);
itemContentView.setMaxLines(commentDefaultLines);
streamUrl = item.getUrl();
itemContentView.setLines(commentDefaultLines);
commentText = item.getCommentText();
itemContentView.setText(commentText);
itemContentView.setOnTouchListener(CommentTextOnTouchListener.INSTANCE);
if (itemContentView.getLineCount() == 0) {
itemContentView.post(() -> ellipsize());
} else {
ellipsize();
}
itemContentView.setText(item.getCommentText());
if (null != item.getLikeCount()) {
itemLikesCountView.setText(String.valueOf(item.getLikeCount()));
}
itemPublishedTime.setText(item.getPublishedTime());
itemView.setOnClickListener(view -> {
toggleEllipsize(item.getCommentText());
toggleEllipsize();
if (itemBuilder.getOnCommentsSelectedListener() != null) {
itemBuilder.getOnCommentsSelectedListener().selected(item);
}
});
}
private void toggleEllipsize(String text) {
// toggle ellipsize
if (null == itemContentView.getEllipsize()) {
itemContentView.setEllipsize(TextUtils.TruncateAt.END);
itemContentView.setMaxLines(commentDefaultLines);
private void ellipsize() {
if (itemContentView.getLineCount() > commentDefaultLines){
int endOfLastLine = itemContentView.getLayout().getLineEnd(commentDefaultLines - 1);
int end = itemContentView.getText().toString().lastIndexOf(' ', endOfLastLine -2);
if(end == -1) end = Math.max(endOfLastLine -2, 0);
String newVal = itemContentView.getText().subSequence(0, end) + " …";
itemContentView.setText(newVal);
}
linkify();
}
private void toggleEllipsize() {
if (itemContentView.getText().toString().equals(commentText)) {
if (itemContentView.getLineCount() > commentDefaultLines) ellipsize();
} else {
itemContentView.setEllipsize(null);
itemContentView.setMaxLines(commentExpandedLines);
expand();
}
}
private void expand() {
itemContentView.setMaxLines(commentExpandedLines);
itemContentView.setText(commentText);
linkify();
}
private void linkify(){
Linkify.addLinks(itemContentView, Linkify.WEB_URLS);
Linkify.addLinks(itemContentView, pattern, null, null, timestampLink);
itemContentView.setMovementMethod(null);
}
}

View File

@@ -8,7 +8,11 @@ import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
@@ -21,13 +25,16 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.ThemeHelper;
import java.util.ArrayList;
@@ -104,6 +111,12 @@ public class StatisticsPlaylistFragment
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_history, menu);
}
///////////////////////////////////////////////////////////////////////////
// Fragment LifeCycle - Views
///////////////////////////////////////////////////////////////////////////
@@ -155,6 +168,53 @@ public class StatisticsPlaylistFragment
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_history_clear:
new AlertDialog.Builder(activity)
.setTitle(R.string.delete_view_history_alert)
.setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
.setPositiveButton(R.string.delete, ((dialog, which) -> {
final Disposable onDelete = recordManager.deleteWholeStreamHistory()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
howManyDeleted -> Toast.makeText(getContext(),
R.string.view_history_deleted,
Toast.LENGTH_SHORT).show(),
throwable -> ErrorActivity.reportError(getContext(),
throwable,
SettingsActivity.class, null,
ErrorActivity.ErrorInfo.make(
UserAction.DELETE_FROM_HISTORY,
"none",
"Delete view history",
R.string.general_error)));
final Disposable onClearOrphans = recordManager.removeOrphanedRecords()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
howManyDeleted -> {},
throwable -> ErrorActivity.reportError(getContext(),
throwable,
SettingsActivity.class, null,
ErrorActivity.ErrorInfo.make(
UserAction.DELETE_FROM_HISTORY,
"none",
"Delete search history",
R.string.general_error)));
disposables.add(onClearOrphans);
disposables.add(onDelete);
}))
.create()
.show();
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
///////////////////////////////////////////////////////////////////////////
// Fragment LifeCycle - Loading
///////////////////////////////////////////////////////////////////////////
@@ -335,7 +395,7 @@ public class StatisticsPlaylistFragment
deleteEntry(index);
break;
case 6:
shareUrl(item.toStreamInfoItem().getName(), item.toStreamInfoItem().getUrl());
ShareUtils.shareUrl(this.getContext(), item.toStreamInfoItem().getName(), item.toStreamInfoItem().getUrl());
break;
default:
break;

View File

@@ -34,6 +34,7 @@ import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.ShareUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -555,7 +556,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
deleteItem(item);
break;
case 7:
shareUrl(item.toStreamInfoItem().getName(), item.toStreamInfoItem().getUrl());
ShareUtils.shareUrl(this.getContext(), item.toStreamInfoItem().getName(), item.toStreamInfoItem().getUrl());
break;
default:
break;

View File

@@ -57,6 +57,7 @@ import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.views.CollapsibleView;
@@ -425,7 +426,7 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
}
private void shareChannel (ChannelInfoItem selectedItem) {
shareUrl(selectedItem.getName(), selectedItem.getUrl());
ShareUtils.shareUrl(this.getContext(), selectedItem.getName(), selectedItem.getUrl());
}
@SuppressLint("CheckResult")

View File

@@ -0,0 +1,30 @@
package org.schabi.newpipe.player;
import android.content.Context;
import android.content.ContextWrapper;
/**
* Fixes a leak caused by AudioManager using an Activity context.
* Tracked at https://android-review.googlesource.com/#/c/140481/1 and
* https://github.com/square/leakcanary/issues/205
* Source:
* https://gist.github.com/jankovd/891d96f476f7a9ce24e2
*/
public class AudioServiceLeakFix extends ContextWrapper {
AudioServiceLeakFix(Context base) {
super(base);
}
public static ContextWrapper preventLeakOf(Context base) {
return new AudioServiceLeakFix(base);
}
@Override
public Object getSystemService(String name) {
if (Context.AUDIO_SERVICE.equals(name)) {
return getApplicationContext().getSystemService(name);
}
return super.getSystemService(name);
}
}

View File

@@ -130,6 +130,11 @@ public final class BackgroundPlayer extends Service {
onClose();
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(base));
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
@@ -270,6 +275,8 @@ public final class BackgroundPlayer extends Service {
protected class BasePlayerImpl extends BasePlayer {
@NonNull final private AudioPlaybackResolver resolver;
private int cachedDuration;
private String cachedDurationString;
BasePlayerImpl(Context context) {
super(context);
@@ -344,10 +351,14 @@ public final class BackgroundPlayer extends Service {
if (!shouldUpdateOnProgress) return;
resetNotification();
if(Build.VERSION.SDK_INT >= 26 /*Oreo*/) updateNotificationThumbnail();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O /*Oreo*/) updateNotificationThumbnail();
if (bigNotRemoteView != null) {
if(cachedDuration != duration) {
cachedDuration = duration;
cachedDurationString = getTimeString(duration);
}
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + cachedDurationString);
}
if (notRemoteView != null) {
notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);

View File

@@ -207,8 +207,7 @@ public abstract class BasePlayer implements
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
final TrackSelection.Factory trackSelectionFactory =
PlayerHelper.getQualitySelector(context, bandwidthMeter);
final TrackSelection.Factory trackSelectionFactory = PlayerHelper.getQualitySelector(context);
this.trackSelector = new CustomTrackSelector(trackSelectionFactory);
this.loadControl = new LoadController(context);
@@ -225,7 +224,7 @@ public abstract class BasePlayer implements
public void initPlayer(final boolean playOnReady) {
if (DEBUG) Log.d(TAG, "initPlayer() called with: context = [" + context + "]");
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderFactory, trackSelector, loadControl);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(context, renderFactory, trackSelector, loadControl);
simpleExoPlayer.addListener(this);
simpleExoPlayer.setPlayWhenReady(playOnReady);
simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context));
@@ -270,6 +269,18 @@ public abstract class BasePlayer implements
final boolean playbackSkipSilence = intent.getBooleanExtra(PLAYBACK_SKIP_SILENCE,
getPlaybackSkipSilence());
// seek to timestamp if stream is already playing
if (simpleExoPlayer != null
&& queue.size() == 1
&& playQueue != null
&& playQueue.getItem() != null
&& queue.getItem().getUrl().equals(playQueue.getItem().getUrl())
&& queue.getItem().getRecoveryPosition() != PlayQueueItem.RECOVERY_UNSET
) {
simpleExoPlayer.seekTo(playQueue.getIndex(), queue.getItem().getRecoveryPosition());
return;
}
// Good to go...
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence,
/*playOnInit=*/true);

View File

@@ -46,6 +46,7 @@ import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
@@ -75,6 +76,7 @@ import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper;
@@ -241,6 +243,11 @@ public final class MainVideoPlayer extends AppCompatActivity
isBackPressed = false;
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(newBase));
}
/*//////////////////////////////////////////////////////////////////////////
// State Saving
//////////////////////////////////////////////////////////////////////////*/
@@ -277,14 +284,9 @@ public final class MainVideoPlayer extends AppCompatActivity
if (DEBUG) Log.d(TAG, "showSystemUi() called");
if (playerImpl != null && playerImpl.queueVisible) return;
final int visibility;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
} else {
visibility = View.STATUS_BAR_VISIBLE;
}
final int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ColorInt final int systenUiColor =
@@ -353,11 +355,7 @@ public final class MainVideoPlayer extends AppCompatActivity
protected void setShuffleButton(final ImageButton shuffleButton, final boolean shuffled) {
final int shuffleAlpha = shuffled ? 255 : 77;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
shuffleButton.setImageAlpha(shuffleAlpha);
} else {
shuffleButton.setAlpha(shuffleAlpha);
}
shuffleButton.setImageAlpha(shuffleAlpha);
}
private boolean isInMultiWindow() {
@@ -397,6 +395,7 @@ public final class MainVideoPlayer extends AppCompatActivity
private ImageButton playPauseButton;
private ImageButton playPreviousButton;
private ImageButton playNextButton;
private Button closeButton;
private RelativeLayout queueLayout;
private ImageButton itemsListCloseButton;
@@ -406,6 +405,7 @@ public final class MainVideoPlayer extends AppCompatActivity
private boolean queueVisible;
private ImageButton moreOptionsButton;
private ImageButton shareButton;
private ImageButton toggleOrientationButton;
private ImageButton switchPopupButton;
private ImageButton switchBackgroundButton;
@@ -437,9 +437,11 @@ public final class MainVideoPlayer extends AppCompatActivity
this.playPauseButton = rootView.findViewById(R.id.playPauseButton);
this.playPreviousButton = rootView.findViewById(R.id.playPreviousButton);
this.playNextButton = rootView.findViewById(R.id.playNextButton);
this.closeButton = rootView.findViewById(R.id.closeButton);
this.moreOptionsButton = rootView.findViewById(R.id.moreOptionsButton);
this.secondaryControls = rootView.findViewById(R.id.secondaryControls);
this.shareButton = rootView.findViewById(R.id.share);
this.toggleOrientationButton = rootView.findViewById(R.id.toggleOrientation);
this.switchBackgroundButton = rootView.findViewById(R.id.switchBackground);
this.switchPopupButton = rootView.findViewById(R.id.switchPopup);
@@ -483,8 +485,10 @@ public final class MainVideoPlayer extends AppCompatActivity
playPauseButton.setOnClickListener(this);
playPreviousButton.setOnClickListener(this);
playNextButton.setOnClickListener(this);
closeButton.setOnClickListener(this);
moreOptionsButton.setOnClickListener(this);
shareButton.setOnClickListener(this);
toggleOrientationButton.setOnClickListener(this);
switchBackgroundButton.setOnClickListener(this);
switchPopupButton.setOnClickListener(this);
@@ -635,6 +639,9 @@ public final class MainVideoPlayer extends AppCompatActivity
} else if (v.getId() == moreOptionsButton.getId()) {
onMoreOptionsClicked();
} else if (v.getId() == shareButton.getId()) {
onShareClicked();
} else if (v.getId() == toggleOrientationButton.getId()) {
onScreenRotationClicked();
@@ -644,6 +651,9 @@ public final class MainVideoPlayer extends AppCompatActivity
} else if (v.getId() == switchBackgroundButton.getId()) {
onPlayBackgroundButtonClicked();
} else if (v.getId() == closeButton.getId()) {
onPlaybackShutdown();
return;
}
if (getCurrentState() != STATE_COMPLETED) {
@@ -688,6 +698,13 @@ public final class MainVideoPlayer extends AppCompatActivity
showControls(DEFAULT_CONTROLS_DURATION);
}
private void onShareClicked() {
// share video at the current time (youtube.com/watch?v=ID&t=SECONDS)
ShareUtils.shareUrl(MainVideoPlayer.this,
playerImpl.getVideoTitle(),
playerImpl.getVideoUrl() + "&t=" + String.valueOf(playerImpl.getPlaybackSeekBar().getProgress()/1000));
}
private void onScreenRotationClicked() {
if (DEBUG) Log.d(TAG, "onScreenRotationClicked() called");
toggleOrientation();
@@ -770,6 +787,7 @@ public final class MainVideoPlayer extends AppCompatActivity
super.onBlocked();
playPauseButton.setImageResource(R.drawable.ic_pause_white);
animatePlayButtons(false, 100);
animateView(closeButton, false, DEFAULT_CONTROLS_DURATION);
getRootView().setKeepScreenOn(true);
}
@@ -785,6 +803,7 @@ public final class MainVideoPlayer extends AppCompatActivity
animateView(playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, false, 80, 0, () -> {
playPauseButton.setImageResource(R.drawable.ic_pause_white);
animatePlayButtons(true, 200);
animateView(closeButton, false, DEFAULT_CONTROLS_DURATION);
});
getRootView().setKeepScreenOn(true);
@@ -796,6 +815,7 @@ public final class MainVideoPlayer extends AppCompatActivity
animateView(playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, false, 80, 0, () -> {
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white);
animatePlayButtons(true, 200);
animateView(closeButton, false, DEFAULT_CONTROLS_DURATION);
});
showSystemUi();
@@ -815,8 +835,8 @@ public final class MainVideoPlayer extends AppCompatActivity
animateView(playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, false, 0, 0, () -> {
playPauseButton.setImageResource(R.drawable.ic_replay_white);
animatePlayButtons(true, DEFAULT_CONTROLS_DURATION);
animateView(closeButton, true, DEFAULT_CONTROLS_DURATION);
});
getRootView().setKeepScreenOn(false);
super.onCompleted();
}
@@ -851,8 +871,8 @@ public final class MainVideoPlayer extends AppCompatActivity
if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]");
getControlsVisibilityHandler().removeCallbacksAndMessages(null);
getControlsVisibilityHandler().postDelayed(() ->
animateView(getControlsRoot(), false, duration, 0,
MainVideoPlayer.this::hideSystemUi),
animateView(getControlsRoot(), false, duration, 0,
MainVideoPlayer.this::hideSystemUi),
/*delayMillis=*/delay
);
}
@@ -1056,9 +1076,9 @@ public final class MainVideoPlayer extends AppCompatActivity
final int resId =
currentProgressPercent <= 0 ? R.drawable.ic_volume_off_white_72dp
: currentProgressPercent < 0.25 ? R.drawable.ic_volume_mute_white_72dp
: currentProgressPercent < 0.75 ? R.drawable.ic_volume_down_white_72dp
: R.drawable.ic_volume_up_white_72dp;
: currentProgressPercent < 0.25 ? R.drawable.ic_volume_mute_white_72dp
: currentProgressPercent < 0.75 ? R.drawable.ic_volume_down_white_72dp
: R.drawable.ic_volume_up_white_72dp;
playerImpl.getVolumeImageView().setImageDrawable(
AppCompatResources.getDrawable(getApplicationContext(), resId)
@@ -1082,8 +1102,8 @@ public final class MainVideoPlayer extends AppCompatActivity
final int resId =
currentProgressPercent < 0.25 ? R.drawable.ic_brightness_low_white_72dp
: currentProgressPercent < 0.75 ? R.drawable.ic_brightness_medium_white_72dp
: R.drawable.ic_brightness_high_white_72dp;
: currentProgressPercent < 0.75 ? R.drawable.ic_brightness_medium_white_72dp
: R.drawable.ic_brightness_high_white_72dp;
playerImpl.getBrightnessImageView().setImageDrawable(
AppCompatResources.getDrawable(getApplicationContext(), resId)

View File

@@ -181,6 +181,11 @@ public final class PopupVideoPlayer extends Service {
closePopup();
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(base));
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;

View File

@@ -3,7 +3,6 @@ package org.schabi.newpipe.player;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
@@ -653,11 +652,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
}
final int shuffleAlpha = shuffled ? 255 : 77;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
shuffleButton.setImageAlpha(shuffleAlpha);
} else {
shuffleButton.setAlpha(shuffleAlpha);
}
shuffleButton.setImageAlpha(shuffleAlpha);
}
private void onPlaybackParameterChanged(final PlaybackParameters parameters) {

View File

@@ -212,7 +212,6 @@ public abstract class VideoPlayer extends BasePlayer
@Override
public void initListeners() {
super.initListeners();
playbackSeekBar.setOnSeekBarChangeListener(this);
playbackSpeedTextView.setOnClickListener(this);
qualityTextView.setOnClickListener(this);
@@ -298,7 +297,6 @@ public abstract class VideoPlayer extends BasePlayer
return true;
});
// Add all available captions
for (int i = 0; i < availableLanguages.size(); i++) {
final String captionLanguage = availableLanguages.get(i);
MenuItem captionItem = captionPopupMenu.getMenu().add(captionPopupMenuGroupId,
@@ -316,7 +314,6 @@ public abstract class VideoPlayer extends BasePlayer
captionPopupMenu.setOnDismissListener(this);
}
private void updateStreamRelatedViews() {
if (getCurrentMetadata() == null) return;
@@ -509,12 +506,12 @@ public abstract class VideoPlayer extends BasePlayer
}
// Normalize mismatching language strings
final String preferredLanguage = trackSelector.getPreferredTextLanguage();
final String preferredLanguage = trackSelector.getParameters().preferredTextLanguage;
// Build UI
buildCaptionMenu(availableLanguages);
if (trackSelector.getParameters().getRendererDisabled(textRenderer) ||
preferredLanguage == null || !availableLanguages.contains(preferredLanguage)) {
preferredLanguage == null || (!availableLanguages.contains(preferredLanguage)
&& !containsCaseInsensitive(availableLanguages, preferredLanguage))) {
captionTextView.setText(R.string.caption_none);
} else {
captionTextView.setText(preferredLanguage);
@@ -522,6 +519,15 @@ public abstract class VideoPlayer extends BasePlayer
captionTextView.setVisibility(availableLanguages.isEmpty() ? View.GONE : View.VISIBLE);
}
// workaround to match normalized captions like english to English or deutsch to Deutsch
private static boolean containsCaseInsensitive(List<String> list, String toFind) {
for(String i : list){
if(i.equalsIgnoreCase(toFind))
return true;
}
return false;
}
/*//////////////////////////////////////////////////////////////////////////
// General Player
//////////////////////////////////////////////////////////////////////////*/

View File

@@ -12,13 +12,11 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.analytics.AnalyticsListener;
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener,
AudioRendererEventListener {
AnalyticsListener {
private static final String TAG = "AudioFocusReactor";
@@ -42,7 +40,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener,
this.player = player;
this.context = context;
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
player.addAudioDebugListener(this);
player.addAnalyticsListener(this);
if (SHOULD_BUILD_FOCUS_REQUEST) {
request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE)
@@ -57,7 +55,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener,
public void dispose() {
abandonAudioFocus();
player.removeAudioDebugListener(this);
player.removeAnalyticsListener(this);
}
/*//////////////////////////////////////////////////////////////////////////
@@ -164,29 +162,12 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener,
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onAudioSessionId(int i) {
public void onAudioSessionId(EventTime eventTime, int audioSessionId) {
if (!PlayerHelper.isUsingDSP(context)) return;
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, i);
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId);
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
context.sendBroadcast(intent);
}
@Override
public void onAudioEnabled(DecoderCounters decoderCounters) {}
@Override
public void onAudioDecoderInitialized(String s, long l, long l1) {}
@Override
public void onAudioInputFormatChanged(Format format) {}
@Override
public void onAudioSinkUnderrun(int bufferSize,
long bufferSizeMs,
long elapsedSinceLastFeedMs) {}
@Override
public void onAudioDisabled(DecoderCounters decoderCounters) {}
}

View File

@@ -33,14 +33,14 @@ import java.io.File;
public CacheFactory(@NonNull final Context context,
@NonNull final String userAgent,
@NonNull final TransferListener<? super DataSource> transferListener) {
@NonNull final TransferListener transferListener) {
this(context, userAgent, transferListener, PlayerHelper.getPreferredCacheSize(context),
PlayerHelper.getPreferredFileSize(context));
}
private CacheFactory(@NonNull final Context context,
@NonNull final String userAgent,
@NonNull final TransferListener<? super DataSource> transferListener,
@NonNull final TransferListener transferListener,
final long maxCacheSize,
final long maxFileSize) {
this.maxFileSize = maxFileSize;

View File

@@ -2,17 +2,12 @@ package org.schabi.newpipe.player.helper;
import android.content.Context;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS;
import static com.google.android.exoplayer2.DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES;
public class LoadController implements LoadControl {
@@ -36,15 +31,10 @@ public class LoadController implements LoadControl {
final int optimalPlaybackBufferMs) {
this.initialPlaybackBufferUs = initialPlaybackBufferMs * 1000;
final DefaultAllocator allocator = new DefaultAllocator(true,
C.DEFAULT_BUFFER_SEGMENT_SIZE);
internalLoadControl = new DefaultLoadControl(allocator,
/*minBufferMs=*/minimumPlaybackbufferMs,
/*maxBufferMs=*/optimalPlaybackBufferMs,
/*bufferForPlaybackMs=*/initialPlaybackBufferMs,
/*bufferForPlaybackAfterRebufferMs=*/initialPlaybackBufferMs,
DEFAULT_TARGET_BUFFER_BYTES, DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS);
DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder();
builder.setBufferDurationsMs(minimumPlaybackbufferMs, optimalPlaybackBufferMs,
initialPlaybackBufferMs, initialPlaybackBufferMs);
internalLoadControl = builder.createDefaultLoadControl();
}
/*//////////////////////////////////////////////////////////////////////////

View File

@@ -12,6 +12,7 @@ import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener;
public class PlayerDataSource {
@@ -24,7 +25,7 @@ public class PlayerDataSource {
public PlayerDataSource(@NonNull final Context context,
@NonNull final String userAgent,
@NonNull final TransferListener<? super DataSource> transferListener) {
@NonNull final TransferListener transferListener) {
cacheDataSourceFactory = new CacheFactory(context, userAgent, transferListener);
cachelessDataSourceFactory = new DefaultDataSourceFactory(context, userAgent, transferListener);
}
@@ -32,21 +33,21 @@ public class PlayerDataSource {
public SsMediaSource.Factory getLiveSsMediaSourceFactory() {
return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory(
cachelessDataSourceFactory), cachelessDataSourceFactory)
.setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY)
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY))
.setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS);
}
public HlsMediaSource.Factory getLiveHlsMediaSourceFactory() {
return new HlsMediaSource.Factory(cachelessDataSourceFactory)
.setAllowChunklessPreparation(true)
.setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY);
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY));
}
public DashMediaSource.Factory getLiveDashMediaSourceFactory() {
return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory(
cachelessDataSourceFactory), cachelessDataSourceFactory)
.setMinLoadableRetryCount(MANIFEST_MINIMUM_RETRY)
.setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS);
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(MANIFEST_MINIMUM_RETRY))
.setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS, true);
}
public SsMediaSource.Factory getSsMediaSourceFactory() {
@@ -65,7 +66,7 @@ public class PlayerDataSource {
public ExtractorMediaSource.Factory getExtractorMediaSourceFactory() {
return new ExtractorMediaSource.Factory(cacheDataSourceFactory)
.setMinLoadableRetryCount(EXTRACTOR_MINIMUM_RETRY);
.setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY));
}
public ExtractorMediaSource.Factory getExtractorMediaSourceFactory(@NonNull final String key) {

View File

@@ -14,7 +14,6 @@ import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes;
import org.schabi.newpipe.R;
@@ -70,10 +69,10 @@ public class PlayerHelper {
////////////////////////////////////////////////////////////////////////////
public static String getTimeString(int milliSeconds) {
long seconds = (milliSeconds % 60000L) / 1000L;
long minutes = (milliSeconds % 3600000L) / 60000L;
long hours = (milliSeconds % 86400000L) / 3600000L;
long days = (milliSeconds % (86400000L * 7L)) / 86400000L;
int seconds = (milliSeconds % 60000) / 1000;
int minutes = (milliSeconds % 3600000) / 60000;
int hours = (milliSeconds % 86400000) / 3600000;
int days = (milliSeconds % (86400000 * 7)) / 86400000;
stringBuilder.setLength(0);
return days > 0 ? stringFormatter.format("%d:%02d:%02d:%02d", days, hours, minutes, seconds).toString()
@@ -240,9 +239,8 @@ public class PlayerHelper {
return 60000;
}
public static TrackSelection.Factory getQualitySelector(@NonNull final Context context,
@NonNull final BandwidthMeter meter) {
return new AdaptiveTrackSelection.Factory(meter,
public static TrackSelection.Factory getQualitySelector(@NonNull final Context context) {
return new AdaptiveTrackSelection.Factory(
/*bufferDurationRequiredForQualityIncrease=*/1000,
AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,

View File

@@ -1,12 +1,13 @@
package org.schabi.newpipe.player.mediasource;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.source.BaseMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
@@ -79,7 +80,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
}
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
return null;
}
@@ -88,7 +89,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
@Override
protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
Log.e(TAG, "Loading failed source: ", error);
}

View File

@@ -2,12 +2,13 @@ package org.schabi.newpipe.player.mediasource;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
@@ -36,9 +37,8 @@ public class LoadedMediaSource implements ManagedMediaSource {
}
@Override
public void prepareSource(ExoPlayer player, boolean isTopLevelSource,
SourceInfoRefreshListener listener) {
source.prepareSource(player, isTopLevelSource, listener);
public void prepareSource(SourceInfoRefreshListener listener, @Nullable TransferListener mediaTransferListener) {
source.prepareSource(listener, mediaTransferListener);
}
@Override
@@ -47,8 +47,8 @@ public class LoadedMediaSource implements ManagedMediaSource {
}
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
return source.createPeriod(id, allocator);
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
return source.createPeriod(id, allocator, startPositionUs);
}
@Override

View File

@@ -1,5 +1,5 @@
package org.schabi.newpipe.player.mediasource;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -86,21 +86,22 @@ public class ManagedMediaSourcePlaylist {
/**
* Invalidates the {@link ManagedMediaSource} at the given index by replacing it
* with a {@link PlaceholderMediaSource}.
* @see #update(int, ManagedMediaSource, Runnable)
* @see #update(int, ManagedMediaSource, Handler, Runnable)
* */
public synchronized void invalidate(final int index,
@Nullable final Handler handler,
@Nullable final Runnable finalizingAction) {
if (get(index) instanceof PlaceholderMediaSource) return;
update(index, new PlaceholderMediaSource(), finalizingAction);
update(index, new PlaceholderMediaSource(), handler, finalizingAction);
}
/**
* Updates the {@link ManagedMediaSource} in {@link ConcatenatingMediaSource}
* at the given index with a given {@link ManagedMediaSource}.
* @see #update(int, ManagedMediaSource, Runnable)
* @see #update(int, ManagedMediaSource, Handler, Runnable)
* */
public synchronized void update(final int index, @NonNull final ManagedMediaSource source) {
update(index, source, /*doNothing=*/null);
update(index, source, null, /*doNothing=*/null);
}
/**
@@ -108,9 +109,10 @@ public class ManagedMediaSourcePlaylist {
* at the given index with a given {@link ManagedMediaSource}. If the index is out of bound,
* then the replacement is ignored.
* @see ConcatenatingMediaSource#addMediaSource
* @see ConcatenatingMediaSource#removeMediaSource(int, Runnable)
* @see ConcatenatingMediaSource#removeMediaSource(int, Handler, Runnable)
* */
public synchronized void update(final int index, @NonNull final ManagedMediaSource source,
@Nullable final Handler handler,
@Nullable final Runnable finalizingAction) {
if (index < 0 || index >= internalSource.getSize()) return;
@@ -126,6 +128,6 @@ public class ManagedMediaSourcePlaylist {
// Because of the above race condition, it is thus only safe to synchronize the player
// in the finalizing action AFTER the removal is complete and the timeline has changed.
internalSource.removeMediaSource(index, finalizingAction);
internalSource.removeMediaSource(index, handler, finalizingAction);
}
}

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