Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download playlist #2018

Closed
wants to merge 9 commits into from
Closed

Conversation

VishalNehra
Copy link

@VishalNehra VishalNehra commented Jan 18, 2019

Hello,
My first contribution here. Saw there's missing option to download playlist, so tried implementing it.
Open to suggestions.
Fixes #1058

Edit: Also noticed, channel specific playlists are not shown on the channel page. I'm interested in implementing a way to show them too. Please point me to the issue if still exists.

@theScrabi
Copy link
Member

I will not add features right now. There are already so many features and bugs at the moment that I/we can not take care about this any time soon.
So this will have to wait, and propably need to be refactored then.

@TobiGr
Copy link
Member

TobiGr commented Jun 17, 2019

@VishalNehra I've just merged a bunch of downloader changes (see #2149). I'd like to take a look at your changes soon. Can you please rebase?

@VishalNehra
Copy link
Author

@TobiGr sure, will try this weekend.

@gcandrade10
Copy link

I tried to resolve the conflicts and I just realize that your download all implementation triggers a pop-up for each item of the playlist that was the idea?
I'm not a UX or something but I was expecting to choose just one time the download settings (e.g audio, 32 threads) and that's it 🤔

@VishalNehra
Copy link
Author

There is a smart download option in the download dialog which I added, which will identify your last chose setting and based on that will download remaining items of playlist without opening dialog for each.

@gcandrade10
Copy link

Yes! you are right, it's an 'auto' checkbox!

@VishalNehra
Copy link
Author

Alright, after hours of trouble to merge the latest dev branch here, I'm expecting this to get reviewed this time. @theScrabi

strongwinderic
strongwinderic previously approved these changes Sep 6, 2019
Copy link

@strongwinderic strongwinderic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice and clean code!

strongwinderic
strongwinderic previously approved these changes Sep 9, 2019
@TobiGr
Copy link
Member

TobiGr commented Sep 24, 2019

@VishalNehra The code looks good. I'll test it in the during the week.
@kapodamy You are aware of all things regarding the download process. Can you please review it, too?

@theScrabi theScrabi requested review from karyogamy and removed request for karyogamy September 24, 2019 19:37
kapodamy
kapodamy previously approved these changes Sep 24, 2019
@kapodamy
Copy link
Contributor

@TobiGr looks fine, i submited a review that was not necessary

@VishalNehra
Copy link
Author

Sure @TobiGr I'll be rebasing on weekend, and also have a minor fix which I didn't commit.

@VishalNehra
Copy link
Author

I've rebased dev and fixed some NPEs
I'm done from my side, there might be some problems if we rotate screen at the same time we tick the 'auto' option in dialog.. apart from that, it seems stable enough now.
Thanks for the patience and sorry again for dragging this but I've been caught up with my daily job.
cc @Stypox @TobiGr

@@ -138,6 +155,231 @@ public static void playOnBackgroundPlayer(final Context context, final PlayQueue
startService(context, getPlayerIntent(context, BackgroundPlayer.class, queue, resumePlayback));
}

public static void downloadPlaylist(final PlaylistFragment context, final PlayQueue queue) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do all of these PlaylistFragment types always have to be like that? Couldn't a Fragment or Activity work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly do you mean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if one wants to download a playlist from a different fragment? It would be better if the type of the parameter context was the base class Fragment and not PlaylistFragment, so that the method can be used everywhere.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically I can get away with using FragmentActivity instead (there would be some implications; like I'm passing onError implementation of PlaylistFragment for reactive stream failure, while in FragmentActivity won't be able to do that. If there were an abstract class, I could've used that instead, for this specific use case.
Apart from that, the initial call to initialize DownloadDialog#newInstance requires PlaylistFragment#callback now. Again, an abstract class would help here too, so in future you would need to extend that class wherever you would want to initialize this download dialog.
Right now it's tightly coupled with PlaylistFragment, but the change you're suggesting would require a lot of changes in many parts of your source.
I'll leave it upto you to decide for this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmhh OK, in case I ever need to use it from elsewhere I will implement it myself

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, in this case it is time for a last round of testing and then we should be ready, finally :)
Thanks again for keeping your branch updated @VishalNehra. I am sorry, we've kept you waiting way too long.

@TobiGr
Copy link
Member

TobiGr commented Nov 4, 2019

Using KitKat (API 19, Android 4.4) I get this Exception when downloading a YouTube (upstream) playlist:

android.view.InflateException: Binary XML file line #64: Error inflating class android.support.v7.widget.AppCompatCheckBox
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:708)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:756)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
        at org.schabi.newpipe.download.DownloadDialog.onCreateView(DownloadDialog.java:254)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
        at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5017)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v7.widget.AppCompatCheckBox" on path: DexPathList[[zip file "/data/app/org.schabi.newpipe.debug-1.apk", zip file "/data/data/org.schabi.newpipe.debug/code_cache/secondary-dexes/org.schabi.newpipe.debug-1.apk.classes2.zip", zip file "/data/data/org.schabi.newpipe.debug/code_cache/secondary-dexes/org.schabi.newpipe.debug-1.apk.classes3.zip"],nativeLibraryDirectories=[/data/app-lib/org.schabi.newpipe.debug-1, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
        at android.view.LayoutInflater.createView(LayoutInflater.java:559)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:756) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:353) 
        at org.schabi.newpipe.download.DownloadDialog.onCreateView(DownloadDialog.java:254) 
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600) 
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881) 
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238) 
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303) 
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439) 
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079) 
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869) 
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824) 
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727) 
        at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150) 
        at android.os.Handler.handleCallback(Handler.java:733) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:136) 
        at android.app.ActivityThread.main(ActivityThread.java:5017) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
        at dalvik.system.NativeStart.main(Native Method) 

