1
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-09-22 21:40:52 +02:00

Compare commits

...

206 Commits

Author SHA1 Message Date
Christian Schabesberger
b52dee37f4 move on to version v0.13.7 2018-07-23 18:54:40 +02:00
Ali Demirtas
21bd9f09da Translated using Weblate (Turkish)
Currently translated at 100,0% (383 of 383 strings)
2018-07-22 18:53:19 +02:00
Weblate
44f24e58f6 Merge branch 'origin/dev' into Weblate 2018-07-22 15:03:59 +02:00
Allan Nordhøy
860c4d045a Translated using Weblate (Norwegian Bokmål)
Currently translated at 95.8% (367 of 383 strings)
2018-07-22 15:03:58 +02:00
Marc Riera
3b0c96f654 Translated using Weblate (Catalan)
Currently translated at 100.0% (383 of 383 strings)
2018-07-22 15:03:56 +02:00
Jeff Huang
65b744472b Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (383 of 383 strings)
2018-07-22 15:03:53 +02:00
Christian Schabesberger
26489b0f00 fix filters 2018-07-22 13:55:17 +02:00
Marc Riera
414abad05f Translated using Weblate (Catalan)
Currently translated at 100,0% (383 of 383 strings)
2018-07-22 12:41:26 +02:00
Heimen Stoffels
735d9a5391 Translated using Weblate (Dutch)
Currently translated at 100.0% (383 of 383 strings)
2018-07-22 11:40:53 +02:00
Osoitz
50571449cb Translated using Weblate (Basque)
Currently translated at 100.0% (383 of 383 strings)
2018-07-22 11:01:08 +02:00
Weblate
a31aacd115 Merge branch 'origin/dev' into Weblate 2018-07-22 10:57:42 +02:00
Rex_sa
f5b57cc0da Translated using Weblate (Arabic)
Currently translated at 100.0% (379 of 379 strings)
2018-07-22 10:57:42 +02:00
Osoitz
b7006a8f2c Translated using Weblate (Basque)
Currently translated at 100.0% (379 of 379 strings)
2018-07-22 10:57:35 +02:00
Christian Schabesberger
82bb467a2a move on to version v0.13.6 2018-07-21 14:35:03 +02:00
Christian Schabesberger
3a44e92432 Merge branch 'search' into dev 2018-07-19 16:19:33 +02:00
Christian Schabesberger
e60db5f928 make new filtersystem translatable 2018-07-19 16:18:57 +02:00
Ariel Shulman
78485287a4 Translated using Weblate (Hebrew)
Currently translated at 82.3% (312 of 379 strings)
2018-07-18 20:37:59 +02:00
D D
48b6f01b13 Translated using Weblate (Bulgarian)
Currently translated at 97.8% (371 of 379 strings)
2018-07-18 17:35:33 +02:00
Christian Schabesberger
39e04de208 show radio pin for content filter again 2018-07-18 15:05:49 +02:00
Next Hubs
68d5b59693 Translated using Weblate (Urdu)
Currently translated at 5.0% (19 of 379 strings)
2018-07-18 12:43:31 +02:00
Andrea Troiano
4ef01ef745 Translated using Weblate (Italian)
Currently translated at 100,0% (379 of 379 strings)
2018-07-18 10:28:06 +02:00
Rex_sa
573fa8870c Translated using Weblate (Arabic)
Currently translated at 100.0% (379 of 379 strings)
2018-07-17 14:34:21 +02:00
Rex_sa
88d354b08b Translated using Weblate (Arabic)
Currently translated at 100,0% (379 of 379 strings)
2018-07-16 13:17:38 +02:00
Rex_sa
0ff65b5496 Translated using Weblate (Arabic)
Currently translated at 100.0% (379 of 379 strings)
2018-07-15 21:34:22 +02:00
Christian Schabesberger
14e0dcb085 fix names from UIH to LinkHandler 2018-07-15 21:21:09 +02:00
Rex_sa
e008fd21a4 Translated using Weblate (Arabic)
Currently translated at 100.0% (379 of 379 strings)
2018-07-14 21:00:07 +02:00
Nathan Follens
4638149ad0 Translated using Weblate (Flemish)
Currently translated at 100,0% (379 of 379 strings)
2018-07-11 20:52:24 +02:00
Tobias Groza
e386bdd6b3 Translated using Weblate (Greek)
Currently translated at 19.7% (75 of 379 strings)
2018-07-11 18:38:04 +02:00
Christian Schabesberger
decb167ba9 make the new extractor refactorings work with SoundCloud 2018-07-10 16:26:42 +02:00
Tobias Groza
dd9557c13e Translated using Weblate (Greek)
Currently translated at 19.5% (74 of 379 strings)
2018-07-10 02:38:34 +02:00
Lee Hoe Mun
708d7162fb Translated using Weblate (Chinese (Mandarin))
Currently translated at 16.6% (63 of 379 strings)
2018-07-09 20:35:11 +02:00
Michalis Nikolaidis
1ee1b522f1 Translated using Weblate (Greek)
Currently translated at 19,5% (74 of 379 strings)
2018-07-09 02:11:31 +02:00
Christian Schabesberger
d5a500c037 bring everything to compile and run 2018-07-08 17:46:21 +02:00
Eduardo Caron
3e02c65bc0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (379 of 379 strings)
2018-07-08 15:22:38 +02:00
Christian Schabesberger
d10f9a5f25 add getMoreInfo to SearchInfo 2018-07-08 14:45:00 +02:00
AB
17e7214d25 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (379 of 379 strings)
2018-07-08 09:28:02 +02:00
Víctor Manuel Tapia Ramírez
22774592db Translated using Weblate (Spanish)
Currently translated at 100,0% (379 of 379 strings)
2018-07-07 21:07:00 +02:00
Freddy Morán Jr
7c2aa6e69d Translated using Weblate (Spanish)
Currently translated at 100,0% (379 of 379 strings)
2018-07-07 21:06:55 +02:00
Ali Demirtas
d1dbcda88e Translated using Weblate (Turkish)
Currently translated at 100,0% (379 of 379 strings)
2018-07-07 19:03:18 +02:00
Jeff Huang
3e05508cf9 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (379 of 379 strings)
2018-07-07 15:10:47 +02:00
Heimen Stoffels
1acdefd358 Translated using Weblate (Dutch)
Currently translated at 100.0% (379 of 379 strings)
2018-07-07 11:06:57 +02:00
Marc Riera
23143797f9 Translated using Weblate (Catalan)
Currently translated at 100,0% (379 of 379 strings)
2018-07-07 10:27:11 +02:00
ssantos
3364bf268b Translated using Weblate (German)
Currently translated at 100,0% (379 of 379 strings)
2018-07-07 07:51:52 +02:00
Weblate
2025d6305e Merge branch 'origin/dev' into Weblate 2018-07-07 07:48:38 +02:00
cxj
639ad7698d Translated using Weblate (Chinese (Mandarin))
Currently translated at 15,6% (59 of 378 strings)
2018-07-07 07:48:37 +02:00
D D
4eaff51ba2 Translated using Weblate (Bulgarian)
Currently translated at 61,9% (234 of 378 strings)
2018-07-07 07:48:35 +02:00
ssantos
1fb30bc3d9 Translated using Weblate (German)
Currently translated at 100,0% (378 of 378 strings)
2018-07-07 07:48:33 +02:00
Christian Schabesberger
6b66f40bcb Merge pull request #1392 from karyogamy/exoplayer-2.8.0-update
ExoPlayer 2.8.2 Update
2018-07-05 13:02:21 +02:00
Allan Nordhøy
a3cd531cc8 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.0% (363 of 378 strings)
2018-07-04 00:40:31 +02:00
Nathan Follens
55c84192be Translated using Weblate (Flemish)
Currently translated at 100.0% (378 of 378 strings)
2018-07-03 09:36:55 +02:00
Víctor Manuel Tapia Ramírez
aa9018b97b Translated using Weblate (Spanish)
Currently translated at 100.0% (378 of 378 strings)
2018-07-03 00:43:30 +02:00
monolifed
1e79c146a7 Translated using Weblate (Turkish)
Currently translated at 100.0% (378 of 378 strings)
2018-07-02 15:43:34 +02:00
Marian Hanzel
cb8545e33d Translated using Weblate (Slovak)
Currently translated at 96.0% (363 of 378 strings)
2018-07-02 09:44:01 +02:00
Nathan Follens
4a484c535b Translated using Weblate (Flemish)
Currently translated at 100,0% (378 of 378 strings)
2018-07-02 09:27:09 +02:00
Víctor Manuel Tapia Ramírez
ee417e41ea Translated using Weblate (Spanish)
Currently translated at 100,0% (378 of 378 strings)
2018-07-02 00:16:04 +02:00
Eduardo Caron
3cdc1fcaee Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (378 of 378 strings)
2018-07-01 22:45:25 +02:00
Jeff Huang
0a023a61f9 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (378 of 378 strings)
2018-07-01 15:21:02 +02:00
monolifed
73f81c5b52 Translated using Weblate (Turkish)
Currently translated at 100.0% (378 of 378 strings)
2018-07-01 14:48:03 +02:00
Marc Riera
bc4acbb7e1 Translated using Weblate (Catalan)
Currently translated at 100,0% (378 of 378 strings)
2018-07-01 12:39:58 +02:00
Heimen Stoffels
26d07ea2c6 Translated using Weblate (Dutch)
Currently translated at 100.0% (378 of 378 strings)
2018-07-01 11:40:26 +02:00
Weblate
5380c8352d Merge branch 'origin/dev' into Weblate 2018-07-01 08:42:10 +02:00
Anton Shestakov
e85e91183e Translated using Weblate (Russian)
Currently translated at 99.4% (371 of 373 strings)
2018-07-01 08:42:07 +02:00
Christian Schabesberger
a208a22bc2 add link to the incredible bugreport converter 2018-06-29 14:03:15 +02:00
John Zhen Mo
644766b5a6 -Updated exoplayer lib to 2.8.2. 2018-06-28 12:21:03 -07:00
John Zhen Mo
ca679f5932 -Fixed potential NPE when updating thumbnail in background player. 2018-06-28 12:18:02 -07:00
John Zhen Mo
7f7145e8de -Fixed playback parameter dialog settings not persisting through rotation.
-Moved playback parameter dialog step size selector to below pitch slider.
2018-06-28 12:04:30 -07:00
John Zhen Mo
aa1878c15a -Changed baseplayer metadata getters to use media tag as source.
-Changed background player notification to no longer update bitmap on progress time change.
-Changed popup player to move above soft keyboard when it is opened.
2018-06-28 12:04:30 -07:00
John Zhen Mo
e7d23176b7 -Fixed database backup failing due to journal file name change after Room DB version update. 2018-06-28 12:04:30 -07:00
John Zhen Mo
31218c2a8c -Fixed popup player notification metadata not updated on stream change.
-Fixed popup player window not clipped to above soft input keyboard upon expansion.
2018-06-28 12:03:20 -07:00
John Zhen Mo
06374c82fd -Fixed video players end screen not cleared on restarting playback after single stream play queue is completed. 2018-06-28 12:03:20 -07:00
John Zhen Mo
8efcc8f80f -Fixed main video player end screen thumbnail not fitting screen aspect ratio. 2018-06-28 12:03:20 -07:00
John Zhen Mo
2d6317bd24 -Fixed audio-only streams thumbnail not displaying on video players.
-Fixed potential play queue desynchronization due to fast forwarding on silence.
-Added current thumbnail storing in base player to allow immediate retrieval for notification building.
-Removed video player buffer spinner during interim buffering but not initial buffering.
-Reverted foreground notification stopping on pause and on complete.
2018-06-28 12:03:20 -07:00
John Zhen Mo
157b064214 -Fixed player database and progress disposable disposed when destroying exoplayer.
-Fixed livestream not reloading on behind live window exception.
-Added nonnull annotation to player intent strings.
2018-06-28 12:01:34 -07:00
John Zhen Mo
0ece4851d2 -Updated ExoPlayer to 2.8.1, fixing livestream with long duration not loading.
-Updated OkHttp to 3.10.0 and RxJava to 2.1.14.
-Changed player recovery seek to use ExoPlayer built-in window seeking instead of seeking after stream window starts playing.
-Changed playback speed changer default step size to 25%.
-Changed player notification to reset on all state changes.
-Fixed gradle dependency version incorrect variable names.
-Fixed video player double tap not working during pause.
-[#1412] Fixed NPE when sharing video to main video activity when it was playing but is out of focus: Reset main player state when new intent is received.
-[#1410] Fixed fast forwarding and rewinding not working within 10 seconds from beginning or end of a stream window.
2018-06-28 12:01:34 -07:00
John Zhen Mo
f1f5996975 -Refactored playback resolvers and other persistent player objects to instantiate once only during player creation to enforce non-nullity.
-Fixed background and popup player service staying in foreground when playback is paused or completed.
-Fixed player metadata not updating on new stream.
-Fixed player intent playback quality not applied.
-Fixed player auto-queue not applied after stream transition or swapping.
2018-06-28 12:00:00 -07:00
John Zhen Mo
0a2dbc4688 -Fixed playlist fragment infinite update cycle.
-Updated Room DB version to 1.1.0.
2018-06-28 11:59:59 -07:00
John Zhen Mo
13587d7ab3 -Fixed some typos. 2018-06-28 11:58:33 -07:00
John Zhen Mo
0fcef064fb -Reduced fling speed required to close popup by 40%. 2018-06-28 11:58:33 -07:00
John Zhen Mo
19b8796cbc -Fixed statistics fragment button not animating when pressed.
-Removed background player notification button opacity change.
2018-06-28 11:58:33 -07:00
John Zhen Mo
15fb60a845 -Fixed bookmarked playlist not updating metadata when changed. 2018-06-28 11:58:32 -07:00
John Zhen Mo
5c202f04e7 -[#1383]Fixed popup player caption selector not populating due to full width aspect ratio selector.
-Fixed potential memory leak in media session connector containing player instance.
2018-06-28 11:58:32 -07:00
John Zhen Mo
bc6fdf81d2 -Refactored player media source resolution into external helpers.
-Baked resolved media metadata into media source for one-way data passing.
2018-06-28 11:58:32 -07:00
John Zhen Mo
3194a2bf2c -Fixed skip silence state not maintained by player on new queue.
-Fixed TrackSelector deprecations.
2018-06-28 11:58:32 -07:00
John Zhen Mo
72d1e5131f -Added skip silence toggle to playback speed control.
-Added step size selector to playback speed control.
-Added skip silence flag to player intents.
-Moved default preset in playback speed control to neutral dialog button, renamed as reset.
-Removed nightcore preset from playback speed control.
2018-06-28 11:58:32 -07:00
John Zhen Mo
7721098551 -Updated ExoPlayer to 2.8.0
-Updated MediaSource contracts in ManagedMediaSource.
-Changed PlaceholderMediaSource and FailedMediaSource to use built-in BaseMediaSource implementation.
-Changed deprecated DynamicConcatenatingMediaSource to ConcatenatingMediaSource.
-Removed manual playlist media source disposal in favor of player built-in disposal.
2018-06-28 11:58:32 -07:00
Christian Schabesberger
f563bc4210 Merge pull request #1510 from karyogamy/lib-update
Library version update and database backup fix
2018-06-28 12:16:04 +02:00
Christian Schabesberger
43e7be9b86 Merge pull request #1509 from karyogamy/main-video-player-fix
Main video player fix
2018-06-28 12:00:54 +02:00
John Zhen Mo
27131d15dd -Updated room db to 1.1.1.
-Fixed database import/export to no longer include accessory db files to ensure backward compatibility.
2018-06-26 12:26:01 -07:00
John Zhen Mo
fb1a290bd9 -Updated okHttp to 3.10.0.
-Updated mockito to 2.8.9.
-Updated rxJava to 2.1.14.
-Fixed stetho to use correct lib version.
2018-06-26 12:02:26 -07:00
John Zhen Mo
ef16145695 -Fixed player new share intent causing main player crash due to player activity in background. 2018-06-26 10:21:43 -07:00
John Zhen Mo
4fbd1182c2 -Fixed minimizing to popup player does not destroying existing player when drawing over app permission is not granted. 2018-06-26 10:19:16 -07:00
Christian Schabesberger
2d39e65b5c Merge branch '640-screen-off' of https://github.com/krtkush/NewPipe into test 2018-06-26 11:23:45 +02:00
Kartikey Kushwaha
8e96b675fa Removed unwanted files. 2018-06-26 01:13:21 +05:30
Christian Schabesberger
adb6943420 Merge pull request #1354 from karyogamy/minimize-on-exit
Minimize main player on exit
2018-06-25 19:46:13 +02:00
Christian Schabesberger
eae7babf93 Merge pull request #1454 from Somethingweirdhere/dev
Added share option to long tap menu
2018-06-25 15:28:37 +02:00
Christian Schabesberger
7d5e18c05b Merge pull request #1498 from Somethingweirdhere/download
Download option in share menu
2018-06-25 12:35:34 +02:00
Somethingweirdhere
cbe001efd6 Added option to menu 2018-06-25 12:04:11 +02:00
Christian Schabesberger
86b783fb0f Merge pull request #1472 from acrosca/undo_delete
undo delete
2018-06-25 10:04:17 +02:00
Christian Schabesberger
ccc27b48df Merge pull request #1497 from karyogamy/view-history-fix
View history fix
2018-06-25 09:26:08 +02:00
Tobias Groza
a32391f560 Translated using Weblate (German)
Currently translated at 100.0% (373 of 373 strings)
2018-06-24 17:38:37 +02:00
nautilusx
aed0348802 Translated using Weblate (German)
Currently translated at 100.0% (373 of 373 strings)
2018-06-24 17:38:32 +02:00
Rossinière Vaud
1b66446c0d Translated using Weblate (Polish)
Currently translated at 100.0% (373 of 373 strings)
2018-06-24 12:42:40 +02:00
Tobias Groza
2bc0c8a483 Translated using Weblate (German)
Currently translated at 100,0% (373 of 373 strings)
2018-06-23 17:09:58 +02:00
DafabHoid
3f7e02e305 Translated using Weblate (German)
Currently translated at 100,0% (373 of 373 strings)
2018-06-23 17:09:53 +02:00
nautilusx
dd0d666003 Translated using Weblate (German)
Currently translated at 100,0% (373 of 373 strings)
2018-06-23 17:09:47 +02:00
Tobias Groza
81859a37de Translated using Weblate (German)
Currently translated at 100,0% (373 of 373 strings)
2018-06-23 17:05:55 +02:00
rimasx
180bb581a3 Translated using Weblate (Estonian)
Currently translated at 94.6% (353 of 373 strings)
2018-06-23 16:37:11 +02:00
yuriqdev
2f31779af4 Translated using Weblate (Russian)
Currently translated at 99.7% (372 of 373 strings)
2018-06-23 13:42:42 +02:00
Rossinière Vaud
ee6d512165 Translated using Weblate (Polish)
Currently translated at 100,0% (373 of 373 strings)
2018-06-23 12:08:23 +02:00
Weblate
1470fdc057 Merge branch 'origin/dev' into Weblate 2018-06-22 09:35:50 +02:00
rimasx
93bbaf187e Translated using Weblate (Estonian)
Currently translated at 94.6% (353 of 373 strings)
2018-06-22 09:35:46 +02:00
Víctor Manuel Tapia Ramírez
f1e43007f1 Translated using Weblate (Chinese (Mandarin))
Currently translated at 6.4% (24 of 373 strings)
2018-06-22 09:35:21 +02:00
D D
155436b85d Translated using Weblate (Bulgarian)
Currently translated at 62.7% (234 of 373 strings)
2018-06-22 09:35:18 +02:00
Somethingweirdhere
f3e029c3f6 Cleaned code, downloaddialog now also appears after giving storage permission. 2018-06-20 14:46:57 +02:00
Christian Schabesberger
90d6416f55 Merge pull request #1491 from annoyatron255/video-info-fix
Fix #1440 Broken Video Info Layout
2018-06-19 09:50:02 +02:00
Ale-Ma
af2a2e45af Translated using Weblate (Italian)
Currently translated at 100.0% (373 of 373 strings)
2018-06-19 09:40:03 +02:00
Andrea Troiano
e79eda9c5c Translated using Weblate (Italian)
Currently translated at 100.0% (373 of 373 strings)
2018-06-19 09:39:58 +02:00
John Zhen Mo
b338d9dbcf -Fixed view not registered when playback is started on external players. 2018-06-18 18:27:37 -07:00
John Zhen Mo
7fb9345344 -Fixed remote playlist metadata not updated when remote source data has changed. 2018-06-18 18:22:52 -07:00
Weblate
77b488568b Merge branch 'origin/dev' into Weblate 2018-06-17 15:56:31 +02:00
Edwar Tikhonov
fcf650c6eb Translated using Weblate (Russian)
Currently translated at 100.0% (373 of 373 strings)
2018-06-17 15:56:30 +02:00
rimasx
0c21023ad8 Added translation using Weblate (Estonian) 2018-06-17 15:56:28 +02:00
Somethingweirdhere
8f35a56ec8 Added download to share menu 2018-06-17 13:55:43 +02:00
annoyatron255
95ba1873e4 Fix #1440 Broken Video Info Layout 2018-06-16 18:12:56 -05:00
Andrei.Rosca
8b8652d44c undo delete - code format 2018-06-15 16:15:55 +02:00
Issam Maghni
2515b8167f Disable animation (hidden anyway by navigation) 2018-06-15 01:21:30 -04:00
Andrei.Rosca
09dd044f3d undo delete 2018-06-13 09:07:57 +02:00
Dual Natan
ace0ed9667 Translated using Weblate (Swedish)
Currently translated at 68.9% (257 of 373 strings)
2018-06-12 22:43:59 +02:00
Dual Natan
cf03708da2 Translated using Weblate (Macedonian)
Currently translated at 100.0% (373 of 373 strings)
2018-06-11 21:21:57 +02:00
Edwar Tikhonov
d4670bf6fa Translated using Weblate (Russe)
Currently translated at 100,0% (373 of 373 strings)
2018-06-11 16:04:29 +02:00
Edwar Tikhonov
feea448a24 Translated using Weblate (Русский)
Currently translated at 100,0% (373 of 373 strings)
2018-06-10 15:17:20 +02:00
aiddroid
71ad54652b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (373 of 373 strings)
2018-06-10 10:35:41 +02:00
aiddroid
8e1deda7b0 Translated using Weblate (Chinese (Mandarin))
Currently translated at 0.0% (0 of 373 strings)
2018-06-10 09:35:42 +02:00
aiddroid
752f985e13 Translated using Weblate (简体中文(Chinese Simplified))
Currently translated at 100.0% (373 of 373 strings)
2018-06-09 10:09:35 +02:00
Kartikey Kushwaha
89e3219e06 Further fixes wrt FLAG_NOT_FOCUSABLE. 2018-06-09 01:38:57 +05:30
Kartikey Kushwaha
429dddc6c9 reintroduced hideControls method. 2018-06-09 01:13:37 +05:30
Kartikey Kushwaha
981174a490 Fixed bug #640. 2018-06-09 01:01:13 +05:30
Somethingweirdhere
201f7e9848 Added share option to Popup and Background queues 2018-06-08 15:59:05 +02:00
kapodamy
bb0d8ad58a Translated using Weblate (Spanish)
Currently translated at 99.7% (372 of 373 strings)
2018-06-08 01:44:11 +02:00
Weblate
29e64f7c1a Merge branch 'origin/dev' into Weblate 2018-06-06 20:37:29 +02:00
JAPP
4819ebd56e Translated using Weblate (French)
Currently translated at 99.1% (370 of 373 strings)
2018-06-06 20:37:23 +02:00
John Zhen Mo
3b603b0637 -Added back button press check to destroy rather than minimize main video player. 2018-06-05 23:37:20 -07:00
Somethingweirdhere
baa63249d1 Added share option to long tap menu 2018-06-05 19:48:31 +02:00
Somethingweirdhere
ee347e3081 Merge pull request #1 from TeamNewPipe/dev
Up to date
2018-06-05 19:35:47 +02:00
Christian Schabesberger
f96bc95053 Update CONTRIBUTING.md 2018-06-05 11:03:48 +02:00
John Zhen Mo
e1df4757e4 -Expanded minimize to exit to allow resuming on background player.
-Modified minimize to exit toggle to selection dialog.
2018-06-03 14:09:16 -07:00
John Zhen Mo
4fc37a7321 -Added toggle to allow main video player to switch to popup player when onstop is called.
-Fixed player state not recovering when player is stopped during multiwindow mode.
-Updated gradle to 3.1.2.
2018-06-03 13:20:39 -07:00
Christian Schabesberger
2a45a13f73 move on to version v0.13.5 2018-06-03 12:36:35 +02:00
Christian Schabesberger
067b15c300 Merge branch 'dev' of https://github.com/DafabHoid/NewPipe into test 2018-06-03 12:20:43 +02:00
Christian Schabesberger
8a1c283542 Merge branch 'media-session-fix' of https://github.com/karyogamy/NewPipe into test 2018-06-03 12:12:54 +02:00
Christian Schabesberger
93d1e8b2ff Merge pull request #1441 from DafabHoid/fixdownloadercrashrelease
Downloader: Fix crash on loading unfinished downloads from .giga files (Fixup for release builds)
2018-06-03 12:08:20 +02:00
Christian Schabesberger
c60d5b54fa Merge branch 'remeber_brightness' of https://github.com/acrosca/NewPipe into test 2018-06-03 11:02:49 +02:00
Andrei.Rosca
ef180f082e Remember brightness for the session 2018-06-02 09:06:40 +02:00
Rex_sa
f52741cc37 Translated using Weblate (Arabic)
Currently translated at 100.0% (373 of 373 strings)
2018-06-02 07:34:24 +02:00
DafabHoid
2a2661f066 Downloader: Fix crash on loading unfinished downloads from .giga files
This is a fixup, which fixes the crash in release builds, too. It keeps proguard from removing the new method "private void readObject(ObjectInputStream)", which is only called by the VM, but not from the code.
2018-06-01 14:35:03 +02:00
Rex_sa
b521903138 Translated using Weblate (Arabic)
Currently translated at 100.0% (373 of 373 strings)
2018-06-01 07:02:51 +02:00
Ali Toor
acbd699d95 Translated using Weblate (Urdu)
Currently translated at 2.9% (11 of 373 strings)
2018-05-31 06:43:02 +02:00
Andrea Troiano
6b8928becb Translated using Weblate (Italiano)
Currently translated at 100,0% (373 of 373 strings)
2018-05-30 11:14:38 +02:00
Víctor Manuel Tapia Ramírez
e393bdb1e5 Translated using Weblate (Spanish)
Currently translated at 99.7% (372 of 373 strings)
2018-05-30 10:43:28 +02:00
Osoitz
bba6b96765 Translated using Weblate (Basque)
Currently translated at 100.0% (373 of 373 strings)
2018-05-29 16:58:04 +02:00
John Zhen Mo
740116356c -Fixed media session activation.
-Removed redundant setShuffle call in media session callback and its user.
-Removed unused dummy playback preparer.
2018-05-28 20:02:02 -07:00
monolifed
2f6e4fa4a3 Translated using Weblate (Turkish)
Currently translated at 100.0% (373 of 373 strings)
2018-05-28 20:44:52 +02:00
Allan Nordhøy
fb3f6721b2 Translated using Weblate (Norwegian Bokmål)
Currently translated at 95.9% (358 of 373 strings)
2018-05-28 17:41:18 +02:00
AB
4e7bd21e5c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (373 of 373 strings)
2018-05-28 17:07:13 +02:00
Jeff Huang
219c2030b9 Translated using Weblate (漢語(正體字))
Currently translated at 100.0% (373 of 373 strings)
2018-05-28 08:56:18 +02:00
Marc Riera
b75fdb4566 Translated using Weblate (català)
Currently translated at 100,0% (373 of 373 strings)
2018-05-28 08:41:52 +02:00
Nathan Follens
4584b14a31 Translated using Weblate (Vlaams)
Currently translated at 100,0% (373 of 373 strings)
2018-05-28 07:53:32 +02:00
thami simo
814ddb5932 Translated using Weblate (Arabic)
Currently translated at 100.0% (373 of 373 strings)
2018-05-28 07:45:58 +02:00
DafabHoid
6ea0f6290a Downloader: Notify the progress every 64K instead of every 512 Bytes
This improves downloading performance dramatically when cpu bound:
Before, even a high-end cpu from 2013 can't download faster than around 1MB/s.
The bigger read buffer size removes the need for a dedicated BufferedInputStream.
2018-05-28 01:07:30 +02:00
monolifed
c796fe1fe6 Translated using Weblate (Turkish)
Currently translated at 100.0% (373 of 373 strings)
2018-05-27 19:49:08 +02:00
Heimen Stoffels
a452a164e6 Translated using Weblate (Dutch)
Currently translated at 100.0% (373 of 373 strings)
2018-05-27 18:00:16 +02:00
ssantos
0d9dd69b19 Translated using Weblate (Deutsch)
Currently translated at 100,0% (373 of 373 strings)
2018-05-27 17:51:41 +02:00
Eduardo Caron
d7b73c18f1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (373 of 373 strings)
2018-05-27 15:14:19 +02:00
Weblate
07f66c0e45 Merge branch 'dev' into weblate-merge-tmp 2018-05-27 15:11:40 +02:00
monolifed
d449acbf86 Translated using Weblate (Turkish)
Currently translated at 99.4% (369 of 371 strings)
2018-05-27 15:11:40 +02:00
Allan Nordhøy
fce416ba76 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.2% (357 of 371 strings)
2018-05-27 15:11:35 +02:00
dadosch
cb6bfe8556 Translated using Weblate (German)
Currently translated at 100.0% (371 of 371 strings)
2018-05-27 15:11:35 +02:00
Florian
d7b31e1d25 Translated using Weblate (French)
Currently translated at 98.6% (366 of 371 strings)
2018-05-27 15:11:34 +02:00
Eduardo Caron
85057376d6 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (371 of 371 strings)
2018-05-27 15:11:31 +02:00
Christian Schabesberger
c43ac7c869 fix conflict 2018-05-27 13:30:23 +02:00
Heimen Stoffels
b2657315f1 Translated using Weblate (Dutch)
Currently translated at 100.0% (371 of 371 strings)
2018-05-27 12:36:08 +02:00
ezjerry liao
de5ed9717c Translated using Weblate (漢語(正體字))
Currently translated at 100.0% (371 of 371 strings)
2018-05-27 01:18:13 +02:00
Ali Demirtas
e17a6cbb9f Translated using Weblate (Turkish)
Currently translated at 100.0% (371 of 371 strings)
2018-05-27 00:07:08 +02:00
Marc Riera
8e783b774b Translated using Weblate (català)
Currently translated at 100,0% (371 of 371 strings)
2018-05-27 00:03:34 +02:00
AB
733663f40d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (371 of 371 strings)
2018-05-26 22:34:26 +02:00
Ali Demirtas
4b2a792a62 Translated using Weblate (Türkçe)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 21:01:30 +02:00
dadosch
f7aa171d01 Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)

informal "du"
2018-05-26 15:14:27 +02:00
dadosch
5eafefb683 Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 15:12:02 +02:00
dadosch
5d1b02a856 Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)

informal "du"
2018-05-26 15:08:29 +02:00
dadosch
4acda3d9ae Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 15:07:50 +02:00
dadosch
643e10ace2 Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)

