diff --git a/app/build.gradle b/app/build.gradle index ee9f099d3f5..afca8564667 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { resValue "string", "app_name", "NewPipe" minSdkVersion 19 targetSdkVersion 29 - versionCode 951 - versionName "0.19.6" + versionCode 952 + versionName "0.19.7" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -163,7 +163,7 @@ dependencies { exclude module: 'support-annotations' } - implementation 'com.github.TeamNewPipe:NewPipeExtractor:a70cb0283ffc3bba2709815673a5a7940aab0a3a' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:b4481dfec21cf39aabbb791290d30130235aeabd' implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751" implementation "org.jsoup:jsoup:1.13.1" diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 531cb5a388b..33d77ea47ea 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -9,6 +9,7 @@ import android.os.Build; import android.util.Log; +import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; import com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache; @@ -37,7 +38,6 @@ import java.util.Collections; import java.util.List; -import io.reactivex.annotations.NonNull; import io.reactivex.exceptions.CompositeException; import io.reactivex.exceptions.MissingBackpressureException; import io.reactivex.exceptions.OnErrorNotImplementedException; 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 fff689930cd..336e3997e27 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 @@ -365,10 +365,6 @@ public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, public void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); - // Check if the next video label and video is visible, - // if it is, include the two elements in the next check - int nextCount = currentInfo != null && currentInfo.getNextVideo() != null ? 2 : 0; - if (!isLoading.get() && currentInfo != null && isVisible()) { outState.putSerializable(INFO_KEY, currentInfo); } @@ -1018,14 +1014,14 @@ private VideoStream getSelectedVideoStream() { } private void prepareDescription(final Description description) { - if (TextUtils.isEmpty(description.getContent()) + if (description == null || TextUtils.isEmpty(description.getContent()) || description == Description.emptyDescription) { return; } if (description.getType() == Description.HTML) { disposables.add(Single.just(description.getContent()) - .map((@io.reactivex.annotations.NonNull String descriptionText) -> { + .map((@NonNull String descriptionText) -> { Spanned parsedDescription; if (Build.VERSION.SDK_INT >= 24) { parsedDescription = Html.fromHtml(descriptionText, 0); @@ -1037,7 +1033,7 @@ private void prepareDescription(final Description description) { }) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe((@io.reactivex.annotations.NonNull Spanned spanned) -> { + .subscribe((@NonNull Spanned spanned) -> { videoDescriptionView.setText(spanned); videoDescriptionView.setVisibility(View.VISIBLE); })); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java index 82b1d18ed05..86b093e453b 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java @@ -158,11 +158,10 @@ protected void loadMoreItems() { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doFinally(this::allowDownwardFocusScroll) - .subscribe((@io.reactivex.annotations.NonNull - ListExtractor.InfoItemsPage InfoItemsPage) -> { + .subscribe((@NonNull ListExtractor.InfoItemsPage InfoItemsPage) -> { isLoading.set(false); handleNextItems(InfoItemsPage); - }, (@io.reactivex.annotations.NonNull Throwable throwable) -> { + }, (@NonNull Throwable throwable) -> { isLoading.set(false); onError(throwable); }); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java index 5d48afd15d5..cf2101111aa 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java @@ -9,7 +9,6 @@ import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CompoundButton; import android.widget.Switch; import androidx.annotation.NonNull; @@ -40,9 +39,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment PreferenceManager.getDefaultSharedPreferences(getContext()).edit() - .putBoolean(getString(R.string.auto_queue_key), b).apply(); - } - }); + .putBoolean(getString(R.string.auto_queue_key), b).apply()); return headerRootLayout; } else { return null; @@ -105,7 +92,7 @@ public void onCheckedChanged(final CompoundButton compoundButton, @Override protected Single loadMoreItemsLogic() { - return Single.fromCallable(() -> ListExtractor.InfoItemsPage.emptyPage()); + return Single.fromCallable(ListExtractor.InfoItemsPage::emptyPage); } /*////////////////////////////////////////////////////////////////////////// @@ -216,8 +203,8 @@ public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String s) { SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext()); boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false); - if (null != aSwitch) { - aSwitch.setChecked(autoplay); + if (autoplaySwitch != null) { + autoplaySwitch.setChecked(autoplay); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index db98ee6d3ae..e63e56bf99f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -132,17 +132,17 @@ public static String cacheKeyOf(@NonNull final StreamInfo info, } /** - * Given a {@link StreamInfo} and the existing queue items, provide the - * {@link SinglePlayQueue} consisting of the next video for auto queuing. + * Given a {@link StreamInfo} and the existing queue items, + * provide the {@link SinglePlayQueue} consisting of the next video for auto queueing. *

- * This method detects and prevents cycle by naively checking if a - * candidate next video's url already exists in the existing items. + * This method detects and prevents cycles by naively checking + * if a candidate next video's url already exists in the existing items. *

*

- * To select the next video, {@link StreamInfo#getNextVideo()} is first - * checked. If it is nonnull and is not part of the existing items, then - * it will be used as the next video. Otherwise, an random item with - * non-repeating url will be selected from the {@link StreamInfo#getRelatedStreams()}. + * The first item in {@link StreamInfo#getRelatedStreams()} is checked first. + * If it is non-null and is not part of the existing items, it will be used as the next stream. + * Otherwise, a random item with non-repeating url will be selected + * from the {@link StreamInfo#getRelatedStreams()}. *

* * @param info currently playing stream @@ -152,27 +152,28 @@ public static String cacheKeyOf(@NonNull final StreamInfo info, @Nullable public static PlayQueue autoQueueOf(@NonNull final StreamInfo info, @NonNull final List existingItems) { - Set urls = new HashSet<>(existingItems.size()); + final Set urls = new HashSet<>(existingItems.size()); for (final PlayQueueItem item : existingItems) { urls.add(item.getUrl()); } - final StreamInfoItem nextVideo = info.getNextVideo(); - if (nextVideo != null && !urls.contains(nextVideo.getUrl())) { - return getAutoQueuedSinglePlayQueue(nextVideo); - } - final List relatedItems = info.getRelatedStreams(); if (relatedItems == null) { return null; } - List autoQueueItems = new ArrayList<>(); - for (final InfoItem item : info.getRelatedStreams()) { + if (relatedItems.get(0) != null && relatedItems.get(0) instanceof StreamInfoItem + && !urls.contains(relatedItems.get(0).getUrl())) { + return getAutoQueuedSinglePlayQueue((StreamInfoItem) relatedItems.get(0)); + } + + final List autoQueueItems = new ArrayList<>(); + for (final InfoItem item : relatedItems) { if (item instanceof StreamInfoItem && !urls.contains(item.getUrl())) { autoQueueItems.add((StreamInfoItem) item); } } + Collections.shuffle(autoQueueItems); return autoQueueItems.isEmpty() ? null : getAutoQueuedSinglePlayQueue(autoQueueItems.get(0)); diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java index cde376f4fa5..3c15cd3422d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java @@ -2,6 +2,8 @@ import android.util.Log; +import androidx.annotation.NonNull; + import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListInfo; @@ -13,7 +15,6 @@ import java.util.List; import io.reactivex.SingleObserver; -import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; abstract class AbstractInfoPlayQueue extends PlayQueue { diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java index f8777597aeb..3b42f274555 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueAdapter.java @@ -6,6 +6,7 @@ import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import org.schabi.newpipe.R; @@ -20,7 +21,6 @@ import java.util.List; import io.reactivex.Observer; -import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; /** diff --git a/app/src/main/java/org/schabi/newpipe/util/RelatedStreamInfo.java b/app/src/main/java/org/schabi/newpipe/util/RelatedStreamInfo.java index ce642da5e3d..fcd392d67d6 100644 --- a/app/src/main/java/org/schabi/newpipe/util/RelatedStreamInfo.java +++ b/app/src/main/java/org/schabi/newpipe/util/RelatedStreamInfo.java @@ -4,16 +4,12 @@ import org.schabi.newpipe.extractor.ListInfo; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.stream.StreamInfo; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class RelatedStreamInfo extends ListInfo { - - private StreamInfoItem nextStream; - public RelatedStreamInfo(final int serviceId, final ListLinkHandler listUrlIdHandler, final String name) { super(serviceId, listUrlIdHandler, name); @@ -25,20 +21,8 @@ public static RelatedStreamInfo getInfo(final StreamInfo info) { RelatedStreamInfo relatedStreamInfo = new RelatedStreamInfo( info.getServiceId(), handler, info.getName()); List streams = new ArrayList<>(); - if (info.getNextVideo() != null) { - streams.add(info.getNextVideo()); - } streams.addAll(info.getRelatedStreams()); relatedStreamInfo.setRelatedItems(streams); - relatedStreamInfo.setNextStream(info.getNextVideo()); return relatedStreamInfo; } - - public StreamInfoItem getNextStream() { - return nextStream; - } - - public void setNextStream(final StreamInfoItem nextStream) { - this.nextStream = nextStream; - } } diff --git a/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java b/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java index 1c868f66a7d..bd5ae10e8e0 100644 --- a/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java +++ b/app/src/main/java/org/schabi/newpipe/views/FocusOverlayView.java @@ -74,44 +74,26 @@ public FocusOverlayView(final Context context) { @Override public void onGlobalFocusChanged(final View oldFocus, final View newFocus) { - int l = focusRect.left; - int r = focusRect.right; - int t = focusRect.top; - int b = focusRect.bottom; - - if (newFocus != null && newFocus.getWidth() > 0 && newFocus.getHeight() > 0) { - newFocus.getGlobalVisibleRect(focusRect); - + if (newFocus != null) { focused = new WeakReference<>(newFocus); } else { - focusRect.setEmpty(); - focused = null; } - if (l != focusRect.left || r != focusRect.right - || t != focusRect.top || b != focusRect.bottom) { - invalidateSelf(); - } - - focused = new WeakReference<>(newFocus); + updateRect(); animator.sendEmptyMessageDelayed(0, 1000); } private void updateRect() { - if (focused == null) { - return; - } - - View focusedView = this.focused.get(); + View focusedView = focused == null ? null : this.focused.get(); int l = focusRect.left; int r = focusRect.right; int t = focusRect.top; int b = focusRect.bottom; - if (focusedView != null) { + if (focusedView != null && isShown(focusedView)) { focusedView.getGlobalVisibleRect(focusRect); } else { focusRect.setEmpty(); @@ -123,6 +105,10 @@ private void updateRect() { } } + private boolean isShown(@NonNull final View view) { + return view.getWidth() != 0 && view.getHeight() != 0 && view.isShown(); + } + @Override public void onDraw() { updateRect(); @@ -223,6 +209,7 @@ private static void setupOverlay(final Window window, final FocusOverlayView ove observer.addOnGlobalFocusChangeListener(overlay); observer.addOnGlobalLayoutListener(overlay); observer.addOnTouchModeChangeListener(overlay); + observer.addOnDrawListener(overlay); overlay.setCurrentFocus(decor.getFocusedChild()); diff --git a/fastlane/metadata/android/en-US/changelogs/952.txt b/fastlane/metadata/android/en-US/changelogs/952.txt new file mode 100644 index 00000000000..c72818bc58d --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/952.txt @@ -0,0 +1,7 @@ +Improved +• Auto-play is available for all services (instead of only for YouTube) + +Fixed +• Fixed related streams by supporting YouTube's new continuations +• Fixed age restricted YouTube videos +• [Android TV] Fixed lingering focus highlight overlay \ No newline at end of file