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

Compare commits

...

147 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
86 changed files with 3426 additions and 1250 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 64
versionName "0.13.5"
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

@@ -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
@@ -125,7 +127,7 @@ public final class MainVideoPlayer extends AppCompatActivity
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) {
@@ -152,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
@@ -177,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());
}
}
@@ -191,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");
@@ -200,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);
}
@@ -208,10 +220,17 @@ public final class MainVideoPlayer extends AppCompatActivity
protected void onStop() {
if (DEBUG) Log.d(TAG, "onStop() called");
super.onStop();
playerImpl.destroy();
PlayerHelper.setScreenBrightness(getApplicationContext(),
getWindow().getAttributes().screenBrightness);
if (playerImpl == null) return;
if (!isBackPressed) {
playerImpl.minimize();
}
playerImpl.destroy();
isInMultiWindow = false;
isBackPressed = false;
}
/*//////////////////////////////////////////////////////////////////////////
@@ -335,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);
}
}
///////////////////////////////////////////////////////////////////////////
@@ -441,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
//////////////////////////////////////////////////////////////////////////*/
@@ -461,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
@@ -501,6 +535,7 @@ public final class MainVideoPlayer extends AppCompatActivity
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
context.startService(intent);
@@ -522,6 +557,7 @@ public final class MainVideoPlayer extends AppCompatActivity
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
context.startService(intent);
@@ -617,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);
}
@@ -647,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.getResolutionIndex(context, sortedVideos, playbackQuality);
@Override
public int getOverrideResolutionIndex(List<VideoStream> sortedVideos,
String playbackQuality) {
return ListHelper.getResolutionIndex(context, sortedVideos, playbackQuality);
}
};
}
/*//////////////////////////////////////////////////////////////////////////
@@ -678,7 +720,6 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void onBuffering() {
super.onBuffering();
animatePlayButtons(false, 100);
getRootView().setKeepScreenOn(true);
}
@@ -854,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();

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

@@ -39,10 +39,13 @@ public class MediaSessionManager {
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,6 +4,7 @@ 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;
@@ -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;
@@ -42,6 +44,8 @@ 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() {}
@@ -51,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
////////////////////////////////////////////////////////////////////////////
@@ -173,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) ?
@@ -213,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,
@@ -225,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) {
@@ -249,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;
@@ -322,4 +348,10 @@ public class PlayerHelper {
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);
}
}

View File

@@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.source.BaseMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.upstream.Allocator;
@@ -11,7 +12,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import java.io.IOException;
public class FailedMediaSource implements ManagedMediaSource {
public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSource {
private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode());
public static class FailedMediaSourceException extends Exception {
@@ -72,11 +73,6 @@ public class FailedMediaSource implements ManagedMediaSource {
return System.currentTimeMillis() >= retryTimestamp;
}
@Override
public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) {
Log.e(TAG, "Loading failed source: ", error);
}
@Override
public void maybeThrowSourceInfoRefreshError() throws IOException {
throw new IOException(error);
@@ -90,8 +86,14 @@ public class FailedMediaSource implements ManagedMediaSource {
@Override
public void releasePeriod(MediaPeriod mediaPeriod) {}
@Override
public void releaseSource() {}
protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {
Log.e(TAG, "Loading failed source: ", error);
}
@Override
protected void releaseSourceInternal() {}
@Override
public boolean shouldBeReplacedWith(@NonNull final PlayQueueItem newIdentity,

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