informal "du"
2018-05-26 15:04:45 +02:00
dadosch
7b64a232de Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 15:00:23 +02:00
dadosch
d7472d837d Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)

informal "du"
2018-05-26 14:57:32 +02:00
dadosch
94b473ab4b Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 14:56:36 +02:00
dadosch
4a05bbb6c8 Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 14:45:26 +02:00
Linux User
0343659b35 Translated using Weblate (Deutsch)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 14:45:21 +02:00
Nathan Follens
f38eadbe30 Translated using Weblate (Vlaams)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 09:32:42 +02:00
Nathan Follens
eb29a53ac5 Translated using Weblate (Nederlands)
Currently translated at 100,0% (371 of 371 strings)
2018-05-26 09:29:31 +02:00
Weblate
bc71e260e2 Merge branch 'dev' into weblate-merge-tmp 2018-05-26 08:38:30 +02:00
Bogdan Khomutsky
ddf23a3443 Translated using Weblate (Russian)
Currently translated at 100.0% (365 of 365 strings)
2018-05-26 08:38:30 +02:00
Dual Natan
d41b248d1c Translated using Weblate (Macedonian)
Currently translated at 100.0% (365 of 365 strings)
2018-05-26 08:38:29 +02:00
SN
a025b25933 Translated using Weblate (Hindi)
Currently translated at 83.0% (303 of 365 strings)
2018-05-26 08:38:28 +02:00
Charlotte Lewer
c9a52a6088 Translated using Weblate (Esperanto)
Currently translated at 25.2% (92 of 365 strings)
2018-05-26 08:38:28 +02:00
My Account
0276dca406 Translated using Weblate (Hindi)
Currently translated at 83.0% (303 of 365 strings)
2018-05-26 08:38:22 +02:00
James Straub
646fa877ba Update to mobile data limiting
- Moved non-key strings from string_keys.xml to strings.xml
- Code style changes
- Replaced a hard coded key string with resource constant
2018-04-22 10:20:19 -04:00
James Straub
d1b0cd74be Added the ability to limit video quality if using mobile data.
* Added a dropdown to video & audio settings
* Changes to ListHelper:
** Limits resolution when code requests the default video resolution
** Limits audio bitrate when code requests the default audio bitrate
** Removed some dead code and did some cleanup
** Make methods private/protected to help understand what was in use
** The code now chooses one format over an other using a simple raking system defined in array constants. I realized I needed to do this in order to choose the most efficient video stream. I did my best to evaluate the video and audio formats based on quality and efficiency. It's not an exact science.
** Made changes to the tests to support my changes
2018-04-21 12:35:04 -04:00
97 changed files with 4204 additions and 1532 deletions