Copy link
Contributor

@mauriciocolli mauriciocolli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had an overview, and in my opinion we should not merge this as it is. Here are some reasons:

  • Coupling to the fragment, which definitely shouldn't be necessary.
  • Spaghetti code in the NavigationHelper.
  • Bad UX to the user.
    • Rotated the phone? Switched apps? Problems ahead.
  • This don't deal with configurations changes.
  • As the playlist in the fragment is paged, it isn't completely loaded yet, so this don't download all the playlist.

Creating a new screen showing a list of items giving the user the option to select which one they wanted, and the preferred configurations for all downloads (per-item configuration as well), would be much better here.

PS: Downloading all the items (the stream pages) might have an impact on reCAPTCHAs. YouTube seems to rate limit those a lot, so it should handle this as well.

private StoredFileHelper storedFileHelper;
private int threadCount;
private String[] urls;
private char kind;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a good idea using char for this, a enum would be much better.

@@ -304,6 +308,12 @@ public void handleResult(@NonNull final PlaylistInfo result) {
return true;
});

headerDownloadAllButton.setOnClickListener(view -> {
if (PermissionHelper.checkStoragePermissions(activity, PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) {
NavigationHelper.downloadPlaylist(this, getPlayQueue());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange use of the PlayQueue items here. Why not the items themselves?

@@ -345,7 +365,7 @@ public void handleNextItems(ListExtractor.InfoItemsPage result) {
//////////////////////////////////////////////////////////////////////////*/

@Override
protected boolean onError(Throwable exception) {
public boolean onError(Throwable exception) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should strictly remain for internal use only.

final Iterator<PlayQueueItem> itemIterator,
DownloadSetting downloadSetting) {
if (downloadSetting != null) {
Completable.create(emitter -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The create method should not be used. Also this isn't the ideal place to subscribe.

* @param streamInfo
* @return
*/
private static DownloadSetting refactorDownloadSetting(PlaylistFragment activity, DownloadSetting downloadSetting,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire method just feels out of place, navigation should be the only thing done in this class.

@@ -61,11 +61,24 @@
android:text="@string/caption_setting_title"/>
</RadioGroup>

<android.support.v7.widget.AppCompatCheckBox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be just CheckBox, let the library replace that for you.

android:layout_below="@+id/video_audio_group"
android:layout_marginBottom="6dp"
android:layout_marginLeft="20dp"
android:gravity="left"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to set gravity here, it will mess up the alignment. It'll also cause issues with RTL languages.

@Stypox
Copy link
Member

Stypox commented Dec 15, 2019

@VishalNehra could you address @mauriciocolli's suggestions? @TobiGr it would be good to have this merged after 0.18.0 is released, so that I can start working on #2583. If you @VishalNehra have no time to dedicate to this pr anymore, feel free to tell me, I would be ok creating a new pr myself ;-)

@gcandrade10
Copy link

Any updates here?

@Stypox Stypox mentioned this pull request Jan 22, 2020
3 tasks
@VishalNehra
Copy link
Author

Sorry for late reply, I did agree with @mauriciocolli however, my current schedule doesn't permit me to address all the changes.
I'm hoping some regular contributor of this project will pick this up.
If not, then I'll try to find some time in near future.

@realjustinwu
Copy link

Any updates here?

@ghost
Copy link

ghost commented May 21, 2020

I feel like this will never get implemented. I am really hoping this will be added on v0.21.0 so @Spypox's #2583 can be added aswell. :)

@B0pol
Copy link
Member

B0pol commented May 21, 2020

@Stypox worked on that but he was blocked waiting for @wb9688 download manager refactoring.

@Stypox
Copy link
Member

Stypox commented May 26, 2020

I decided that I will implement half of #2583 without bulk downloading for now, hopefully in a few days I should have something working with the proper code structure (i.e. not just a demonstration)

@MD77MD
Copy link

MD77MD commented Jun 17, 2020

@Stypox your just amazing!

@Stypox
Copy link
Member

Stypox commented Jan 16, 2021

I'm closing this as this is not really a good approach to bulk downloading. It would leak in many places and the current gigaget downloader is just crappy. We a new downloader for NewPipe will be built we will be able to finally implement this properly. @VishalNehra thank you for your work anyway ;-)

@Stypox Stypox closed this Jan 16, 2021
@0-Kala-0
Copy link

anything new on this topic ?

@Hereux
Copy link

Hereux commented Aug 18, 2023

Anything new on this topic?

@opusforlife2
Copy link
Collaborator

I think the standard forum etiquette applies here. "Don't necropost/Don't bump zombie threads" = "Don't add noise to zombie PRs or issues."

@TeamNewPipe TeamNewPipe locked as spam and limited conversation to collaborators Aug 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature request Issue is related to a feature in the app
Projects
None yet