diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index f6753f128..cbb658025 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -63,7 +63,6 @@ import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.history.HistoryListener; import org.schabi.newpipe.info_list.InfoItemBuilder; -import org.schabi.newpipe.player.BackgroundPlayer; import org.schabi.newpipe.player.MainVideoPlayer; import org.schabi.newpipe.player.PopupVideoPlayer; import org.schabi.newpipe.player.helper.PlayerHelper; diff --git a/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java new file mode 100644 index 000000000..74a4dc555 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java @@ -0,0 +1,131 @@ +package org.schabi.newpipe.playlist; + +import android.util.Log; + +import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.ListInfo; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.annotations.NonNull; +import io.reactivex.disposables.Disposable; + +abstract class AbstractInfoPlayQueue extends PlayQueue { + boolean isInitial; + boolean isComplete; + + int serviceId; + String baseUrl; + String nextUrl; + + transient Disposable fetchReactor; + + AbstractInfoPlayQueue(final U item) { + this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + } + + AbstractInfoPlayQueue(final int serviceId, + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(index, extractListItems(streams)); + + this.baseUrl = url; + this.nextUrl = nextPageUrl; + this.serviceId = serviceId; + + this.isInitial = streams.isEmpty(); + this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + } + + abstract protected String getTag(); + + @Override + public boolean isComplete() { + return isComplete; + } + + SingleObserver getHeadListObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull T result) { + if (!result.has_more_streams) isComplete = true; + nextUrl = result.next_streams_url; + + append(extractListItems(result.related_streams)); + + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(getTag(), "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + SingleObserver getNextItemsObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { + if (!result.hasMoreStreams()) isComplete = true; + nextUrl = result.nextItemsUrl; + + append(extractListItems(result.nextItemsList)); + + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(getTag(), "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + @Override + public void dispose() { + super.dispose(); + if (fetchReactor != null) fetchReactor.dispose(); + } + + private static List extractListItems(final List infos) { + List result = new ArrayList<>(); + for (final InfoItem stream : infos) { + if (stream instanceof StreamInfoItem) { + result.add(new PlayQueueItem((StreamInfoItem) stream)); + } + } + return result; + } +} diff --git a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java index c48f76127..239024f28 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java @@ -1,151 +1,45 @@ package org.schabi.newpipe.playlist; -import android.util.Log; - import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.util.ExtractorHelper; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import io.reactivex.SingleObserver; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -public final class ChannelPlayQueue extends PlayQueue { - private final String TAG = "ChannelPlayQueue@" + Integer.toHexString(hashCode()); - - private boolean isInitial; - private boolean isComplete; - - private int serviceId; - private String baseUrl; - private String nextUrl; - - private transient Disposable fetchReactor; - +public final class ChannelPlayQueue extends AbstractInfoPlayQueue { public ChannelPlayQueue(final ChannelInfoItem item) { - this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + super(item); } public ChannelPlayQueue(final int serviceId, - final String url, - final String nextPageUrl, - final List streams, - final int index) { - super(index, extractChannelItems(streams)); - - this.baseUrl = url; - this.nextUrl = nextPageUrl; - this.serviceId = serviceId; - - this.isInitial = streams.isEmpty(); - this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(serviceId, url, nextPageUrl, streams, index); } @Override - public boolean isComplete() { - return isComplete; + protected String getTag() { + return "ChannelPlayQueue@" + Integer.toHexString(hashCode()); } @Override public void fetch() { - if (isInitial) { + if (this.isInitial) { ExtractorHelper.getChannelInfo(this.serviceId, this.baseUrl, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getChannelInitialObserver()); + .subscribe(getHeadListObserver()); } else { ExtractorHelper.getMoreChannelItems(this.serviceId, this.baseUrl, this.nextUrl) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getChannelNextItemsObserver()); + .subscribe(getNextItemsObserver()); } } - - private SingleObserver getChannelInitialObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull ChannelInfo result) { - if (!result.has_more_streams) isComplete = true; - nextUrl = result.next_streams_url; - - append(extractChannelItems(result.related_streams)); - - isInitial = false; - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - private SingleObserver getChannelNextItemsObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { - if (!result.hasMoreStreams()) isComplete = true; - nextUrl = result.nextItemsUrl; - - append(extractChannelItems(result.nextItemsList)); - - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - @Override - public void dispose() { - super.dispose(); - if (fetchReactor != null) fetchReactor.dispose(); - } - - private static List extractChannelItems(final List infos) { - List result = new ArrayList<>(); - for (final InfoItem stream : infos) { - if (stream instanceof StreamInfoItem) { - result.add(new PlayQueueItem((StreamInfoItem) stream)); - } - } - return result; - } } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java index 39ac6517d..30edcec7c 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java @@ -1,150 +1,45 @@ package org.schabi.newpipe.playlist; -import android.util.Log; - import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.util.ExtractorHelper; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import io.reactivex.SingleObserver; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -public final class PlaylistPlayQueue extends PlayQueue { - private final String TAG = "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); - - private boolean isInitial; - private boolean isComplete; - - private int serviceId; - private String baseUrl; - private String nextUrl; - - private transient Disposable fetchReactor; - +public final class PlaylistPlayQueue extends AbstractInfoPlayQueue { public PlaylistPlayQueue(final PlaylistInfoItem item) { - this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + super(item); } public PlaylistPlayQueue(final int serviceId, - final String url, - final String nextPageUrl, - final List streams, - final int index) { - super(index, extractPlaylistItems(streams)); - - this.baseUrl = url; - this.nextUrl = nextPageUrl; - this.serviceId = serviceId; - - this.isInitial = streams.isEmpty(); - this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(serviceId, url, nextPageUrl, streams, index); } @Override - public boolean isComplete() { - return isComplete; + protected String getTag() { + return "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); } @Override public void fetch() { - if (isInitial) { + if (this.isInitial) { ExtractorHelper.getPlaylistInfo(this.serviceId, this.baseUrl, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getInitialPlaylistObserver()); + .subscribe(getHeadListObserver()); } else { ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getPlaylistNextItemsObserver()); + .subscribe(getNextItemsObserver()); } } - - private SingleObserver getInitialPlaylistObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull PlaylistInfo result) { - if (!result.has_more_streams) isComplete = true; - nextUrl = result.next_streams_url; - - append(extractPlaylistItems(result.related_streams)); - - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - private SingleObserver getPlaylistNextItemsObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { - if (!result.hasMoreStreams()) isComplete = true; - nextUrl = result.nextItemsUrl; - - append(extractPlaylistItems(result.nextItemsList)); - - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - @Override - public void dispose() { - super.dispose(); - if (fetchReactor != null) fetchReactor.dispose(); - } - - private static List extractPlaylistItems(final List infos) { - List result = new ArrayList<>(); - for (final InfoItem stream : infos) { - if (stream instanceof StreamInfoItem) { - result.add(new PlayQueueItem((StreamInfoItem) stream)); - } - } - return result; - } } diff --git a/app/src/main/res/layout/list_channel_item.xml b/app/src/main/res/layout/list_channel_item.xml index 90f88b26f..4fa74387e 100644 --- a/app/src/main/res/layout/list_channel_item.xml +++ b/app/src/main/res/layout/list_channel_item.xml @@ -31,13 +31,13 @@ android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" - android:layout_marginLeft="@dimen/video_item_search_image_right_margin" - android:layout_marginStart="@dimen/video_item_search_image_right_margin" + android:paddingLeft="@dimen/video_item_search_padding" + android:paddingStart="@dimen/video_item_search_padding" android:background="?attr/selectableItemBackground" android:src="?attr/more_vertical" android:visibility="gone" - tools:ignore="ContentDescription" - tools:visibility="visible" /> + tools:visibility="visible" + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/>