View File

@@ -15,6 +15,8 @@ Do not report crashes in the GitHub issue tracker. NewPipe has an automated cras
* 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.
* 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.
* Issues that only contain a generated bug report, but no describtion might be closed.
## 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.

View File

@@ -1,2 +1,3 @@
- [ ] I carefully read the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md) and agree to them.
- [ ] I checked if the issue/feature exists in the latest version.
- [ ] I did use the [incredible bugreport to markdown converter](https://teamnewpipe.github.io/CrashReportToMarkdown/) to paste bug reports.

View File

@@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 27
versionCode 63
versionName "0.13.4"
versionCode 66
versionName "0.13.7"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
@@ -42,10 +42,10 @@ android {
ext {
supportLibVersion = '27.1.1'
exoPlayerLibVersion = '2.7.3'
roomDbLibVersion = '1.0.0'
exoPlayerLibVersion = '2.8.2'
roomDbLibVersion = '1.1.1'
leakCanaryLibVersion = '1.5.4'
okHttpLibVersion = '1.5.0'
okHttpLibVersion = '3.10.0'
icepickLibVersion = '3.2.0'
stethoLibVersion = '1.5.0'
}
@@ -54,10 +54,10 @@ dependencies {
exclude module: 'support-annotations'
}
implementation 'com.github.TeamNewPipe:NewPipeExtractor:bf1c771'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:1eff8c5708'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:1.10.19'
testImplementation 'org.mockito:mockito-core:2.8.9'
implementation "com.android.support:appcompat-v7:$supportLibVersion"
implementation "com.android.support:support-v4:$supportLibVersion"
@@ -79,7 +79,7 @@ dependencies {
debugImplementation "com.facebook.stetho:stetho-urlconnection:$stethoLibVersion"
debugImplementation 'com.android.support:multidex:1.0.3'
implementation 'io.reactivex.rxjava2:rxjava:2.1.10'
implementation 'io.reactivex.rxjava2:rxjava:2.1.14'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
@@ -93,6 +93,6 @@ dependencies {
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryLibVersion"
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryLibVersion"
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
debugImplementation "com.facebook.stetho:stetho-okhttp3:$okHttpLibVersion"
implementation "com.squareup.okhttp3:okhttp:$okHttpLibVersion"
debugImplementation "com.facebook.stetho:stetho-okhttp3:$stethoLibVersion"
}

View File

@@ -42,3 +42,9 @@
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
}

View File

@@ -61,6 +61,8 @@ import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.extractor.InfoItem.InfoType.PLAYLIST;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
@@ -106,7 +108,19 @@ public class MainActivity extends AppCompatActivity {
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerClosed(View view) { super.onDrawerClosed(view); }
@Override
public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); }
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, 0);
}
};
toggle.syncState();
drawer.addDrawerListener(toggle);
drawer.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
@@ -133,13 +147,11 @@ public class MainActivity extends AppCompatActivity {
private boolean changeService(MenuItem item) {
if (item.getGroupId() == R.id.menu_services_group) {
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(false);
ServiceHelper.setSelectedServiceId(this, item.getItemId());
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
} else {
if (item.getGroupId() != R.id.menu_services_group)
return false;
}
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(false);
ServiceHelper.setSelectedServiceId(this, item.getItemId());
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
drawer.closeDrawers();
return true;
}
@@ -382,31 +394,45 @@ public class MainActivity extends AppCompatActivity {
}
private void handleIntent(Intent intent) {
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
try {
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
String url = intent.getStringExtra(Constants.KEY_URL);
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
String title = intent.getStringExtra(Constants.KEY_TITLE);
switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
case STREAM:
boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
break;
case CHANNEL:
NavigationHelper.openChannelFragment(getSupportFragmentManager(), serviceId, url, title);
break;
case PLAYLIST:
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(), serviceId, url, title);
break;
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
String url = intent.getStringExtra(Constants.KEY_URL);
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
String title = intent.getStringExtra(Constants.KEY_TITLE);
switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
case STREAM:
boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
break;
case CHANNEL:
NavigationHelper.openChannelFragment(getSupportFragmentManager(),
serviceId,
url,
title);
break;
case PLAYLIST:
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(),
serviceId,
url,
title);
break;
}
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
String searchString = intent.getStringExtra(Constants.KEY_SEARCH_STRING);
if (searchString == null) searchString = "";
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
NavigationHelper.openSearchFragment(
getSupportFragmentManager(),
serviceId,
searchString);
} else {
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
}
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
String searchQuery = intent.getStringExtra(Constants.KEY_QUERY);
if (searchQuery == null) searchQuery = "";
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
NavigationHelper.openSearchFragment(getSupportFragmentManager(), serviceId, searchQuery);
} else {
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
} catch (Exception e) {
ErrorActivity.reportUiError(this, e);
}
}
}

View File

@@ -1,14 +1,19 @@
package org.schabi.newpipe;
import android.annotation.SuppressLint;
import android.app.FragmentManager;
import android.app.IntentService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
@@ -23,6 +28,7 @@ import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
@@ -31,6 +37,8 @@ import org.schabi.newpipe.extractor.channel.ChannelInfo;
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.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueue;
@@ -38,16 +46,19 @@ 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.ExtractorHelper;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Observer;
import icepick.Icepick;
import icepick.State;
@@ -77,6 +88,8 @@ public class RouterActivity extends AppCompatActivity {
protected String currentUrl;
protected CompositeDisposable disposables = new CompositeDisposable();
private boolean selectionIsDownload = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -104,7 +117,7 @@ public class RouterActivity extends AppCompatActivity {
@Override
protected void onStart() {
super.onStart();
handleUrl(currentUrl);
}
@@ -165,6 +178,7 @@ public class RouterActivity extends AppCompatActivity {
final String videoPlayerKey = getString(R.string.video_player_key);
final String backgroundPlayerKey = getString(R.string.background_player_key);
final String popupPlayerKey = getString(R.string.popup_player_key);
final String downloadKey = getString(R.string.download_key);
final String alwaysAskKey = getString(R.string.always_ask_open_action_key);
if (selectedChoiceKey.equals(alwaysAskKey)) {
@@ -179,6 +193,8 @@ public class RouterActivity extends AppCompatActivity {
}
} else if (selectedChoiceKey.equals(showInfoKey)) {
handleChoice(showInfoKey);
} else if (selectedChoiceKey.equals(downloadKey)) {
handleChoice(downloadKey);
} else {
final boolean isExtVideoEnabled = preferences.getBoolean(getString(R.string.use_external_video_player_key), false);
final boolean isExtAudioEnabled = preferences.getBoolean(getString(R.string.use_external_audio_player_key), false);
@@ -236,7 +252,9 @@ public class RouterActivity extends AppCompatActivity {
.setCancelable(true)
.setNegativeButton(R.string.just_once, dialogButtonsClickListener)
.setPositiveButton(R.string.always, dialogButtonsClickListener)
.setOnDismissListener((dialog) -> finish())
.setOnDismissListener((dialog) -> {
if(!selectionIsDownload) finish();
})
.create();
//noinspection CodeBlock2Expr
@@ -316,6 +334,9 @@ public class RouterActivity extends AppCompatActivity {
resolveResourceIdFromAttr(context, R.attr.audio)));
}
returnList.add(new AdapterChoiceItem(getString(R.string.download_key), getString(R.string.download),
resolveResourceIdFromAttr(context, R.attr.download)));
return returnList;
}
@@ -347,6 +368,14 @@ public class RouterActivity extends AppCompatActivity {
return;
}
if (selectedChoiceKey.equals(getString(R.string.download_key))) {
if (PermissionHelper.checkStoragePermissions(this, PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) {
selectionIsDownload = true;
openDownloadDialog();
}
return;
}
// stop and bypass FetcherService if InfoScreen was selected since
// StreamDetailFragment can fetch data itself
if (selectedChoiceKey.equals(getString(R.string.show_info_key))) {
@@ -373,6 +402,47 @@ public class RouterActivity extends AppCompatActivity {
finish();
}
@SuppressLint("CheckResult")
private void openDownloadDialog() {
ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, true)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((@NonNull StreamInfo result) -> {
List<VideoStream> sortedVideoStreams = ListHelper.getSortedStreamVideosList(this,
result.getVideoStreams(),
result.getVideoOnlyStreams(),
false);
int selectedVideoStreamIndex = ListHelper.getDefaultResolutionIndex(this,
sortedVideoStreams);
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
DownloadDialog downloadDialog = DownloadDialog.newInstance(result);
downloadDialog.setVideoStreams(sortedVideoStreams);
downloadDialog.setAudioStreams(result.getAudioStreams());
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
downloadDialog.show(fm, "downloadDialog");
fm.executePendingTransactions();
downloadDialog.getDialog().setOnDismissListener(dialog -> {
finish();
});
}, (@NonNull Throwable throwable) -> {
onError();
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
for (int i: grantResults){
if (i == PackageManager.PERMISSION_DENIED){
finish();
return;
}
}
if (requestCode == PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE) {
openDownloadDialog();
}
}
private static class AdapterChoiceItem {
final String description, key;
@DrawableRes final int icon;

View File

@@ -71,6 +71,14 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
info.getUploaderName(), info.getStreamCount());
}
@Ignore
public boolean isIdenticalTo(final PlaylistInfo info) {
return getServiceId() == info.getServiceId() && getName().equals(info.getName()) &&
getStreamCount() == info.getStreamCount() && getUrl().equals(info.getUrl()) &&
getThumbnailUrl().equals(info.getThumbnailUrl()) &&
getUploader().equals(info.getUploaderName());
}
public long getUid() {
return uid;
}

View File

@@ -0,0 +1,158 @@
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;
}
}
}
}

View File

@@ -15,12 +15,17 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.settings.SettingsActivity;
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.ui.fragment.AllMissionsFragment;
import us.shandian.giga.ui.fragment.MissionsFragment;
public class DownloadActivity extends AppCompatActivity {
private static final String MISSIONS_FRAGMENT_TAG = "fragment_tag";
private DeleteDownloadManager mDeleteDownloadManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
// Service
@@ -42,21 +47,35 @@ public class DownloadActivity extends AppCompatActivity {
actionBar.setDisplayShowTitleEnabled(true);
}
// Fragment
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
updateFragments();
getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
mDeleteDownloadManager = new DeleteDownloadManager(this);
mDeleteDownloadManager.restoreState(savedInstanceState);
MissionsFragment fragment = (MissionsFragment) getFragmentManager().findFragmentByTag(MISSIONS_FRAGMENT_TAG);
if (fragment != null) {
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() {
MissionsFragment fragment = new AllMissionsFragment();
fragment.setDeleteManager(mDeleteDownloadManager);
getFragmentManager().beginTransaction()
.replace(R.id.frame, fragment)
.replace(R.id.frame, fragment, MISSIONS_FRAGMENT_TAG)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
}
@@ -80,6 +99,7 @@ public class DownloadActivity extends AppCompatActivity {
case R.id.action_settings: {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
deletePending();
return true;
}
default:
@@ -87,4 +107,15 @@ public class DownloadActivity extends AppCompatActivity {
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
deletePending();
}
private void deletePending() {
Completable.fromAction(mDeleteDownloadManager::deletePending)
.subscribeOn(Schedulers.io())
.subscribe();
}
}

View File

@@ -10,6 +10,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
@@ -127,7 +128,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search:
NavigationHelper.openSearchFragment(getFragmentManager(), ServiceHelper.getSelectedServiceId(activity), "");
try {
NavigationHelper.openSearchFragment(
getFragmentManager(),
ServiceHelper.getSelectedServiceId(activity),
"");
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
return true;
}
return super.onOptionsItemSelected(item);
@@ -226,7 +234,9 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
FALLBACK_CHANNEL_URL);
String name = preferences.getString(getString(R.string.main_page_selected_channel_name),
FALLBACK_CHANNEL_NAME);
ChannelFragment fragment = ChannelFragment.getInstance(serviceId, url, name);
ChannelFragment fragment = ChannelFragment.getInstance(serviceId,
url,
name);
fragment.useAsFrontPage(true);
return fragment;
} else {
@@ -255,20 +265,13 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
for (final String ks : kl.getAvailableKiosks()) {
menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE,
KioskTranslator.getTranslatedKioskName(ks, getContext()))
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
.setOnMenuItemClickListener(menuItem -> {
try {
NavigationHelper.openKioskFragment(getFragmentManager(), currentServiceId, ks);
} catch (Exception e) {
ErrorActivity.reportError(activity, e,
activity.getClass(),
null,
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
"none", "", R.string.app_ui_crash));
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
return true;
}
});
i++;
}

View File

@@ -17,6 +17,7 @@ import android.support.v4.content.ContextCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
@@ -54,14 +55,17 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
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.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;
@@ -128,7 +132,7 @@ public class VideoDetailFragment
private StreamInfo currentInfo;
private Disposable currentWorker;
private CompositeDisposable disposables = new CompositeDisposable();
@NonNull private CompositeDisposable disposables = new CompositeDisposable();
private List<VideoStream> sortedVideoStreams;
private int selectedVideoStreamIndex = -1;
@@ -363,11 +367,15 @@ public class VideoDetailFragment
if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
Log.w(TAG, "Can't open channel because we got no channel URL");
} else {
NavigationHelper.openChannelFragment(
getFragmentManager(),
currentInfo.getServiceId(),
currentInfo.getUploaderUrl(),
currentInfo.getUploaderName());
try {
NavigationHelper.openChannelFragment(
getFragmentManager(),
currentInfo.getServiceId(),
currentInfo.getUploaderUrl(),
currentInfo.getUploaderName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
break;
case R.id.detail_thumbnail_root_layout:
@@ -540,7 +548,8 @@ public class VideoDetailFragment
final String[] commands = new String[]{
context.getResources().getString(R.string.enqueue_on_background),
context.getResources().getString(R.string.enqueue_on_popup),
context.getResources().getString(R.string.append_playlist)
context.getResources().getString(R.string.append_playlist),
context.getResources().getString(R.string.share)
};
final DialogInterface.OnClickListener actions = (DialogInterface dialogInterface, int i) -> {
@@ -557,6 +566,9 @@ public class VideoDetailFragment
.show(getFragmentManager(), TAG);
}
break;
case 3:
shareUrl(item.getName(), item.getUrl());
break;
default:
break;
}
@@ -872,10 +884,7 @@ public class VideoDetailFragment
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
openNormalBackgroundPlayer(append);
} else {
NavigationHelper.playOnExternalPlayer(activity,
currentInfo.getName(),
currentInfo.getUploaderName(),
audioStream);
startOnExternalPlayer(activity, currentInfo, audioStream);
}
}
@@ -902,10 +911,7 @@ public class VideoDetailFragment
if (PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
NavigationHelper.playOnExternalPlayer(activity,
currentInfo.getName(),
currentInfo.getUploaderName(),
selectedVideoStream);
startOnExternalPlayer(activity, currentInfo, selectedVideoStream);
} else {
openNormalPlayer(selectedVideoStream);
}
@@ -949,6 +955,20 @@ public class VideoDetailFragment
this.autoPlayEnabled = autoplay;
}
private void startOnExternalPlayer(@NonNull final Context context,
@NonNull final StreamInfo info,
@NonNull final Stream selectedStream) {
NavigationHelper.playOnExternalPlayer(context, currentInfo.getName(),
currentInfo.getUploaderName(), selectedStream);
final HistoryRecordManager recordManager = new HistoryRecordManager(requireContext());
disposables.add(recordManager.onViewed(info).onErrorComplete()
.subscribe(
ignored -> {/* successful */},
error -> Log.e(TAG, "Register view failure: ", error)
));
}
@Nullable
private VideoStream getSelectedVideoStream() {
return sortedVideoStreams != null ? sortedVideoStreams.get(selectedVideoStreamIndex) : null;

View File

@@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@@ -24,6 +25,7 @@ import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.info_list.InfoListAdapter;
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.StateSaver;
@@ -152,18 +154,35 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
@Override
public void selected(ChannelInfoItem selectedItem) {
onItemSelected(selectedItem);
NavigationHelper.openChannelFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
try {
onItemSelected(selectedItem);
NavigationHelper.openChannelFragment(useAsFrontPage ?
getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
});
infoListAdapter.setOnPlaylistSelectedListener(new OnClickGesture<PlaylistInfoItem>() {
@Override
public void selected(PlaylistInfoItem selectedItem) {
onItemSelected(selectedItem);
NavigationHelper.openPlaylistFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
try {
onItemSelected(selectedItem);
NavigationHelper.openPlaylistFragment(
useAsFrontPage
? getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
});
@@ -178,7 +197,9 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
private void onStreamSelected(StreamInfoItem selectedItem) {
onItemSelected(selectedItem);
NavigationHelper.openVideoDetailFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
NavigationHelper.openVideoDetailFragment(useAsFrontPage
? getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
}
@@ -196,7 +217,8 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
final String[] commands = new String[]{
context.getResources().getString(R.string.enqueue_on_background),
context.getResources().getString(R.string.enqueue_on_popup),
context.getResources().getString(R.string.append_playlist)
context.getResources().getString(R.string.append_playlist),
context.getResources().getString(R.string.share)
};
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
@@ -213,6 +235,9 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
.show(getFragmentManager(), TAG);
}
break;
case 3:
shareUrl(item.getName(), item.getUrl());
break;
default:
break;
}

View File

@@ -8,6 +8,9 @@ import android.view.View;
import org.schabi.newpipe.extractor.ListExtractor;
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 java.util.Queue;
@@ -166,7 +169,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
public void handleResult(@NonNull I result) {
super.handleResult(result);
url = result.getUrl();
name = result.getName();
setTitle(name);

View File

@@ -33,6 +33,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
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.info_list.InfoItemDialog;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@@ -161,7 +162,8 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
context.getResources().getString(R.string.start_here_on_main),
context.getResources().getString(R.string.start_here_on_background),
context.getResources().getString(R.string.start_here_on_popup),
context.getResources().getString(R.string.append_playlist)
context.getResources().getString(R.string.append_playlist),
context.getResources().getString(R.string.share)
};
final DialogInterface.OnClickListener actions = new DialogInterface.OnClickListener() {
@@ -190,6 +192,9 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
.show(getFragmentManager(), TAG);
}
break;
case 6:
shareUrl(item.getName(), item.getUrl());
break;
default:
break;
}
@@ -497,7 +502,11 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.REQUESTED_CHANNEL, NewPipe.getNameOfService(serviceId), url, errorId);
onUnrecoverableError(exception,
UserAction.REQUESTED_CHANNEL,
NewPipe.getNameOfService(serviceId),
url,
errorId);
return true;
}

View File

@@ -11,22 +11,20 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
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.info_list.InfoItemBuilder;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.NavigationHelper;
import icepick.State;
import io.reactivex.Single;
@@ -74,10 +72,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
throws ExtractionException {
KioskFragment instance = new KioskFragment();
StreamingService service = NewPipe.getService(serviceId);
UrlIdHandler kioskTypeUrlIdHandler = service.getKioskList()
.getUrlIdHandlerByType(kioskId);
ListLinkHandlerFactory kioskLinkHandlerFactory = service.getKioskList()
.getListLinkHandlerFactoryByType(kioskId);
instance.setInitialData(serviceId,
kioskTypeUrlIdHandler.getUrl(kioskId), kioskId);
kioskLinkHandlerFactory.fromId(kioskId).getUrl(), kioskId);
instance.kioskId = kioskId;
return instance;
}
@@ -136,7 +134,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
.getDefaultSharedPreferences(activity)
.getString(getString(R.string.content_country_key),
getString(R.string.default_country_value));
return ExtractorHelper.getKioskInfo(serviceId, url, contentCountry, forceReload);
return ExtractorHelper.getKioskInfo(serviceId,
url,
contentCountry,
forceReload);
}
@Override
@@ -145,7 +146,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
.getDefaultSharedPreferences(activity)
.getString(getString(R.string.content_country_key),
getString(R.string.default_country_value));
return ExtractorHelper.getMoreKioskItems(serviceId, url, currentNextPageUrl, contentCountry);
return ExtractorHelper.getMoreKioskItems(serviceId,
url,
currentNextPageUrl,
contentCountry);
}
/*//////////////////////////////////////////////////////////////////////////

View File

@@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -19,6 +20,7 @@ import android.widget.TextView;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.schabi.newpipe.App;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
@@ -28,12 +30,14 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
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.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
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.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
@@ -44,6 +48,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
@@ -93,7 +98,8 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
super.onCreate(savedInstanceState);
disposables = new CompositeDisposable();
isBookmarkButtonReady = new AtomicBoolean(false);
remotePlaylistManager = new RemotePlaylistManager(NewPipeDatabase.getInstance(getContext()));
remotePlaylistManager = new RemotePlaylistManager(NewPipeDatabase.getInstance(
requireContext()));
}
@Override
@@ -142,6 +148,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
context.getResources().getString(R.string.start_here_on_main),
context.getResources().getString(R.string.start_here_on_background),
context.getResources().getString(R.string.start_here_on_popup),
context.getResources().getString(R.string.share)
};
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
@@ -162,6 +169,9 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
case 4:
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
break;
case 5:
shareUrl(item.getName(), item.getUrl());
break;
default:
break;
}
@@ -261,11 +271,16 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
if (!TextUtils.isEmpty(result.getUploaderName())) {
headerUploaderName.setText(result.getUploaderName());
if (!TextUtils.isEmpty(result.getUploaderUrl())) {
headerUploaderLayout.setOnClickListener(v ->
headerUploaderLayout.setOnClickListener(v -> {
try {
NavigationHelper.openChannelFragment(getFragmentManager(),
result.getServiceId(), result.getUploaderUrl(),
result.getUploaderName())
);
result.getServiceId(),
result.getUploaderUrl(),
result.getUploaderName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
});
}
}
@@ -281,14 +296,11 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
}
remotePlaylistManager.getPlaylist(result)
.flatMap(lists -> getUpdateProcessor(lists, result), (lists, id) -> lists)
.onBackpressureLatest()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getPlaylistBookmarkSubscriber());
remotePlaylistManager.onUpdate(result)
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(integer -> {/* Do nothing*/}, this::onError);
headerPlayAllButton.setOnClickListener(view ->
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
headerPopupButton.setOnClickListener(view ->
@@ -336,7 +348,11 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId), url, errorId);
onUnrecoverableError(exception,
UserAction.REQUESTED_PLAYLIST,
NewPipe.getNameOfService(serviceId),
url,
errorId);
return true;
}
@@ -344,6 +360,17 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
// Utils
//////////////////////////////////////////////////////////////////////////*/
private Flowable<Integer> getUpdateProcessor(@NonNull List<PlaylistRemoteEntity> playlists,
@NonNull PlaylistInfo result) {
final Flowable<Integer> noItemToUpdate = Flowable.just(/*noItemToUpdate=*/-1);
if (playlists.isEmpty()) return noItemToUpdate;
final PlaylistRemoteEntity playlistEntity = playlists.get(0);
if (playlistEntity.isIdenticalTo(result)) return noItemToUpdate;
return remotePlaylistManager.onUpdate(playlists.get(0).getUid(), result).toFlowable();
}
private Subscriber<List<PlaylistRemoteEntity>> getPlaylistBookmarkSubscriber() {
return new Subscriber<List<PlaylistRemoteEntity>>() {
@Override
@@ -416,4 +443,4 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
playlistBookmarkButton.setIcon(ThemeHelper.resolveResourceIdFromAttr(activity, iconAttr));
playlistBookmarkButton.setTitle(titleRes);
}
}
}

View File

@@ -6,6 +6,7 @@ import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -19,9 +20,11 @@ import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
@@ -99,19 +102,26 @@ public final class BookmarkFragment
itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
@Override
public void selected(LocalItem selectedItem) {
// Requires the parent fragment to find holder for fragment replacement
if (getParentFragment() == null) return;
final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
try {
// Requires the parent fragment to find holder for fragment replacement
if (getParentFragment() == null) return;
final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
if (selectedItem instanceof PlaylistMetadataEntry) {
final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
entry.name);
if (selectedItem instanceof PlaylistMetadataEntry) {
final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
entry.name);
} else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
NavigationHelper.openPlaylistFragment(fragmentManager, entry.getServiceId(),
entry.getUrl(), entry.getName());
} else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
NavigationHelper.openPlaylistFragment(
fragmentManager,
entry.getServiceId(),
entry.getUrl(),
entry.getName());
}
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}

View File

@@ -298,6 +298,7 @@ public class StatisticsPlaylistFragment
context.getResources().getString(R.string.start_here_on_background),
context.getResources().getString(R.string.start_here_on_popup),
context.getResources().getString(R.string.delete),
context.getResources().getString(R.string.share)
};
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
@@ -321,6 +322,9 @@ public class StatisticsPlaylistFragment
case 5:
deleteEntry(index);
break;
case 6:
shareUrl(item.toStreamInfoItem().getName(), item.toStreamInfoItem().getUrl());
break;
default:
break;
}

View File

@@ -520,7 +520,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
context.getResources().getString(R.string.start_here_on_background),
context.getResources().getString(R.string.start_here_on_popup),
context.getResources().getString(R.string.set_as_playlist_thumbnail),
context.getResources().getString(R.string.delete)
context.getResources().getString(R.string.delete),
context.getResources().getString(R.string.share)
};
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
@@ -549,6 +550,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
case 6:
deleteItem(item);
break;
case 7:
shareUrl(item.toStreamInfoItem().getName(), item.toStreamInfoItem().getUrl());
break;
default:
break;
}

View File

@@ -40,8 +40,11 @@ public class RemotePlaylistManager {
}).subscribeOn(Schedulers.io());
}
public Single<Integer> onUpdate(final PlaylistInfo playlistInfo) {
return Single.fromCallable(() -> playlistRemoteTable.update(new PlaylistRemoteEntity(playlistInfo)))
.subscribeOn(Schedulers.io());
public Single<Integer> onUpdate(final long playlistId, final PlaylistInfo playlistInfo) {
return Single.fromCallable(() -> {
PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo);
playlist.setUid(playlistId);
return playlistRemoteTable.update(playlist);
}).subscribeOn(Schedulers.io());
}
}

View File

@@ -15,6 +15,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -38,6 +39,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService;
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
@@ -318,9 +320,15 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
@Override
public void selected(ChannelInfoItem selectedItem) {
// Requires the parent fragment to find holder for fragment replacement
NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
try {
// Requires the parent fragment to find holder for fragment replacement
NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
});

View File

@@ -26,9 +26,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
@@ -39,17 +37,16 @@ import android.widget.RemoteViews;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.MediaSource;
import com.nostra13.universalimageloader.core.assist.FailReason;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.helper.LockManager;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.player.resolver.AudioPlaybackResolver;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper;
@@ -94,7 +91,6 @@ public final class BackgroundPlayer extends Service {
private NotificationCompat.Builder notBuilder;
private RemoteViews notRemoteView;
private RemoteViews bigNotRemoteView;
private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha";
private boolean shouldUpdateOnProgress;
@@ -192,7 +188,9 @@ public final class BackgroundPlayer extends Service {
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setCustomContentView(notRemoteView)
.setCustomBigContentView(bigNotRemoteView);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) builder.setPriority(NotificationCompat.PRIORITY_MAX);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(NotificationCompat.PRIORITY_MAX);
}
return builder;
}
@@ -249,15 +247,6 @@ public final class BackgroundPlayer extends Service {
notificationManager.notify(NOTIFICATION_ID, notBuilder.build());
}
private void setControlsOpacity(@IntRange(from = 0, to = 255) int opacity) {
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationPlayPause, setAlphaMethodName, opacity);
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationPlayPause, setAlphaMethodName, opacity);
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationFForward, setAlphaMethodName, opacity);
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationFForward, setAlphaMethodName, opacity);
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationFRewind, setAlphaMethodName, opacity);
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationFRewind, setAlphaMethodName, opacity);
}
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
@@ -279,8 +268,16 @@ public final class BackgroundPlayer extends Service {
protected class BasePlayerImpl extends BasePlayer {
@NonNull final private AudioPlaybackResolver resolver;
BasePlayerImpl(Context context) {
super(context);
this.resolver = new AudioPlaybackResolver(context, dataSource);
}
@Override
public void initPlayer(boolean playOnReady) {
super.initPlayer(playOnReady);
}
@Override
@@ -293,30 +290,41 @@ public final class BackgroundPlayer extends Service {
startForeground(NOTIFICATION_ID, notBuilder.build());
}
@Override
public void initThumbnail(final String url) {
resetNotification();
if (notRemoteView != null) notRemoteView.setImageViewResource(R.id.notificationCover, R.drawable.dummy_thumbnail);
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewResource(R.id.notificationCover, R.drawable.dummy_thumbnail);
updateNotification(-1);
super.initThumbnail(url);
/*//////////////////////////////////////////////////////////////////////////
// Thumbnail Loading
//////////////////////////////////////////////////////////////////////////*/
private void updateNotificationThumbnail() {
if (basePlayerImpl == null) return;
if (notRemoteView != null) {
notRemoteView.setImageViewBitmap(R.id.notificationCover,
basePlayerImpl.getThumbnail());
}
if (bigNotRemoteView != null) {
bigNotRemoteView.setImageViewBitmap(R.id.notificationCover,
basePlayerImpl.getThumbnail());
}
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
if (loadedImage != null) {
// rebuild notification here since remote view does not release bitmaps, causing memory leaks
resetNotification();
if (notRemoteView != null) notRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
updateNotification(-1);
}
resetNotification();
updateNotificationThumbnail();
updateNotification(-1);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
resetNotification();
updateNotificationThumbnail();
updateNotification(-1);
}
/*//////////////////////////////////////////////////////////////////////////
// States Implementation
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onPrepared(boolean playWhenReady) {
super.onPrepared(playWhenReady);
@@ -390,29 +398,18 @@ public final class BackgroundPlayer extends Service {
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) {
if (shouldUpdateOnProgress || hasPlayQueueItemChanged) {
resetNotification();
updateNotification(-1);
updateMetadata();
}
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
super.onMetadataChanged(tag);
resetNotification();
updateNotificationThumbnail();
updateNotification(-1);
updateMetadata();
}
@Override
@Nullable
public MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info) {
final MediaSource liveSource = super.sourceOf(item, info);
if (liveSource != null) return liveSource;
final int index = ListHelper.getDefaultAudioFormat(context, info.getAudioStreams());
if (index < 0 || index >= info.getAudioStreams().size()) return null;
final AudioStream audio = info.getAudioStreams().get(index);
return buildMediaSource(audio.getUrl(), PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()));
return resolver.resolve(info);
}
@Override
@@ -439,8 +436,8 @@ public final class BackgroundPlayer extends Service {
}
private void updateMetadata() {
if (activityListener != null && currentInfo != null) {
activityListener.onMetadataUpdate(currentInfo);
if (activityListener != null && getCurrentMetadata() != null) {
activityListener.onMetadataUpdate(getCurrentMetadata().getMetadata());
}
}
@@ -531,44 +528,36 @@ public final class BackgroundPlayer extends Service {
updatePlayback();
}
@Override
public void onBlocked() {
super.onBlocked();
setControlsOpacity(77);
updateNotification(-1);
}
@Override
public void onPlaying() {
super.onPlaying();
setControlsOpacity(255);
resetNotification();
updateNotificationThumbnail();
updateNotification(R.drawable.ic_pause_white);
lockManager.acquireWifiAndCpu();
}
@Override
public void onPaused() {
super.onPaused();
resetNotification();
updateNotificationThumbnail();
updateNotification(R.drawable.ic_play_arrow_white);
lockManager.releaseWifiAndCpu();
}
@Override
public void onCompleted() {
super.onCompleted();
setControlsOpacity(255);
resetNotification();
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
if (bigNotRemoteView != null) {
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
}
if (notRemoteView != null) {
notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
}
updateNotificationThumbnail();
updateNotification(R.drawable.ic_replay_white);
lockManager.releaseWifiAndCpu();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -58,7 +58,6 @@ import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SubtitleView;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
@@ -67,6 +66,8 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.playqueue.PlayQueueItemBuilder;
import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder;
import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
@@ -104,6 +105,7 @@ public final class MainVideoPlayer extends AppCompatActivity
@Nullable private PlayerState playerState;
private boolean isInMultiWindow;
private boolean isBackPressed;
/*//////////////////////////////////////////////////////////////////////////
// Activity LifeCycle
@@ -119,9 +121,13 @@ public final class MainVideoPlayer extends AppCompatActivity
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) getWindow().setStatusBarColor(Color.BLACK);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.screenBrightness = PlayerHelper.getScreenBrightness(getApplicationContext());
getWindow().setAttributes(lp);
hideSystemUi();
setContentView(R.layout.activity_main_player);
playerImpl = new VideoPlayerImpl(this);
playerImpl = new VideoPlayerImpl(this);
playerImpl.setup(findViewById(android.R.id.content));
if (savedInstanceState != null && savedInstanceState.get(KEY_SAVED_STATE) != null) {
@@ -148,7 +154,10 @@ public final class MainVideoPlayer extends AppCompatActivity
protected void onNewIntent(Intent intent) {
if (DEBUG) Log.d(TAG, "onNewIntent() called with: intent = [" + intent + "]");
super.onNewIntent(intent);
playerImpl.handleIntent(intent);
if (intent != null) {
playerState = null;
playerImpl.handleIntent(intent);
}
}
@Override
@@ -173,7 +182,7 @@ public final class MainVideoPlayer extends AppCompatActivity
playerImpl.setPlaybackQuality(playerState.getPlaybackQuality());
playerImpl.initPlayback(playerState.getPlayQueue(), playerState.getRepeatMode(),
playerState.getPlaybackSpeed(), playerState.getPlaybackPitch(),
playerState.wasPlaying());
playerState.isPlaybackSkipSilence(), playerState.wasPlaying());
}
}
@@ -187,6 +196,12 @@ public final class MainVideoPlayer extends AppCompatActivity
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
isBackPressed = true;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if (DEBUG) Log.d(TAG, "onSaveInstanceState() called");
@@ -196,7 +211,8 @@ public final class MainVideoPlayer extends AppCompatActivity
playerImpl.setRecovery();
playerState = new PlayerState(playerImpl.getPlayQueue(), playerImpl.getRepeatMode(),
playerImpl.getPlaybackSpeed(), playerImpl.getPlaybackPitch(),
playerImpl.getPlaybackQuality(), playerImpl.isPlaying());
playerImpl.getPlaybackQuality(), playerImpl.getPlaybackSkipSilence(),
playerImpl.isPlaying());
StateSaver.tryToSave(isChangingConfigurations(), null, outState, this);
}
@@ -204,7 +220,17 @@ public final class MainVideoPlayer extends AppCompatActivity
protected void onStop() {
if (DEBUG) Log.d(TAG, "onStop() called");
super.onStop();
PlayerHelper.setScreenBrightness(getApplicationContext(),
getWindow().getAttributes().screenBrightness);
if (playerImpl == null) return;
if (!isBackPressed) {
playerImpl.minimize();
}
playerImpl.destroy();
isInMultiWindow = false;
isBackPressed = false;
}
/*//////////////////////////////////////////////////////////////////////////
@@ -328,8 +354,11 @@ public final class MainVideoPlayer extends AppCompatActivity
////////////////////////////////////////////////////////////////////////////
@Override
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch) {
if (playerImpl != null) playerImpl.setPlaybackParameters(playbackTempo, playbackPitch);
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
boolean playbackSkipSilence) {
if (playerImpl != null) {
playerImpl.setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
}
}
///////////////////////////////////////////////////////////////////////////
@@ -434,6 +463,21 @@ public final class MainVideoPlayer extends AppCompatActivity
switchPopupButton.setOnClickListener(this);
}
public void minimize() {
switch (PlayerHelper.getMinimizeOnExitAction(context)) {
case PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND:
onPlayBackgroundButtonClicked();
break;
case PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP:
onFullScreenButtonClicked();
break;
case PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE:
default:
// No action
break;
}
}
/*//////////////////////////////////////////////////////////////////////////
// ExoPlayer Video Listener
//////////////////////////////////////////////////////////////////////////*/
@@ -454,14 +498,11 @@ public final class MainVideoPlayer extends AppCompatActivity
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) {
super.onMetadataChanged(item, info, newPlayQueueIndex, false);
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
super.onMetadataChanged(tag);
titleTextView.setText(getVideoTitle());
channelTextView.setText(getUploaderName());
titleTextView.setText(tag.getMetadata().getName());
channelTextView.setText(tag.getMetadata().getUploaderName());
}
@Override
@@ -494,6 +535,7 @@ public final class MainVideoPlayer extends AppCompatActivity
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
context.startService(intent);
@@ -515,6 +557,7 @@ public final class MainVideoPlayer extends AppCompatActivity
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
context.startService(intent);
@@ -610,7 +653,8 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void onPlaybackSpeedClicked() {
PlaybackParameterDialog.newInstance(getPlaybackSpeed(), getPlaybackPitch())
PlaybackParameterDialog
.newInstance(getPlaybackSpeed(), getPlaybackPitch(), getPlaybackSkipSilence())
.show(getSupportFragmentManager(), TAG);
}
@@ -640,14 +684,19 @@ public final class MainVideoPlayer extends AppCompatActivity
}
@Override
protected int getDefaultResolutionIndex(final List<VideoStream> sortedVideos) {
return ListHelper.getDefaultResolutionIndex(context, sortedVideos);
}
protected VideoPlaybackResolver.QualityResolver getQualityResolver() {
return new VideoPlaybackResolver.QualityResolver() {
@Override
public int getDefaultResolutionIndex(List<VideoStream> sortedVideos) {
return ListHelper.getDefaultResolutionIndex(context, sortedVideos);
}
@Override
protected int getOverrideResolutionIndex(final List<VideoStream> sortedVideos,
final String playbackQuality) {
return ListHelper.getDefaultResolutionIndex(context, sortedVideos, playbackQuality);
@Override
public int getOverrideResolutionIndex(List<VideoStream> sortedVideos,
String playbackQuality) {
return ListHelper.getResolutionIndex(context, sortedVideos, playbackQuality);
}
};
}
/*//////////////////////////////////////////////////////////////////////////
@@ -671,7 +720,6 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void onBuffering() {
super.onBuffering();
animatePlayButtons(false, 100);
getRootView().setKeepScreenOn(true);
}
@@ -847,7 +895,6 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public boolean onDoubleTap(MotionEvent e) {
if (DEBUG) Log.d(TAG, "onDoubleTap() called with: e = [" + e + "]" + "rawXy = " + e.getRawX() + ", " + e.getRawY() + ", xy = " + e.getX() + ", " + e.getY());
if (!playerImpl.isPlaying()) return false;
if (e.getX() > playerImpl.getRootView().getWidth() * 2 / 3) {
playerImpl.onFastForward();
@@ -884,7 +931,9 @@ public final class MainVideoPlayer extends AppCompatActivity
private final boolean isPlayerGestureEnabled = PlayerHelper.isPlayerGestureEnabled(getApplicationContext());
private final float stepsBrightness = 15, stepBrightness = (1f / stepsBrightness), minBrightness = .01f;
private float currentBrightness = .5f;
private float currentBrightness = getWindow().getAttributes().screenBrightness > 0
? getWindow().getAttributes().screenBrightness
: 0.5f;
private int currentVolume, maxVolume = playerImpl.getAudioReactor().getMaxVolume();
private final float stepsVolume = 15, stepVolume = (float) Math.ceil(maxVolume / stepsVolume), minVolume = 0;

View File

@@ -14,21 +14,26 @@ public class PlayerState implements Serializable {
private final float playbackSpeed;
private final float playbackPitch;
@Nullable private final String playbackQuality;
private final boolean playbackSkipSilence;
private final boolean wasPlaying;
PlayerState(@NonNull final PlayQueue playQueue, final int repeatMode,
final float playbackSpeed, final float playbackPitch, final boolean wasPlaying) {
this(playQueue, repeatMode, playbackSpeed, playbackPitch, null, wasPlaying);
final float playbackSpeed, final float playbackPitch,
final boolean playbackSkipSilence, final boolean wasPlaying) {
this(playQueue, repeatMode, playbackSpeed, playbackPitch, null,
playbackSkipSilence, wasPlaying);
}
PlayerState(@NonNull final PlayQueue playQueue, final int repeatMode,
final float playbackSpeed, final float playbackPitch,
@Nullable final String playbackQuality, final boolean wasPlaying) {
@Nullable final String playbackQuality, final boolean playbackSkipSilence,
final boolean wasPlaying) {
this.playQueue = playQueue;
this.repeatMode = repeatMode;
this.playbackSpeed = playbackSpeed;
this.playbackPitch = playbackPitch;
this.playbackQuality = playbackQuality;
this.playbackSkipSilence = playbackSkipSilence;
this.wasPlaying = wasPlaying;
}
@@ -62,6 +67,10 @@ public class PlayerState implements Serializable {
return playbackQuality;
}
public boolean isPlaybackSkipSilence() {
return playbackSkipSilence;
}
public boolean wasPlaying() {
return wasPlaying;
}

View File

@@ -187,6 +187,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
this.player.getRepeatMode(),
this.player.getPlaybackSpeed(),
this.player.getPlaybackPitch(),
this.player.getPlaybackSkipSilence(),
null
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
@@ -340,6 +341,13 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
return true;
});
final MenuItem share = menu.getMenu().add(RECYCLER_ITEM_POPUP_MENU_GROUP_ID, /*pos=*/3,
Menu.NONE, R.string.share);
share.setOnMenuItemClickListener(menuItem -> {
shareUrl(item.getTitle(), item.getUrl());
return true;
});
menu.show();
}
@@ -459,13 +467,16 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
private void openPlaybackParameterDialog() {
if (player == null) return;
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(),
player.getPlaybackPitch()).show(getSupportFragmentManager(), getTag());
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(), player.getPlaybackPitch(),
player.getPlaybackSkipSilence()).show(getSupportFragmentManager(), getTag());
}
@Override
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch) {
if (player != null) player.setPlaybackParameters(playbackTempo, playbackPitch);
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
boolean playbackSkipSilence) {
if (player != null) {
player.setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
}
}
////////////////////////////////////////////////////////////////////////////
@@ -509,6 +520,18 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
.show(getSupportFragmentManager(), getTag());
}
////////////////////////////////////////////////////////////////////////////
// Share
////////////////////////////////////////////////////////////////////////////
private 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)));
}
////////////////////////////////////////////////////////////////////////////
// Binding Service Listener
////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,6 @@ import android.view.KeyEvent;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
import org.schabi.newpipe.player.mediasession.DummyPlaybackPreparer;
import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
import org.schabi.newpipe.player.mediasession.PlayQueueNavigator;
import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController;
@@ -26,10 +25,12 @@ public class MediaSessionManager {
@NonNull final Player player,
@NonNull final MediaSessionCallback callback) {
this.mediaSession = new MediaSessionCompat(context, TAG);
this.mediaSession.setActive(true);
this.sessionConnector = new MediaSessionConnector(mediaSession,
new PlayQueuePlaybackController(callback));
this.sessionConnector.setQueueNavigator(new PlayQueueNavigator(mediaSession, callback));
this.sessionConnector.setPlayer(player, new DummyPlaybackPreparer());
this.sessionConnector.setPlayer(player, null);
}
@Nullable
@@ -37,4 +38,14 @@ public class MediaSessionManager {
public KeyEvent handleMediaButtonIntent(final Intent intent) {
return MediaButtonReceiver.handleIntent(mediaSession, intent);
}
/**
* Should be called on player destruction to prevent leakage.
* */
public void dispose() {
this.sessionConnector.setPlayer(null, null);
this.sessionConnector.setQueueNavigator(null);
this.mediaSession.setActive(false);
this.mediaSession.release();
}
}

View File

@@ -4,14 +4,15 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.accessibility.CaptioningManager;
import com.google.android.exoplayer2.SeekParameters;
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.text.CaptionStyleCompat;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes;
@@ -28,6 +29,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import java.lang.annotation.Retention;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
@@ -37,10 +39,13 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FILL;
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FIT;
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_ZOOM;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.*;
public class PlayerHelper {
private PlayerHelper() {}
@@ -50,6 +55,14 @@ public class PlayerHelper {
private static final NumberFormat speedFormatter = new DecimalFormat("0.##x");
private static final NumberFormat pitchFormatter = new DecimalFormat("##%");
@Retention(SOURCE)
@IntDef({MINIMIZE_ON_EXIT_MODE_NONE, MINIMIZE_ON_EXIT_MODE_BACKGROUND,
MINIMIZE_ON_EXIT_MODE_POPUP})
public @interface MinimizeMode {
int MINIMIZE_ON_EXIT_MODE_NONE = 0;
int MINIMIZE_ON_EXIT_MODE_BACKGROUND = 1;
int MINIMIZE_ON_EXIT_MODE_POPUP = 2;
}
////////////////////////////////////////////////////////////////////////////
// Exposed helpers
////////////////////////////////////////////////////////////////////////////
@@ -172,6 +185,22 @@ public class PlayerHelper {
return isAutoQueueEnabled(context, false);
}
@MinimizeMode
public static int getMinimizeOnExitAction(@NonNull final Context context) {
final String defaultAction = context.getString(R.string.minimize_on_exit_none_key);
final String popupAction = context.getString(R.string.minimize_on_exit_popup_key);
final String backgroundAction = context.getString(R.string.minimize_on_exit_background_key);
final String action = getMinimizeOnExitAction(context, defaultAction);
if (action.equals(popupAction)) {
return MINIMIZE_ON_EXIT_MODE_POPUP;
} else if (action.equals(backgroundAction)) {
return MINIMIZE_ON_EXIT_MODE_BACKGROUND;
} else {
return MINIMIZE_ON_EXIT_MODE_NONE;
}
}
@NonNull
public static SeekParameters getSeekParameters(@NonNull final Context context) {
return isUsingInexactSeek(context, false) ?
@@ -212,7 +241,6 @@ public class PlayerHelper {
public static TrackSelection.Factory getQualitySelector(@NonNull final Context context,
@NonNull final BandwidthMeter meter) {
return new AdaptiveTrackSelection.Factory(meter,
AdaptiveTrackSelection.DEFAULT_MAX_INITIAL_BITRATE,
/*bufferDurationRequiredForQualityIncrease=*/1000,
AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
@@ -224,7 +252,7 @@ public class PlayerHelper {
}
public static int getShutdownFlingVelocity(@NonNull final Context context) {
return 10000;
return 6000;
}
public static int getTossFlingVelocity(@NonNull final Context context) {
@@ -248,7 +276,6 @@ public class PlayerHelper {
* System font scaling:
* Very small - 0.25f, Small - 0.5f, Normal - 1.0f, Large - 1.5f, Very Large - 2.0f
* */
@NonNull
public static float getCaptionScale(@NonNull final Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return 1f;
@@ -260,6 +287,16 @@ public class PlayerHelper {
return captioningManager.getFontScale();
}
public static float getScreenBrightness(@NonNull final Context context) {
//a value of less than 0, the default, means to use the preferred screen brightness
return getScreenBrightness(context, -1);
}
public static void setScreenBrightness(@NonNull final Context context, final float setScreenBrightness) {
setScreenBrightness(context, setScreenBrightness, System.currentTimeMillis());
}
////////////////////////////////////////////////////////////////////////////
// Private helpers
////////////////////////////////////////////////////////////////////////////
@@ -292,4 +329,29 @@ public class PlayerHelper {
private static boolean isAutoQueueEnabled(@NonNull final Context context, final boolean b) {
return getPreferences(context).getBoolean(context.getString(R.string.auto_queue_key), b);
}
private static void setScreenBrightness(@NonNull final Context context, final float screenBrightness, final long timestamp) {
SharedPreferences.Editor editor = getPreferences(context).edit();
editor.putFloat(context.getString(R.string.screen_brightness_key), screenBrightness);
editor.putLong(context.getString(R.string.screen_brightness_timestamp_key), timestamp);
editor.apply();
}
private static float getScreenBrightness(@NonNull final Context context, final float screenBrightness) {
SharedPreferences sp = getPreferences(context);
long timestamp = sp.getLong(context.getString(R.string.screen_brightness_timestamp_key), 0);
// hypothesis: 4h covers a viewing block, eg evening. External lightning conditions will change in the next
// viewing block so we fall back to the default brightness
if ((System.currentTimeMillis() - timestamp) > TimeUnit.HOURS.toMillis(4)) {
return screenBrightness;
} else {
return sp.getFloat(context.getString(R.string.screen_brightness_key), screenBrightness);
}
}
private static String getMinimizeOnExitAction(@NonNull final Context context,
final String key) {
return getPreferences(context).getString(context.getString(R.string.minimize_on_exit_key),
key);
}
}

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