getParentActivity() {
final ViewParent rootParent = binding.getRoot().getParent();
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
index 7df9102b75d..43440b87359 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
@@ -8,7 +8,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
-import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -61,6 +60,12 @@ public final class PopupPlayerUi extends VideoPlayerUi {
private WindowManager.LayoutParams popupLayoutParams; // null if player is not popup
private final WindowManager windowManager;
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Constructor, setup, destroy
+ //////////////////////////////////////////////////////////////////////////*/
+ //region Constructor, setup, destroy
+
public PopupPlayerUi(@NonNull final Player player,
@NonNull final PlayerBinding playerBinding) {
super(player, playerBinding);
@@ -173,11 +178,14 @@ public void destroy() {
super.destroy();
removePopupFromView();
}
+ //endregion
+
/*//////////////////////////////////////////////////////////////////////////
// Broadcast receiver
//////////////////////////////////////////////////////////////////////////*/
//region Broadcast receiver
+
@Override
public void onBroadcastReceived(final Intent intent) {
super.onBroadcastReceived(intent);
@@ -200,6 +208,11 @@ public void onBroadcastReceived(final Intent intent) {
//endregion
+ /*//////////////////////////////////////////////////////////////////////////
+ // Popup position and size
+ //////////////////////////////////////////////////////////////////////////*/
+ //region Popup position and size
+
/**
* Check if {@link #popupLayoutParams}' position is within a arbitrary boundary
* that goes from (0, 0) to (screenWidth, screenHeight).
@@ -272,16 +285,19 @@ public void changePopupSize(final int width) {
windowManager.updateViewLayout(binding.getRoot(), popupLayoutParams);
}
- private void changePopupWindowFlags(final int flags) {
- if (DEBUG) {
- Log.d(TAG, "changePopupWindowFlags() called with: flags = [" + flags + "]");
- }
-
- if (!anyPopupViewIsNull()) {
- popupLayoutParams.flags = flags;
- windowManager.updateViewLayout(binding.getRoot(), popupLayoutParams);
- }
+ @Override
+ protected float calculateMaxEndScreenThumbnailHeight(@NonNull final Bitmap bitmap) {
+ // no need for the end screen thumbnail to be resized on popup player: it's only needed
+ // for the main player so that it is enlarged correctly inside the fragment
+ return bitmap.getHeight();
}
+ //endregion
+
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Popup closing
+ //////////////////////////////////////////////////////////////////////////*/
+ //region Popup closing
public void closePopup() {
if (DEBUG) {
@@ -351,23 +367,22 @@ private void end() {
}
}).start();
}
+ //endregion
- @Override
- protected float calculateMaxEndScreenThumbnailHeight(@NonNull final Bitmap bitmap) {
- // no need for the end screen thumbnail to be resized on popup player: it's only needed
- // for the main player so that it is enlarged correctly inside the fragment
- return bitmap.getHeight();
- }
+ /*//////////////////////////////////////////////////////////////////////////
+ // Playback states
+ //////////////////////////////////////////////////////////////////////////*/
+ //region Playback states
- private boolean popupHasParent() {
- return binding != null
- && binding.getRoot().getLayoutParams() instanceof WindowManager.LayoutParams
- && binding.getRoot().getParent() != null;
- }
+ private void changePopupWindowFlags(final int flags) {
+ if (DEBUG) {
+ Log.d(TAG, "changePopupWindowFlags() called with: flags = [" + flags + "]");
+ }
- private boolean anyPopupViewIsNull() {
- return popupLayoutParams == null || windowManager == null
- || binding.getRoot().getParent() == null;
+ if (!anyPopupViewIsNull()) {
+ popupLayoutParams.flags = flags;
+ windowManager.updateViewLayout(binding.getRoot(), popupLayoutParams);
+ }
}
@Override
@@ -400,11 +415,14 @@ protected void onPlaybackSpeedClicked() {
playbackSpeedPopupMenu.show();
isSomePopupMenuVisible = true;
}
+ //endregion
+
/*//////////////////////////////////////////////////////////////////////////
// Gestures
//////////////////////////////////////////////////////////////////////////*/
//region Gestures
+
private int distanceFromCloseButton(@NonNull final MotionEvent popupMotionEvent) {
final int closeOverlayButtonX = closeOverlayBinding.closeButton.getLeft()
+ closeOverlayBinding.closeButton.getWidth() / 2;
@@ -433,7 +451,19 @@ public boolean isInsideClosingRadius(@NonNull final MotionEvent popupMotionEvent
/*//////////////////////////////////////////////////////////////////////////
// Getters
//////////////////////////////////////////////////////////////////////////*/
- //region Gestures
+ //region Getters
+
+ private boolean popupHasParent() {
+ return binding != null
+ && binding.getRoot().getLayoutParams() instanceof WindowManager.LayoutParams
+ && binding.getRoot().getParent() != null;
+ }
+
+ private boolean anyPopupViewIsNull() {
+ return popupLayoutParams == null || windowManager == null
+ || binding.getRoot().getParent() == null;
+ }
+
public PlayerPopupCloseOverlayBinding getCloseOverlayBinding() {
return closeOverlayBinding;
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index 24cdb8908bb..f4ebc3304b5 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -135,6 +135,12 @@ public abstract class VideoPlayerUi extends PlayerUi
@NonNull private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder =
new SeekbarPreviewThumbnailHolder();
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Constructor, setup, destroy
+ //////////////////////////////////////////////////////////////////////////*/
+ //region Constructor, setup, destroy
+
public VideoPlayerUi(@NonNull final Player player,
@NonNull final PlayerBinding playerBinding) {
super(player);
@@ -142,11 +148,6 @@ public VideoPlayerUi(@NonNull final Player player,
setupFromView();
}
-
- /*//////////////////////////////////////////////////////////////////////////
- // Setup
- //////////////////////////////////////////////////////////////////////////*/
- //region Setup
public void setupFromView() {
initViews();
initListeners();
@@ -414,6 +415,7 @@ protected void setupElementsSize(final int buttonsMinWidth,
// Broadcast receiver
//////////////////////////////////////////////////////////////////////////*/
//region Broadcast receiver
+
@Override
public void onBroadcastReceived(final Intent intent) {
super.onBroadcastReceived(intent);
@@ -433,6 +435,7 @@ public void onBroadcastReceived(final Intent intent) {
// Thumbnail
//////////////////////////////////////////////////////////////////////////*/
//region Thumbnail
+
/**
* Scale the player audio / end screen thumbnail down if necessary.
*
@@ -481,6 +484,7 @@ private void updateEndScreenThumbnail() {
// Progress loop and updates
//////////////////////////////////////////////////////////////////////////*/
//region Progress loop and updates
+
@Override
public void onUpdateProgress(final int currentProgress,
final int duration,
@@ -744,6 +748,7 @@ public boolean isFullscreen() {
// Playback states
//////////////////////////////////////////////////////////////////////////*/
//region Playback states
+
@Override
public void onPrepared() {
super.onPrepared();
@@ -885,7 +890,8 @@ private void animatePlayButtons(final boolean show, final long duration) {
/*//////////////////////////////////////////////////////////////////////////
// Repeat, shuffle, mute
//////////////////////////////////////////////////////////////////////////*/
- //region Repeat and shuffle
+ //region Repeat, shuffle, mute
+
public void onRepeatClicked() {
if (DEBUG) {
Log.d(TAG, "onRepeatClicked() called");
@@ -945,52 +951,9 @@ private void setShuffleButton(final boolean shuffled) {
/*//////////////////////////////////////////////////////////////////////////
- // ExoPlayer listeners (that didn't fit in other categories)
+ // Other player listeners
//////////////////////////////////////////////////////////////////////////*/
- //region ExoPlayer listeners (that didn't fit in other categories)
- @Override
- public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
- super.onTextTracksChanged(currentTracks);
-
- final boolean trackTypeTextSupported = !currentTracks.containsType(C.TRACK_TYPE_TEXT)
- || currentTracks.isTypeSupported(C.TRACK_TYPE_TEXT, false);
- if (getPlayer().getTrackSelector().getCurrentMappedTrackInfo() == null
- || !trackTypeTextSupported) {
- binding.captionTextView.setVisibility(View.GONE);
- return;
- }
-
- // Extract all loaded languages
- final List textTracks = currentTracks
- .getGroups()
- .stream()
- .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getType())
- .collect(Collectors.toList());
- final List availableLanguages = textTracks.stream()
- .map(Tracks.Group::getMediaTrackGroup)
- .filter(textTrack -> textTrack.length > 0)
- .map(textTrack -> textTrack.getFormat(0).language)
- .collect(Collectors.toList());
-
- // Find selected text track
- final Optional selectedTracks = textTracks.stream()
- .filter(Tracks.Group::isSelected)
- .filter(info -> info.getMediaTrackGroup().length >= 1)
- .map(info -> info.getMediaTrackGroup().getFormat(0))
- .findFirst();
-
- // Build UI
- buildCaptionMenu(availableLanguages);
- //noinspection SimplifyOptionalCallChains
- if (player.getTrackSelector().getParameters().getRendererDisabled(
- player.getCaptionRendererIndex()) || !selectedTracks.isPresent()) {
- binding.captionTextView.setText(R.string.caption_none);
- } else {
- binding.captionTextView.setText(selectedTracks.get().language);
- }
- binding.captionTextView.setVisibility(
- availableLanguages.isEmpty() ? View.GONE : View.VISIBLE);
- }
+ //region Other player listeners
@Override
public void onPlaybackParametersChanged(@NonNull final PlaybackParameters playbackParameters) {
@@ -1004,12 +967,6 @@ public void onRenderedFirstFrame() {
//TODO check if this causes black screen when switching to fullscreen
animate(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION);
}
-
- @Override
- public void onCues(@NonNull List cues) {
- super.onCues(cues);
- binding.subtitleView.setCues(cues);
- }
//endregion
@@ -1017,6 +974,7 @@ public void onCues(@NonNull List cues) {
// Metadata & stream related views
//////////////////////////////////////////////////////////////////////////*/
//region Metadata & stream related views
+
@Override
public void onMetadataChanged(@NonNull final StreamInfo info) {
super.onMetadataChanged(info);
@@ -1092,6 +1050,7 @@ private void updateStreamRelatedViews() {
// Popup menus ("popup" means that they pop up, not that they belong to the popup player)
//////////////////////////////////////////////////////////////////////////*/
//region Popup menus ("popup" means that they pop up, not that they belong to the popup player)
+
private void buildQualityMenu() {
if (qualityPopupMenu == null) {
return;
@@ -1315,6 +1274,57 @@ public boolean isSomePopupMenuVisible() {
// Captions (text tracks)
//////////////////////////////////////////////////////////////////////////*/
//region Captions (text tracks)
+
+ @Override
+ public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
+ super.onTextTracksChanged(currentTracks);
+
+ final boolean trackTypeTextSupported = !currentTracks.containsType(C.TRACK_TYPE_TEXT)
+ || currentTracks.isTypeSupported(C.TRACK_TYPE_TEXT, false);
+ if (getPlayer().getTrackSelector().getCurrentMappedTrackInfo() == null
+ || !trackTypeTextSupported) {
+ binding.captionTextView.setVisibility(View.GONE);
+ return;
+ }
+
+ // Extract all loaded languages
+ final List textTracks = currentTracks
+ .getGroups()
+ .stream()
+ .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getType())
+ .collect(Collectors.toList());
+ final List availableLanguages = textTracks.stream()
+ .map(Tracks.Group::getMediaTrackGroup)
+ .filter(textTrack -> textTrack.length > 0)
+ .map(textTrack -> textTrack.getFormat(0).language)
+ .collect(Collectors.toList());
+
+ // Find selected text track
+ final Optional selectedTracks = textTracks.stream()
+ .filter(Tracks.Group::isSelected)
+ .filter(info -> info.getMediaTrackGroup().length >= 1)
+ .map(info -> info.getMediaTrackGroup().getFormat(0))
+ .findFirst();
+
+ // Build UI
+ buildCaptionMenu(availableLanguages);
+ //noinspection SimplifyOptionalCallChains
+ if (player.getTrackSelector().getParameters().getRendererDisabled(
+ player.getCaptionRendererIndex()) || !selectedTracks.isPresent()) {
+ binding.captionTextView.setText(R.string.caption_none);
+ } else {
+ binding.captionTextView.setText(selectedTracks.get().language);
+ }
+ binding.captionTextView.setVisibility(
+ availableLanguages.isEmpty() ? View.GONE : View.VISIBLE);
+ }
+
+ @Override
+ public void onCues(@NonNull List cues) {
+ super.onCues(cues);
+ binding.subtitleView.setCues(cues);
+ }
+
private void setupSubtitleView() {
setupSubtitleView(PlayerHelper.getCaptionScale(context));
final CaptionStyleCompat captionStyle = PlayerHelper.getCaptionStyle(context);
@@ -1330,6 +1340,7 @@ private void setupSubtitleView() {
// Click listeners
//////////////////////////////////////////////////////////////////////////*/
//region Click listeners
+
@Override
public void onClick(final View v) {
if (DEBUG) {
@@ -1493,9 +1504,10 @@ private void onOpenInBrowserClicked() {
/*//////////////////////////////////////////////////////////////////////////
- // Video size, resize, orientation, fullscreen
+ // Video size
//////////////////////////////////////////////////////////////////////////*/
- //region Video size, resize, orientation, fullscreen
+ //region Video size
+
protected void setResizeMode(@AspectRatioFrameLayout.ResizeMode final int resizeMode) {
binding.surfaceView.setResizeMode(resizeMode);
binding.resizeTextView.setText(PlayerHelper.resizeTypeOf(context, resizeMode));
@@ -1569,6 +1581,7 @@ private void clearVideoSurface() {
// Getters
//////////////////////////////////////////////////////////////////////////*/
//region Getters
+
public PlayerBinding getBinding() {
return binding;
}
From 1b39b5376f518ee570258da82fbe4fb09d11c231 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Fri, 15 Apr 2022 00:01:59 +0200
Subject: [PATCH 036/152] Add some javadocs; move preparing player uis to
PlayerUiList
---
.../org/schabi/newpipe/player/Player.java | 25 ++---
.../schabi/newpipe/player/ui/PlayerUi.java | 92 ++++++++++++++++++-
.../newpipe/player/ui/PlayerUiList.java | 43 ++++++++-
3 files changed, 138 insertions(+), 22 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java
index b0fed3d7d70..f8ea7bc90cc 100644
--- a/app/src/main/java/org/schabi/newpipe/player/Player.java
+++ b/app/src/main/java/org/schabi/newpipe/player/Player.java
@@ -447,7 +447,7 @@ && isPlaybackResumeEnabled(this)
private void initUIsForCurrentPlayerType() {
//noinspection SimplifyOptionalCallChains
if (!UIs.get(NotificationPlayerUi.class).isPresent()) {
- UIs.add(new NotificationPlayerUi(this));
+ UIs.addAndPrepare(new NotificationPlayerUi(this));
}
if ((UIs.get(MainPlayerUi.class).isPresent() && playerType == PlayerType.MAIN)
@@ -469,24 +469,15 @@ private void initUIsForCurrentPlayerType() {
switch (playerType) {
case MAIN:
UIs.destroyAll(PopupPlayerUi.class);
- UIs.add(new MainPlayerUi(this, binding));
- break;
- case AUDIO:
- UIs.destroyAll(VideoPlayerUi.class);
+ UIs.addAndPrepare(new MainPlayerUi(this, binding));
break;
case POPUP:
UIs.destroyAll(MainPlayerUi.class);
- UIs.add(new PopupPlayerUi(this, binding));
+ UIs.addAndPrepare(new PopupPlayerUi(this, binding));
+ break;
+ case AUDIO:
+ UIs.destroyAll(VideoPlayerUi.class);
break;
- }
-
- if (fragmentListener != null) {
- // make sure UIs know whether a service is connected or not
- UIs.call(PlayerUi::onFragmentListenerSet);
- }
- if (!exoPlayerIsNull()) {
- UIs.call(PlayerUi::initPlayer);
- UIs.call(PlayerUi::initPlayback);
}
}
@@ -1968,9 +1959,9 @@ public int getCaptionRendererIndex() {
/*//////////////////////////////////////////////////////////////////////////
- // Video size, resize, orientation, fullscreen
+ // Video size
//////////////////////////////////////////////////////////////////////////*/
- //region Video size, resize, orientation, fullscreen
+ //region Video size
@Override // exoplayer listener
public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
if (DEBUG) {
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
index 81e93ca238f..c4db1f33426 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
@@ -18,50 +18,105 @@
import java.util.List;
+/**
+ * A player UI is a component that can seamlessly connect and disconnect from the {@link Player} and
+ * provide a user interface of some sort. Try to extend this class instead of adding more code to
+ * {@link Player}!
+ */
public abstract class PlayerUi {
- @NonNull protected Context context;
- @NonNull protected Player player;
+ @NonNull protected final Context context;
+ @NonNull protected final Player player;
+ /**
+ * @param player the player instance that will be usable throughout the lifetime of this UI
+ */
public PlayerUi(@NonNull final Player player) {
this.context = player.getContext();
this.player = player;
}
+ /**
+ * @return the player instance this UI was constructed with
+ */
@NonNull
public Player getPlayer() {
return player;
}
+ /**
+ * Called after the player received an intent and processed it
+ */
public void setupAfterIntent() {
}
+ /**
+ * Called right after the exoplayer instance is constructed, or right after this UI is
+ * constructed if the exoplayer is already available then. Note that the exoplayer instance
+ * could be built and destroyed multiple times during the lifetime of the player, so this method
+ * might be called multiple times.
+ */
public void initPlayer() {
}
+ /**
+ * Called when playback in the exoplayer is about to start, or right after this UI is
+ * constructed if the exoplayer and the play queue are already available then. The play queue
+ * will therefore always be not null.
+ */
public void initPlayback() {
}
+ /**
+ * Called when the exoplayer instance is about to be destroyed. Note that the exoplayer instance
+ * could be built and destroyed multiple times during the lifetime of the player, so this method
+ * might be called multiple times. Be sure to unset any video surface view or play queue
+ * listeners! This will also be called when this UI is being discarded, just before {@link
+ * #destroy()}.
+ */
public void destroyPlayer() {
}
+ /**
+ * Called when this UI is being discarded, either because the player is switching to a different
+ * UI or because the player is shutting down completely
+ */
public void destroy() {
}
+ /**
+ * Called when the player is smooth-stopping, that is, transitioning smoothly to a new play
+ * queue after the user tapped on a new video stream while a stream was playing in the video
+ * detail fragment
+ */
public void smoothStopForImmediateReusing() {
}
+ /**
+ * Called when the video detail fragment listener is connected with the player, or right after
+ * this UI is constructed if the listener is already connected then
+ */
public void onFragmentListenerSet() {
}
/**
- * If you want to register new broadcast actions to receive here, add them to
- * {@link Player#setupBroadcastReceiver()}.
+ * Broadcasts that the player receives will also be notified to UIs here. If you want to
+ * register new broadcast actions to receive here, add them to {@link
+ * Player#setupBroadcastReceiver()}.
*/
public void onBroadcastReceived(final Intent intent) {
}
+ /**
+ * Called when stream progress (i.e. the current time in the seekbar) or stream duration change.
+ * Will surely be called every {@link Player#PROGRESS_LOOP_INTERVAL_MILLIS} while a stream is
+ * playing.
+ * @param currentProgress the current progress in milliseconds
+ * @param duration the duration of the stream being played
+ * @param bufferPercent the percentage of stream already buffered, see {@link
+ * com.google.android.exoplayer2.BasePlayer#getBufferedPercentage()}
+ */
public void onUpdateProgress(final int currentProgress,
final int duration,
final int bufferPercent) {
@@ -97,27 +152,56 @@ public void onShuffleModeEnabledChanged(final boolean shuffleModeEnabled) {
public void onMuteUnmuteChanged(final boolean isMuted) {
}
+ /**
+ * @see com.google.android.exoplayer2.Player.Listener#onTracksChanged(Tracks)
+ */
public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
}
+ /**
+ * @see com.google.android.exoplayer2.Player.Listener#onPlaybackParametersChanged
+ */
public void onPlaybackParametersChanged(@NonNull final PlaybackParameters playbackParameters) {
}
+ /**
+ * @see com.google.android.exoplayer2.Player.Listener#onRenderedFirstFrame
+ */
public void onRenderedFirstFrame() {
}
+ /**
+ * @see com.google.android.exoplayer2.text.TextOutput#onCues
+ */
public void onCues(@NonNull final List cues) {
}
+ /**
+ * Called when the stream being played changes
+ * @param info the {@link StreamInfo} metadata object, along with data about the selected and
+ * available video streams (to be used to build the resolution menus, for example)
+ */
public void onMetadataChanged(@NonNull final StreamInfo info) {
}
+ /**
+ * Called when the thumbnail for the current metadata was loaded
+ * @param bitmap the thumbnail to process, or null if there is no thumbnail or there was an
+ * error when loading the thumbnail
+ */
public void onThumbnailLoaded(@Nullable final Bitmap bitmap) {
}
+ /**
+ * Called when the play queue was edited: a stream was appended, moved or removed.
+ */
public void onPlayQueueEdited() {
}
+ /**
+ * @param videoSize the new video size, useful to set the surface aspect ratio
+ * @see com.google.android.exoplayer2.Player.Listener#onVideoSizeChanged
+ */
public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java
index 8c5c0dbfabd..749cda02c61 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java
@@ -8,10 +8,39 @@
public final class PlayerUiList {
final List playerUis = new ArrayList<>();
- public void add(final PlayerUi playerUi) {
+ /**
+ * Adds the provided player ui to the list and calls on it the initialization functions that
+ * apply based on the current player state. The preparation step needs to be done since when UIs
+ * are removed and re-added, the player will not call e.g. initPlayer again since the exoplayer
+ * is already initialized, but we need to notify the newly built UI that the player is ready
+ * nonetheless.
+ * @param playerUi the player ui to prepare and add to the list; its {@link
+ * PlayerUi#getPlayer()} will be used to query information about the player
+ * state
+ */
+ public void addAndPrepare(final PlayerUi playerUi) {
+ if (playerUi.getPlayer().getFragmentListener().isPresent()) {
+ // make sure UIs know whether a service is connected or not
+ playerUi.onFragmentListenerSet();
+ }
+
+ if (!playerUi.getPlayer().exoPlayerIsNull()) {
+ playerUi.initPlayer();
+ if (playerUi.getPlayer().getPlayQueue() != null) {
+ playerUi.initPlayback();
+ }
+ }
+
playerUis.add(playerUi);
}
+ /**
+ * Destroys all matching player UIs and removes them from the list
+ * @param playerUiType the class of the player UI to destroy; the {@link
+ * Class#isInstance(Object)} method will be used, so even subclasses will be
+ * destroyed and removed
+ * @param the class type parameter
+ */
public void destroyAll(final Class playerUiType) {
playerUis.stream()
.filter(playerUiType::isInstance)
@@ -22,6 +51,14 @@ public void destroyAll(final Class playerUiType) {
playerUis.removeIf(playerUiType::isInstance);
}
+ /**
+ * @param playerUiType the class of the player UI to return; the {@link
+ * Class#isInstance(Object)} method will be used, so even subclasses could
+ * be returned
+ * @param the class type parameter
+ * @return the first player UI of the required type found in the list, or an empty {@link
+ * Optional} otherwise
+ */
public Optional get(final Class playerUiType) {
return playerUis.stream()
.filter(playerUiType::isInstance)
@@ -29,6 +66,10 @@ public Optional get(final Class playerUiType) {
.findFirst();
}
+ /**
+ * Calls the provided consumer on all player UIs in the list
+ * @param consumer the consumer to call with player UIs
+ */
public void call(final Consumer consumer) {
//noinspection SimplifyStreamApiCallChains
playerUis.stream().forEach(consumer);
From a19073ec011e7c314ccab2e9d84d466d235fd24a Mon Sep 17 00:00:00 2001
From: Stypox
Date: Sat, 16 Apr 2022 12:03:59 +0200
Subject: [PATCH 037/152] Restore checkstyle and solve its errors
---
app/build.gradle | 2 +-
.../fragments/detail/VideoDetailFragment.java | 25 +++++++++----------
.../org/schabi/newpipe/player/Player.java | 6 +++--
.../player/notification/NotificationUtil.java | 4 +--
.../player/playback/PlayerMediaSession.java | 2 --
.../newpipe/player/ui/MainPlayerUi.java | 2 +-
.../schabi/newpipe/player/ui/PlayerUi.java | 16 +++++++-----
.../newpipe/player/ui/PlayerUiList.java | 4 +--
.../newpipe/player/ui/VideoPlayerUi.java | 15 ++++++-----
.../custom/NotificationActionsPreference.java | 1 -
10 files changed, 41 insertions(+), 36 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 46eee8d00c6..9867037e6a9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -166,7 +166,7 @@ afterEvaluate {
if (!System.properties.containsKey('skipFormatKtlint')) {
preDebugBuild.dependsOn formatKtlint
}
- //preDebugBuild.dependsOn runCheckstyle, runKtlint
+ preDebugBuild.dependsOn runCheckstyle, runKtlint
}
sonarqube {
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 cb8f0961f5d..8ffff2f9ef1 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
@@ -1,5 +1,16 @@
package org.schabi.newpipe.fragments.detail;
+import static android.text.TextUtils.isEmpty;
+import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
+import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
+import static org.schabi.newpipe.ktx.ViewUtils.animate;
+import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
+import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
+import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
+import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
+import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
+import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams;
+
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.BroadcastReceiver;
@@ -43,7 +54,6 @@
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager;
-import androidx.viewbinding.ViewBinding;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
@@ -78,9 +88,9 @@
import org.schabi.newpipe.ktx.AnimationType;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager;
+import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.PlayerService.PlayerType;
-import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.event.OnKeyDownListener;
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
import org.schabi.newpipe.player.helper.PlayerHelper;
@@ -118,17 +128,6 @@
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
-import static android.text.TextUtils.isEmpty;
-import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
-import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
-import static org.schabi.newpipe.ktx.ViewUtils.animate;
-import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
-import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
-import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
-import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
-import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
-import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams;
-
public final class VideoDetailFragment
extends BaseStateFragment
implements BackPressable,
diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java
index f8ea7bc90cc..0755f9b4de0 100644
--- a/app/src/main/java/org/schabi/newpipe/player/Player.java
+++ b/app/src/main/java/org/schabi/newpipe/player/Player.java
@@ -239,6 +239,7 @@ public final class Player implements PlaybackListener, Listener {
// UIs, listeners and disposables
//////////////////////////////////////////////////////////////////////////*/
+ @SuppressWarnings("MemberName") // keep the unusual member name
private final PlayerUiList UIs = new PlayerUiList();
private BroadcastReceiver broadcastReceiver;
@@ -1148,7 +1149,7 @@ public void setRepeatMode(@RepeatMode final int repeatMode) {
simpleExoPlayer.setRepeatMode(repeatMode);
}
}
-
+
public void cycleNextRepeatMode() {
setRepeatMode(nextRepeatMode(getRepeatMode()));
}
@@ -1181,7 +1182,7 @@ public void onShuffleModeEnabledChanged(final boolean shuffleModeEnabled) {
UIs.call(playerUi -> playerUi.onShuffleModeEnabledChanged(shuffleModeEnabled));
notifyPlaybackUpdateToListeners();
}
-
+
public void toggleShuffleModeEnabled() {
if (!exoPlayerIsNull()) {
simpleExoPlayer.setShuffleModeEnabled(!simpleExoPlayer.getShuffleModeEnabled());
@@ -2301,6 +2302,7 @@ public Optional getFragmentListener() {
/**
* @return the user interfaces connected with the player
*/
+ @SuppressWarnings("MethodName") // keep the unusual method name
public PlayerUiList UIs() {
return UIs;
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java
index 5f005245343..28c3b3655ad 100644
--- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java
+++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java
@@ -132,7 +132,7 @@ private synchronized void updateNotification() {
// also update content intent, in case the user switched players
notificationBuilder.setContentIntent(PendingIntent.getActivity(player.getContext(),
- NOTIFICATION_ID, getIntentForNotification(player), FLAG_UPDATE_CURRENT));
+ NOTIFICATION_ID, getIntentForNotification(), FLAG_UPDATE_CURRENT));
notificationBuilder.setContentTitle(player.getVideoTitle());
notificationBuilder.setContentText(player.getUploaderName());
notificationBuilder.setTicker(player.getVideoTitle());
@@ -321,7 +321,7 @@ private NotificationCompat.Action getAction(@DrawableRes final int drawable,
new Intent(intentAction), FLAG_UPDATE_CURRENT));
}
- private Intent getIntentForNotification(final Player player) {
+ private Intent getIntentForNotification() {
if (player.audioPlayerSelected() || player.popupPlayerSelected()) {
// Means we play in popup or audio only. Let's show the play queue
return NavigationHelper.getPlayQueueActivityIntent(player.getContext());
diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java b/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java
index 2f261a0fa11..3be9b61734f 100644
--- a/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java
+++ b/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java
@@ -10,8 +10,6 @@
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.ui.VideoPlayerUi;
-import java.util.Optional;
-
public class PlayerMediaSession implements MediaSessionCallback {
private final Player player;
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
index c62382782e3..3bdda0029ae 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
@@ -497,7 +497,7 @@ private void showHideKodiButton() {
//region Captions (text tracks)
@Override
- protected void setupSubtitleView(float captionScale) {
+ protected void setupSubtitleView(final float captionScale) {
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int minimumLength = Math.min(metrics.heightPixels, metrics.widthPixels);
final float captionRatioInverse = 20f + 4f * (1.0f - captionScale);
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
index c4db1f33426..49980069035 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
@@ -46,7 +46,7 @@ public Player getPlayer() {
/**
- * Called after the player received an intent and processed it
+ * Called after the player received an intent and processed it.
*/
public void setupAfterIntent() {
}
@@ -80,7 +80,7 @@ public void destroyPlayer() {
/**
* Called when this UI is being discarded, either because the player is switching to a different
- * UI or because the player is shutting down completely
+ * UI or because the player is shutting down completely.
*/
public void destroy() {
}
@@ -88,14 +88,14 @@ public void destroy() {
/**
* Called when the player is smooth-stopping, that is, transitioning smoothly to a new play
* queue after the user tapped on a new video stream while a stream was playing in the video
- * detail fragment
+ * detail fragment.
*/
public void smoothStopForImmediateReusing() {
}
/**
* Called when the video detail fragment listener is connected with the player, or right after
- * this UI is constructed if the listener is already connected then
+ * this UI is constructed if the listener is already connected then.
*/
public void onFragmentListenerSet() {
}
@@ -104,6 +104,7 @@ public void onFragmentListenerSet() {
* Broadcasts that the player receives will also be notified to UIs here. If you want to
* register new broadcast actions to receive here, add them to {@link
* Player#setupBroadcastReceiver()}.
+ * @param intent the broadcast intent received by the player
*/
public void onBroadcastReceived(final Intent intent) {
}
@@ -154,12 +155,14 @@ public void onMuteUnmuteChanged(final boolean isMuted) {
/**
* @see com.google.android.exoplayer2.Player.Listener#onTracksChanged(Tracks)
+ * @param currentTracks the available tracks information
*/
public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
}
/**
* @see com.google.android.exoplayer2.Player.Listener#onPlaybackParametersChanged
+ * @param playbackParameters the new playback parameters
*/
public void onPlaybackParametersChanged(@NonNull final PlaybackParameters playbackParameters) {
}
@@ -172,12 +175,13 @@ public void onRenderedFirstFrame() {
/**
* @see com.google.android.exoplayer2.text.TextOutput#onCues
+ * @param cues the cues to pass to the subtitle view
*/
public void onCues(@NonNull final List cues) {
}
/**
- * Called when the stream being played changes
+ * Called when the stream being played changes.
* @param info the {@link StreamInfo} metadata object, along with data about the selected and
* available video streams (to be used to build the resolution menus, for example)
*/
@@ -185,7 +189,7 @@ public void onMetadataChanged(@NonNull final StreamInfo info) {
}
/**
- * Called when the thumbnail for the current metadata was loaded
+ * Called when the thumbnail for the current metadata was loaded.
* @param bitmap the thumbnail to process, or null if there is no thumbnail or there was an
* error when loading the thumbnail
*/
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java
index 749cda02c61..05c0ed5b3cc 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUiList.java
@@ -35,7 +35,7 @@ public void addAndPrepare(final PlayerUi playerUi) {
}
/**
- * Destroys all matching player UIs and removes them from the list
+ * Destroys all matching player UIs and removes them from the list.
* @param playerUiType the class of the player UI to destroy; the {@link
* Class#isInstance(Object)} method will be used, so even subclasses will be
* destroyed and removed
@@ -67,7 +67,7 @@ public Optional get(final Class playerUiType) {
}
/**
- * Calls the provided consumer on all player UIs in the list
+ * Calls the provided consumer on all player UIs in the list.
* @param consumer the consumer to call with player UIs
*/
public void call(final Consumer consumer) {
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index f4ebc3304b5..393bf141bf4 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -86,7 +86,8 @@
import java.util.stream.Collectors;
public abstract class VideoPlayerUi extends PlayerUi
- implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
+ implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, View.OnLongClickListener,
+ PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
private static final String TAG = VideoPlayerUi.class.getSimpleName();
// time constants
@@ -476,7 +477,7 @@ private void updateEndScreenThumbnail() {
binding.endScreen.setImageBitmap(endScreenBitmap);
}
- protected abstract float calculateMaxEndScreenThumbnailHeight(@NonNull final Bitmap bitmap);
+ protected abstract float calculateMaxEndScreenThumbnailHeight(@NonNull Bitmap bitmap);
//endregion
@@ -511,6 +512,7 @@ public void onUpdateProgress(final int currentProgress,
/**
* Sets the current duration into the corresponding elements.
+ * @param currentProgress the current progress, in milliseconds
*/
private void updatePlayBackElementsCurrentDuration(final int currentProgress) {
// Don't set seekbar progress while user is seeking
@@ -522,6 +524,7 @@ private void updatePlayBackElementsCurrentDuration(final int currentProgress) {
/**
* Sets the video duration time into all control components (e.g. seekbar).
+ * @param duration the video duration, in milliseconds
*/
private void setVideoDurationToControls(final int duration) {
binding.playbackEndTime.setText(getTimeString(duration));
@@ -1214,7 +1217,7 @@ public boolean onMenuItemClick(@NonNull final MenuItem menuItem) {
final MediaItemTag.Quality quality = currentMetadata.getMaybeQuality().get();
final List availableStreams = quality.getSortedVideoStreams();
final int selectedStreamIndex = quality.getSelectedVideoStreamIndex();
- if (selectedStreamIndex == menuItemIndex|| availableStreams.size() <= menuItemIndex) {
+ if (selectedStreamIndex == menuItemIndex || availableStreams.size() <= menuItemIndex) {
return true;
}
@@ -1320,7 +1323,7 @@ public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
}
@Override
- public void onCues(@NonNull List cues) {
+ public void onCues(@NonNull final List cues) {
super.onCues(cues);
binding.subtitleView.setCues(cues);
}
@@ -1332,7 +1335,7 @@ private void setupSubtitleView() {
binding.subtitleView.setStyle(captionStyle);
}
- protected abstract void setupSubtitleView(final float captionScale);
+ protected abstract void setupSubtitleView(float captionScale);
//endregion
@@ -1518,7 +1521,7 @@ void onResizeClicked() {
}
@Override
- public void onVideoSizeChanged(@NonNull VideoSize videoSize) {
+ public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
super.onVideoSizeChanged(videoSize);
binding.surfaceView.setAspectRatio(((float) videoSize.width) / videoSize.height);
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java b/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java
index dfcf2e5974e..b4f6d598a43 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java
@@ -28,7 +28,6 @@
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
-import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.notification.NotificationConstants;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ThemeHelper;
From 4979f84e4116d114dca851a31d706bec90a93450 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Sat, 16 Apr 2022 16:01:23 +0200
Subject: [PATCH 038/152] Solve some Sonarlint warnings
---
.../newpipe/local/dialog/PlaylistDialog.java | 37 ++++++++++++++--
.../newpipe/player/PlayQueueActivity.java | 8 ++--
.../org/schabi/newpipe/player/Player.java | 42 +------------------
.../schabi/newpipe/player/PlayerService.java | 17 ++++----
.../gesture/BasePlayerGestureListener.kt | 5 ++-
.../player/notification/NotificationUtil.java | 1 +
.../newpipe/player/ui/MainPlayerUi.java | 13 +++---
.../schabi/newpipe/player/ui/PlayerUi.java | 2 +-
.../newpipe/player/ui/PopupPlayerUi.java | 16 ++++---
.../newpipe/player/ui/VideoPlayerUi.java | 40 +++++++++---------
10 files changed, 86 insertions(+), 95 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java
index f568ef81a03..dec8b05b230 100644
--- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java
+++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java
@@ -9,15 +9,20 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentManager;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
+import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.util.StateSaver;
import java.util.List;
+import java.util.Objects;
import java.util.Queue;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.Disposable;
@@ -131,13 +136,13 @@ protected void setStreamEntities(final List streamEntities) {
* @param context context used for accessing the database
* @param streamEntities used for crating the dialog
* @param onExec execution that should occur after a dialog got created, e.g. showing it
- * @return Disposable
+ * @return the disposable that was created
*/
public static Disposable createCorrespondingDialog(
final Context context,
final List streamEntities,
- final Consumer onExec
- ) {
+ final Consumer onExec) {
+
return new LocalPlaylistManager(NewPipeDatabase.getInstance(context))
.hasPlaylists()
.observeOn(AndroidSchedulers.mainThread())
@@ -147,4 +152,30 @@ public static Disposable createCorrespondingDialog(
: PlaylistCreationDialog.newInstance(streamEntities))
);
}
+
+ /**
+ * Creates a {@link PlaylistAppendDialog} when playlists exists,
+ * otherwise a {@link PlaylistCreationDialog}. If the player's play queue is null or empty, no
+ * dialog will be created.
+ *
+ * @param player the player from which to extract the context and the play queue
+ * @param fragmentManager the fragment manager to use to show the dialog
+ * @return the disposable that was created
+ */
+ public static Disposable showForPlayQueue(
+ final Player player,
+ @NonNull final FragmentManager fragmentManager) {
+
+ final List streamEntities = Stream.of(player.getPlayQueue())
+ .filter(Objects::nonNull)
+ .flatMap(playQueue -> Objects.requireNonNull(playQueue).getStreams().stream())
+ .map(StreamEntity::new)
+ .collect(Collectors.toList());
+ if (streamEntities.isEmpty()) {
+ return Disposable.empty();
+ }
+
+ return PlaylistDialog.createCorrespondingDialog(player.getContext(), streamEntities,
+ dialog -> dialog.show(fragmentManager, "PlaylistDialog"));
+ }
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
index cdba900f9bf..c18a7f4874d 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
@@ -29,6 +29,7 @@
import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
+import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
import org.schabi.newpipe.player.playqueue.PlayQueue;
@@ -53,8 +54,6 @@ public final class PlayQueueActivity extends AppCompatActivity
private Player player;
- private PlayQueueAdapter adapter = null;
-
private boolean serviceBound;
private ServiceConnection serviceConnection;
@@ -128,7 +127,7 @@ public boolean onOptionsItemSelected(final MenuItem item) {
NavigationHelper.openSettings(this);
return true;
case R.id.action_append_playlist:
- player.onAddToPlaylistClicked(getSupportFragmentManager());
+ PlaylistDialog.showForPlayQueue(player, getSupportFragmentManager());
return true;
case R.id.action_playback_speed:
openPlaybackParameterDialog();
@@ -441,10 +440,9 @@ public void onStopTrackingTouch(final SeekBar seekBar) {
@Override
public void onQueueUpdate(@Nullable final PlayQueue queue) {
if (queue == null) {
- adapter = null;
queueControlBinding.playQueue.setAdapter(null);
} else {
- adapter = new PlayQueueAdapter(this, queue);
+ final PlayQueueAdapter adapter = new PlayQueueAdapter(this, queue);
adapter.setSelectedListener(getOnSelectedListener());
queueControlBinding.playQueue.setAdapter(adapter);
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java
index 0755f9b4de0..2d44c644918 100644
--- a/app/src/main/java/org/schabi/newpipe/player/Player.java
+++ b/app/src/main/java/org/schabi/newpipe/player/Player.java
@@ -63,16 +63,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.content.res.AppCompatResources;
-import androidx.appcompat.view.ContextThemeWrapper;
-import androidx.appcompat.widget.AppCompatImageButton;
-import androidx.appcompat.widget.PopupMenu;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.Insets;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.WindowInsetsCompat;
-import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
import com.google.android.exoplayer2.C;
@@ -96,7 +86,6 @@
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.databinding.PlayerBinding;
import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorUtil;
@@ -105,7 +94,6 @@
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
-import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.PlayerService.PlayerType;
import org.schabi.newpipe.player.event.PlayerEventListener;
@@ -116,6 +104,7 @@
import org.schabi.newpipe.player.helper.PlayerDataSource;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.mediaitem.MediaItemTag;
+import org.schabi.newpipe.player.notification.NotificationPlayerUi;
import org.schabi.newpipe.player.playback.MediaSourceManager;
import org.schabi.newpipe.player.playback.PlaybackListener;
import org.schabi.newpipe.player.playback.PlayerMediaSession;
@@ -125,7 +114,6 @@
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver.SourceType;
import org.schabi.newpipe.player.ui.MainPlayerUi;
-import org.schabi.newpipe.player.notification.NotificationPlayerUi;
import org.schabi.newpipe.player.ui.PlayerUi;
import org.schabi.newpipe.player.ui.PlayerUiList;
import org.schabi.newpipe.player.ui.PopupPlayerUi;
@@ -137,10 +125,8 @@
import org.schabi.newpipe.util.SerializedCache;
import org.schabi.newpipe.util.StreamTypeUtil;
-import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import java.util.stream.Collectors;
import java.util.stream.IntStream;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
@@ -1192,32 +1178,6 @@ public void toggleShuffleModeEnabled() {
- /*//////////////////////////////////////////////////////////////////////////
- // Playlist append TODO this does not make sense here
- //////////////////////////////////////////////////////////////////////////*/
- //region Playlist append
-
- public void onAddToPlaylistClicked(@NonNull final FragmentManager fragmentManager) {
- if (DEBUG) {
- Log.d(TAG, "onAddToPlaylistClicked() called");
- }
-
- if (getPlayQueue() != null) {
- PlaylistDialog.createCorrespondingDialog(
- getContext(),
- getPlayQueue()
- .getStreams()
- .stream()
- .map(StreamEntity::new)
- .collect(Collectors.toList()),
- dialog -> dialog.show(fragmentManager, TAG)
- );
- }
- }
- //endregion
-
-
-
/*//////////////////////////////////////////////////////////////////////////
// Mute / Unmute
//////////////////////////////////////////////////////////////////////////*/
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
index b5014eeed09..326b0159006 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
@@ -71,16 +71,17 @@ public int onStartCommand(final Intent intent, final int flags, final int startI
Log.d(TAG, "onStartCommand() called with: intent = [" + intent
+ "], flags = [" + flags + "], startId = [" + startId + "]");
}
- if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
- && player.getPlayQueue() == null) {
- // Player is not working, no need to process media button's action
- return START_NOT_STICKY;
- }
- player.handleIntent(intent);
- if (player.getMediaSessionManager() != null) {
- player.getMediaSessionManager().handleMediaButtonIntent(intent);
+ if (!Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
+ || player.getPlayQueue() != null) {
+ // ^ no need to process media button's action if player is not working
+
+ player.handleIntent(intent);
+ if (player.getMediaSessionManager() != null) {
+ player.getMediaSessionManager().handleMediaButtonIntent(intent);
+ }
}
+
return START_NOT_STICKY;
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt
index bd5d6f1c5f5..b006e73aac7 100644
--- a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt
+++ b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt
@@ -92,7 +92,10 @@ abstract class BasePlayerGestureListener(
return true
}
- return if (onDownNotDoubleTapping(e)) super.onDown(e) else true
+ if (onDownNotDoubleTapping(e)) {
+ return super.onDown(e)
+ }
+ return true
}
/**
diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java
index 28c3b3655ad..2ba754500ff 100644
--- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java
+++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java
@@ -266,6 +266,7 @@ private NotificationCompat.Action getAction(
null);
}
+ // fallthrough
case NotificationConstants.PLAY_PAUSE:
if (player.getCurrentState() == Player.STATE_COMPLETED) {
return getAction(R.drawable.ic_replay,
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
index 3bdda0029ae..eebcc81c464 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
@@ -51,6 +51,7 @@
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.info_list.StreamSegmentAdapter;
import org.schabi.newpipe.ktx.AnimationType;
+import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.event.PlayerServiceEventListener;
import org.schabi.newpipe.player.gesture.BasePlayerGestureListener;
@@ -147,7 +148,8 @@ protected void initListeners() {
binding.addToPlaylistButton.setOnClickListener(v ->
getParentActivity().map(FragmentActivity::getSupportFragmentManager)
- .ifPresent(player::onAddToPlaylistClicked));
+ .ifPresent(fragmentManager ->
+ PlaylistDialog.showForPlayQueue(player, fragmentManager)));
settingsContentObserver = new ContentObserver(new Handler()) {
@Override
@@ -401,6 +403,7 @@ public void onCompleted() {
//////////////////////////////////////////////////////////////////////////*/
//region Controls showing / hiding
+ @Override
protected void showOrHideButtons() {
super.showOrHideButtons();
@Nullable final PlayQueue playQueue = player.getPlayQueue();
@@ -667,12 +670,11 @@ public void closeItemsList() {
}
animate(binding.itemsListPanel, false, DEFAULT_CONTROLS_DURATION,
- AnimationType.SLIDE_AND_ALPHA, 0, () -> {
+ AnimationType.SLIDE_AND_ALPHA, 0, () ->
// Even when queueLayout is GONE it receives touch events
// and ruins normal behavior of the app. This line fixes it
binding.itemsListPanel.setTranslationY(
- -binding.itemsListPanel.getHeight() * 5);
- });
+ -binding.itemsListPanel.getHeight() * 5.0f));
// clear focus, otherwise a white rectangle remains on top of the player
binding.itemsListClose.clearFocus();
@@ -845,8 +847,7 @@ protected void onPlaybackSpeedClicked() {
}
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(), player.getPlaybackPitch(),
- player.getPlaybackSkipSilence(), (speed, pitch, skipSilence)
- -> player.setPlaybackParameters(speed, pitch, skipSilence))
+ player.getPlaybackSkipSilence(), player::setPlaybackParameters)
.show(activity.getSupportFragmentManager(), null);
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
index 49980069035..9ce04bfd5c9 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PlayerUi.java
@@ -31,7 +31,7 @@ public abstract class PlayerUi {
/**
* @param player the player instance that will be usable throughout the lifetime of this UI
*/
- public PlayerUi(@NonNull final Player player) {
+ protected PlayerUi(@NonNull final Player player) {
this.context = player.getContext();
this.player = player;
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
index 43440b87359..8283437f88e 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
@@ -1,5 +1,6 @@
package org.schabi.newpipe.player.ui;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams;
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight;
@@ -140,8 +141,7 @@ protected void setupElementsVisibility() {
binding.segmentsButton.setVisibility(View.GONE);
binding.moreOptionsButton.setVisibility(View.GONE);
binding.topControls.setOrientation(LinearLayout.HORIZONTAL);
- binding.primaryControls.getLayoutParams().width
- = LinearLayout.LayoutParams.WRAP_CONTENT;
+ binding.primaryControls.getLayoutParams().width = WRAP_CONTENT;
binding.secondaryControls.setAlpha(1.0f);
binding.secondaryControls.setVisibility(View.VISIBLE);
binding.secondaryControls.setTranslationY(0);
@@ -193,14 +193,12 @@ public void onBroadcastReceived(final Intent intent) {
updateScreenSize();
changePopupSize(popupLayoutParams.width);
checkPopupPositionBounds();
- } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
- // Use only audio source when screen turns off while popup player is playing
- if (player.isPlaying() || player.isLoading()) {
+ } else if (player.isPlaying() || player.isLoading()) {
+ if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+ // Use only audio source when screen turns off while popup player is playing
player.useVideoSource(false);
- }
- } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
- // Restore video source when screen turns on and user is watching video in popup player
- if (player.isPlaying() || player.isLoading()) {
+ } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
+ // Restore video source when screen turns on and user was watching video in popup
player.useVideoSource(true);
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index 393bf141bf4..5b0be6f648c 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -41,7 +41,6 @@
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper;
-import androidx.appcompat.widget.AppCompatImageButton;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
@@ -142,7 +141,7 @@ public abstract class VideoPlayerUi extends PlayerUi
//////////////////////////////////////////////////////////////////////////*/
//region Constructor, setup, destroy
- public VideoPlayerUi(@NonNull final Player player,
+ protected VideoPlayerUi(@NonNull final Player player,
@NonNull final PlayerBinding playerBinding) {
super(player);
binding = playerBinding;
@@ -912,7 +911,20 @@ public void onShuffleClicked() {
@Override
public void onRepeatModeChanged(@RepeatMode final int repeatMode) {
super.onRepeatModeChanged(repeatMode);
- setRepeatModeButton(binding.repeatButton, repeatMode);
+
+ switch (repeatMode) {
+ case REPEAT_MODE_OFF:
+ binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_off);
+ break;
+ case REPEAT_MODE_ONE:
+ binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_one);
+ break;
+ case REPEAT_MODE_ALL:
+ binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_all);
+ break;
+ default:
+ break; // unreachable
+ }
}
@Override
@@ -927,21 +939,6 @@ public void onMuteUnmuteChanged(final boolean isMuted) {
setMuteButton(isMuted);
}
- private void setRepeatModeButton(final AppCompatImageButton imageButton,
- @RepeatMode final int repeatMode) {
- switch (repeatMode) {
- case REPEAT_MODE_OFF:
- imageButton.setImageResource(R.drawable.exo_controls_repeat_off);
- break;
- case REPEAT_MODE_ONE:
- imageButton.setImageResource(R.drawable.exo_controls_repeat_one);
- break;
- case REPEAT_MODE_ALL:
- imageButton.setImageResource(R.drawable.exo_controls_repeat_all);
- break;
- }
- }
-
private void setMuteButton(final boolean isMuted) {
binding.switchMute.setImageDrawable(AppCompatResources.getDrawable(context, isMuted
? R.drawable.ic_volume_off : R.drawable.ic_volume_up));
@@ -1037,6 +1034,7 @@ private void updateStreamRelatedViews() {
binding.qualityTextView.setVisibility(View.VISIBLE);
binding.surfaceView.setVisibility(View.VISIBLE);
+ // fallthrough
default:
binding.endScreen.setVisibility(View.GONE);
binding.playbackEndTime.setVisibility(View.VISIBLE);
@@ -1426,8 +1424,6 @@ public boolean onLongClick(final View v) {
public boolean onKeyDown(final int keyCode) {
switch (keyCode) {
- default:
- break;
case KeyEvent.KEYCODE_BACK:
if (DeviceUtils.isTv(context) && isControlsVisible()) {
hideControls(0, 0);
@@ -1442,7 +1438,7 @@ public boolean onKeyDown(final int keyCode) {
if ((binding.getRoot().hasFocus() && !binding.playbackControlRoot.hasFocus())
|| isAnyListViewOpen()) {
// do not interfere with focus in playlist and play queue etc.
- return false;
+ break;
}
if (player.getCurrentState() == org.schabi.newpipe.player.Player.STATE_BLOCKED) {
@@ -1458,6 +1454,8 @@ public boolean onKeyDown(final int keyCode) {
return true;
}
break;
+ default:
+ break; // ignore other keys
}
return false;
From 1cf746f7216c173194e17b52abb7bac85763cb23 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Thu, 7 Jul 2022 11:09:07 +0200
Subject: [PATCH 039/152] Fix volume gestures not working anymore
---
.../gesture/MainPlayerGestureListener.kt | 55 ++++++++++++-------
.../newpipe/player/ui/MainPlayerUi.java | 7 ++-
2 files changed, 39 insertions(+), 23 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt
index 81e216006c9..fd7b4ecf03f 100644
--- a/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt
+++ b/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt
@@ -8,11 +8,13 @@ import android.view.View.OnTouchListener
import android.widget.ProgressBar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.view.isVisible
import org.schabi.newpipe.MainActivity
import org.schabi.newpipe.R
import org.schabi.newpipe.ktx.AnimationType
import org.schabi.newpipe.ktx.animate
import org.schabi.newpipe.player.Player
+import org.schabi.newpipe.player.helper.AudioReactor
import org.schabi.newpipe.player.helper.PlayerHelper
import org.schabi.newpipe.player.ui.MainPlayerUi
import kotlin.math.abs
@@ -64,22 +66,27 @@ class MainPlayerGestureListener(
}
private fun onScrollVolume(distanceY: Float) {
+ val bar: ProgressBar = binding.volumeProgressBar
+ val audioReactor: AudioReactor = player.audioReactor
+
// If we just started sliding, change the progress bar to match the system volume
- if (binding.volumeRelativeLayout.visibility != View.VISIBLE) {
- val volumePercent: Float =
- player.audioReactor.volume / player.audioReactor.maxVolume.toFloat()
- binding.volumeProgressBar.progress = (volumePercent * MAX_GESTURE_LENGTH).toInt()
+ if (!binding.volumeRelativeLayout.isVisible) {
+ val volumePercent: Float = audioReactor.volume / audioReactor.maxVolume.toFloat()
+ bar.progress = (volumePercent * bar.max).toInt()
}
+ // Update progress bar
binding.volumeProgressBar.incrementProgressBy(distanceY.toInt())
- val currentProgressPercent: Float =
- binding.volumeProgressBar.progress.toFloat() / MAX_GESTURE_LENGTH
- val currentVolume = (player.audioReactor.maxVolume * currentProgressPercent).toInt()
- player.audioReactor.volume = currentVolume
+
+ // Update volume
+ val currentProgressPercent: Float = bar.progress / bar.max.toFloat()
+ val currentVolume = (audioReactor.maxVolume * currentProgressPercent).toInt()
+ audioReactor.volume = currentVolume
if (DEBUG) {
Log.d(TAG, "onScroll().volumeControl, currentVolume = $currentVolume")
}
+ // Update player center image
binding.volumeImageView.setImageDrawable(
AppCompatResources.getDrawable(
player.context,
@@ -92,12 +99,11 @@ class MainPlayerGestureListener(
)
)
- if (binding.volumeRelativeLayout.visibility != View.VISIBLE) {
+ // Make sure the correct layout is visible
+ if (!binding.volumeRelativeLayout.isVisible) {
binding.volumeRelativeLayout.animate(true, 200, AnimationType.SCALE_AND_ALPHA)
}
- if (binding.brightnessRelativeLayout.visibility == View.VISIBLE) {
- binding.volumeRelativeLayout.visibility = View.GONE
- }
+ binding.brightnessRelativeLayout.isVisible = false
}
private fun onScrollBrightness(distanceY: Float) {
@@ -105,9 +111,13 @@ class MainPlayerGestureListener(
val window = parent.window
val layoutParams = window.attributes
val bar: ProgressBar = binding.brightnessProgressBar
+
+ // Update progress bar
val oldBrightness = layoutParams.screenBrightness
bar.progress = (bar.max * max(0f, min(1f, oldBrightness))).toInt()
bar.incrementProgressBy(distanceY.toInt())
+
+ // Update brightness
val currentProgressPercent = bar.progress.toFloat() / bar.max
layoutParams.screenBrightness = currentProgressPercent
window.attributes = layoutParams
@@ -121,26 +131,32 @@ class MainPlayerGestureListener(
"currentBrightness = " + currentProgressPercent
)
}
+
+ // Update player center image
binding.brightnessImageView.setImageDrawable(
AppCompatResources.getDrawable(
player.context,
- if (currentProgressPercent < 0.25) R.drawable.ic_brightness_low else if (currentProgressPercent < 0.75) R.drawable.ic_brightness_medium else R.drawable.ic_brightness_high
+ when {
+ currentProgressPercent < 0.25 -> R.drawable.ic_brightness_low
+ currentProgressPercent < 0.75 -> R.drawable.ic_brightness_medium
+ else -> R.drawable.ic_brightness_high
+ }
)
)
- if (binding.brightnessRelativeLayout.visibility != View.VISIBLE) {
+
+ // Make sure the correct layout is visible
+ if (!binding.brightnessRelativeLayout.isVisible) {
binding.brightnessRelativeLayout.animate(true, 200, AnimationType.SCALE_AND_ALPHA)
}
- if (binding.volumeRelativeLayout.visibility == View.VISIBLE) {
- binding.volumeRelativeLayout.visibility = View.GONE
- }
+ binding.volumeRelativeLayout.isVisible = false
}
override fun onScrollEnd(event: MotionEvent) {
super.onScrollEnd(event)
- if (binding.volumeRelativeLayout.visibility == View.VISIBLE) {
+ if (binding.volumeRelativeLayout.isVisible) {
binding.volumeRelativeLayout.animate(false, 200, AnimationType.SCALE_AND_ALPHA, 200)
}
- if (binding.brightnessRelativeLayout.visibility == View.VISIBLE) {
+ if (binding.brightnessRelativeLayout.isVisible) {
binding.brightnessRelativeLayout.animate(false, 200, AnimationType.SCALE_AND_ALPHA, 200)
}
}
@@ -210,7 +226,6 @@ class MainPlayerGestureListener(
private val TAG = MainPlayerGestureListener::class.java.simpleName
private val DEBUG = MainActivity.DEBUG
private const val MOVEMENT_THRESHOLD = 40
- const val MAX_GESTURE_LENGTH = 0.75f
private fun getNavigationBarHeight(context: Context): Int {
val resId = context.resources
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
index eebcc81c464..d9f5ea7f43c 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
@@ -520,12 +520,13 @@ protected void setupSubtitleView(final float captionScale) {
public void onLayoutChange(final View view, final int l, final int t, final int r, final int b,
final int ol, final int ot, final int or, final int ob) {
if (l != ol || t != ot || r != or || b != ob) {
- // Use smaller value to be consistent between screen orientations
- // (and to make usage easier)
+ // Use a smaller value to be consistent across screen orientations, and to make usage
+ // easier. Multiply by 3/4 to ensure the user does not need to move the finger up to the
+ // screen border, in order to reach the maximum volume/brightness.
final int width = r - l;
final int height = b - t;
final int min = Math.min(width, height);
- final int maxGestureLength = (int) (min * MainPlayerGestureListener.MAX_GESTURE_LENGTH);
+ final int maxGestureLength = (int) (min * 0.75);
if (DEBUG) {
Log.d(TAG, "maxGestureLength = " + maxGestureLength);
From 9c51fc3adeaac4670da0bead156315b286f8b5c3 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Thu, 7 Jul 2022 11:59:00 +0200
Subject: [PATCH 040/152] Move functions to get Android dimen to ThemeHelper
---
.../gesture/MainPlayerGestureListener.kt | 28 ++++++-------------
.../org/schabi/newpipe/util/ThemeHelper.java | 16 +++++++++++
2 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt
index fd7b4ecf03f..095b3ccdb77 100644
--- a/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt
+++ b/app/src/main/java/org/schabi/newpipe/player/gesture/MainPlayerGestureListener.kt
@@ -1,6 +1,5 @@
package org.schabi.newpipe.player.gesture
-import android.content.Context
import android.util.Log
import android.view.MotionEvent
import android.view.View
@@ -17,6 +16,7 @@ import org.schabi.newpipe.player.Player
import org.schabi.newpipe.player.helper.AudioReactor
import org.schabi.newpipe.player.helper.PlayerHelper
import org.schabi.newpipe.player.ui.MainPlayerUi
+import org.schabi.newpipe.util.ThemeHelper.getAndroidDimenPx
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -172,9 +172,13 @@ class MainPlayerGestureListener(
return false
}
- val isTouchingStatusBar: Boolean = initialEvent.y < getStatusBarHeight(player.context)
- val isTouchingNavigationBar: Boolean =
- initialEvent.y > (binding.root.height - getNavigationBarHeight(player.context))
+ // Calculate heights of status and navigation bars
+ val statusBarHeight = getAndroidDimenPx(player.context, "status_bar_height")
+ val navigationBarHeight = getAndroidDimenPx(player.context, "navigation_bar_height")
+
+ // Do not handle this event if initially it started from status or navigation bars
+ val isTouchingStatusBar = initialEvent.y < statusBarHeight
+ val isTouchingNavigationBar = initialEvent.y > (binding.root.height - navigationBarHeight)
if (isTouchingStatusBar || isTouchingNavigationBar) {
return false
}
@@ -226,21 +230,5 @@ class MainPlayerGestureListener(
private val TAG = MainPlayerGestureListener::class.java.simpleName
private val DEBUG = MainActivity.DEBUG
private const val MOVEMENT_THRESHOLD = 40
-
- private fun getNavigationBarHeight(context: Context): Int {
- val resId = context.resources
- .getIdentifier("navigation_bar_height", "dimen", "android")
- return if (resId > 0) {
- context.resources.getDimensionPixelSize(resId)
- } else 0
- }
-
- private fun getStatusBarHeight(context: Context): Int {
- val resId = context.resources
- .getIdentifier("status_bar_height", "dimen", "android")
- return if (resId > 0) {
- context.resources.getDimensionPixelSize(resId)
- } else 0
- }
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java
index b8e3a86ed38..389af80eefe 100644
--- a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java
@@ -244,6 +244,22 @@ public static Drawable resolveDrawable(@NonNull final Context context,
return AppCompatResources.getDrawable(context, typedValue.resourceId);
}
+ /**
+ * Gets a runtime dimen from the {@code android} package. Should be used for dimens for which
+ * normal accessing with {@code R.dimen.} is not available.
+ *
+ * @param context context
+ * @param name dimen resource name (e.g. navigation_bar_height)
+ * @return the obtained dimension, in pixels, or 0 if the resource could not be resolved
+ */
+ public static int getAndroidDimenPx(@NonNull final Context context, final String name) {
+ final int resId = context.getResources().getIdentifier(name, "dimen", "android");
+ if (resId <= 0) {
+ return 0;
+ }
+ return context.getResources().getDimensionPixelSize(resId);
+ }
+
private static String getSelectedThemeKey(final Context context) {
final String themeKey = context.getString(R.string.theme_key);
final String defaultTheme = context.getResources().getString(R.string.default_theme_value);
From 3692858a3d10fb33d0386149d630264ca93eca23 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Fri, 8 Jul 2022 22:33:35 +0200
Subject: [PATCH 041/152] Move popup layout param to PopupPlayerUi
---
.../gesture/PopupPlayerGestureListener.kt | 65 ++++++-----
.../newpipe/player/helper/PlayerHelper.java | 103 +---------------
.../newpipe/player/ui/PopupPlayerUi.java | 110 +++++++++++++++++-
3 files changed, 141 insertions(+), 137 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt
index b8c1bc54c5f..bda6ee8d10f 100644
--- a/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt
+++ b/app/src/main/java/org/schabi/newpipe/player/gesture/PopupPlayerGestureListener.kt
@@ -7,7 +7,6 @@ import android.view.ViewConfiguration
import org.schabi.newpipe.MainActivity
import org.schabi.newpipe.ktx.AnimationType
import org.schabi.newpipe.ktx.animate
-import org.schabi.newpipe.player.helper.PlayerHelper
import org.schabi.newpipe.player.ui.PopupPlayerUi
import kotlin.math.abs
import kotlin.math.hypot
@@ -87,7 +86,7 @@ class PopupPlayerGestureListener(
player.changeState(player.currentState)
}
if (!playerUi.isPopupClosing) {
- PlayerHelper.savePopupPositionAndSizeToPrefs(playerUi)
+ playerUi.savePopupPositionAndSizeToPrefs()
}
}
@@ -106,40 +105,42 @@ class PopupPlayerGestureListener(
}
private fun handleMultiDrag(event: MotionEvent): Boolean {
- if (initPointerDistance != -1.0 && event.pointerCount == 2) {
- // get the movements of the fingers
- val firstPointerMove = hypot(
- event.getX(0) - initFirstPointerX.toDouble(),
- event.getY(0) - initFirstPointerY.toDouble()
- )
- val secPointerMove = hypot(
- event.getX(1) - initSecPointerX.toDouble(),
- event.getY(1) - initSecPointerY.toDouble()
- )
+ if (initPointerDistance == -1.0 || event.pointerCount != 2) {
+ return false
+ }
- // minimum threshold beyond which pinch gesture will work
- val minimumMove = ViewConfiguration.get(player.context).scaledTouchSlop
+ // get the movements of the fingers
+ val firstPointerMove = hypot(
+ event.getX(0) - initFirstPointerX.toDouble(),
+ event.getY(0) - initFirstPointerY.toDouble()
+ )
+ val secPointerMove = hypot(
+ event.getX(1) - initSecPointerX.toDouble(),
+ event.getY(1) - initSecPointerY.toDouble()
+ )
+
+ // minimum threshold beyond which pinch gesture will work
+ val minimumMove = ViewConfiguration.get(player.context).scaledTouchSlop
+ if (max(firstPointerMove, secPointerMove) <= minimumMove) {
+ return false
+ }
- if (max(firstPointerMove, secPointerMove) > minimumMove) {
- // calculate current distance between the pointers
- val currentPointerDistance = hypot(
- event.getX(0) - event.getX(1).toDouble(),
- event.getY(0) - event.getY(1).toDouble()
- )
+ // calculate current distance between the pointers
+ val currentPointerDistance = hypot(
+ event.getX(0) - event.getX(1).toDouble(),
+ event.getY(0) - event.getY(1).toDouble()
+ )
- val popupWidth = playerUi.popupLayoutParams.width.toDouble()
- // change co-ordinates of popup so the center stays at the same position
- val newWidth = popupWidth * currentPointerDistance / initPointerDistance
- initPointerDistance = currentPointerDistance
- playerUi.popupLayoutParams.x += ((popupWidth - newWidth) / 2.0).toInt()
+ val popupWidth = playerUi.popupLayoutParams.width.toDouble()
+ // change co-ordinates of popup so the center stays at the same position
+ val newWidth = popupWidth * currentPointerDistance / initPointerDistance
+ initPointerDistance = currentPointerDistance
+ playerUi.popupLayoutParams.x += ((popupWidth - newWidth) / 2.0).toInt()
- playerUi.checkPopupPositionBounds()
- playerUi.updateScreenSize()
- playerUi.changePopupSize(min(playerUi.screenWidth.toDouble(), newWidth).toInt())
- return true
- }
- }
- return false
+ playerUi.checkPopupPositionBounds()
+ playerUi.updateScreenSize()
+ playerUi.changePopupSize(min(playerUi.screenWidth.toDouble(), newWidth).toInt())
+ return true
}
private fun onPopupResizingStart() {
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 ec4cf8602a5..d1d29dd71a1 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
@@ -10,19 +10,13 @@
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE;
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP;
-import static org.schabi.newpipe.player.ui.PopupPlayerUi.IDLE_WINDOW_FLAGS;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.graphics.PixelFormat;
-import android.os.Build;
import android.provider.Settings;
-import android.view.Gravity;
-import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.accessibility.CaptioningManager;
import androidx.annotation.IntDef;
@@ -49,12 +43,11 @@
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
import org.schabi.newpipe.extractor.utils.Utils;
-import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.Player;
+import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
-import org.schabi.newpipe.player.ui.PopupPlayerUi;
import org.schabi.newpipe.util.ListHelper;
import java.lang.annotation.Retention;
@@ -77,20 +70,6 @@ public final class PlayerHelper {
private static final NumberFormat SPEED_FORMATTER = new DecimalFormat("0.##x");
private static final NumberFormat PITCH_FORMATTER = new DecimalFormat("##%");
- /**
- * Maximum opacity allowed for Android 12 and higher to allow touches on other apps when using
- * NewPipe's popup player.
- *
- *
- * This value is hardcoded instead of being get dynamically with the method linked of the
- * constant documentation below, because it is not static and popup player layout parameters
- * are generated with static methods.
- *
- *
- * @see WindowManager.LayoutParams#FLAG_NOT_TOUCHABLE
- */
- private static final float MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER = 0.8f;
-
@Retention(SOURCE)
@IntDef({AUTOPLAY_TYPE_ALWAYS, AUTOPLAY_TYPE_WIFI,
AUTOPLAY_TYPE_NEVER})
@@ -525,90 +504,10 @@ public static void savePlaybackParametersToPrefs(final Player player,
.apply();
}
- /**
- * @param playerUi {@code screenWidth} and {@code screenHeight} must have been initialized
- * @return the popup starting layout params
- */
- @SuppressLint("RtlHardcoded")
- public static WindowManager.LayoutParams retrievePopupLayoutParamsFromPrefs(
- final PopupPlayerUi playerUi) {
- final SharedPreferences prefs = playerUi.getPlayer().getPrefs();
- final Context context = playerUi.getPlayer().getContext();
-
- final boolean popupRememberSizeAndPos = prefs.getBoolean(
- context.getString(R.string.popup_remember_size_pos_key), true);
- final float defaultSize = context.getResources().getDimension(R.dimen.popup_default_width);
- final float popupWidth = popupRememberSizeAndPos
- ? prefs.getFloat(context.getString(R.string.popup_saved_width_key), defaultSize)
- : defaultSize;
- final float popupHeight = getMinimumVideoHeight(popupWidth);
-
- final WindowManager.LayoutParams popupLayoutParams = new WindowManager.LayoutParams(
- (int) popupWidth, (int) popupHeight,
- popupLayoutParamType(),
- IDLE_WINDOW_FLAGS,
- PixelFormat.TRANSLUCENT);
- popupLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-
- final int centerX = (int) (playerUi.getScreenWidth() / 2f - popupWidth / 2f);
- final int centerY = (int) (playerUi.getScreenHeight() / 2f - popupHeight / 2f);
- popupLayoutParams.x = popupRememberSizeAndPos
- ? prefs.getInt(context.getString(R.string.popup_saved_x_key), centerX) : centerX;
- popupLayoutParams.y = popupRememberSizeAndPos
- ? prefs.getInt(context.getString(R.string.popup_saved_y_key), centerY) : centerY;
-
- return popupLayoutParams;
- }
-
- public static void savePopupPositionAndSizeToPrefs(final PopupPlayerUi playerUi) {
- if (playerUi.getPopupLayoutParams() != null) {
- final Context context = playerUi.getPlayer().getContext();
- playerUi.getPlayer().getPrefs().edit()
- .putFloat(context.getString(R.string.popup_saved_width_key),
- playerUi.getPopupLayoutParams().width)
- .putInt(context.getString(R.string.popup_saved_x_key),
- playerUi.getPopupLayoutParams().x)
- .putInt(context.getString(R.string.popup_saved_y_key),
- playerUi.getPopupLayoutParams().y)
- .apply();
- }
- }
-
public static float getMinimumVideoHeight(final float width) {
return width / (16.0f / 9.0f); // Respect the 16:9 ratio that most videos have
}
- @SuppressLint("RtlHardcoded")
- public static WindowManager.LayoutParams buildCloseOverlayLayoutParams() {
- final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-
- final WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
- popupLayoutParamType(),
- flags,
- PixelFormat.TRANSLUCENT);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- // Setting maximum opacity allowed for touch events to other apps for Android 12 and
- // higher to prevent non interaction when using other apps with the popup player
- closeOverlayLayoutParams.alpha = MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER;
- }
-
- closeOverlayLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- closeOverlayLayoutParams.softInputMode =
- WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- return closeOverlayLayoutParams;
- }
-
- public static int popupLayoutParamType() {
- return Build.VERSION.SDK_INT < Build.VERSION_CODES.O
- ? WindowManager.LayoutParams.TYPE_PHONE
- : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- }
-
public static int retrieveSeekDurationFromPreferences(final Player player) {
return Integer.parseInt(Objects.requireNonNull(player.getPrefs().getString(
player.getContext().getString(R.string.seek_duration_key),
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
index 8283437f88e..46396a84036 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
@@ -2,21 +2,25 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static org.schabi.newpipe.MainActivity.DEBUG;
-import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams;
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight;
-import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
+import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.PixelFormat;
+import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AnticipateInterpolator;
import android.widget.LinearLayout;
@@ -38,6 +42,20 @@
public final class PopupPlayerUi extends VideoPlayerUi {
private static final String TAG = PopupPlayerUi.class.getSimpleName();
+ /**
+ * Maximum opacity allowed for Android 12 and higher to allow touches on other apps when using
+ * NewPipe's popup player.
+ *
+ *
+ * This value is hardcoded instead of being get dynamically with the method linked of the
+ * constant documentation below, because it is not static and popup player layout parameters
+ * are generated with static methods.
+ *
+ *
+ * @see WindowManager.LayoutParams#FLAG_NOT_TOUCHABLE
+ */
+ private static final float MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER = 0.8f;
+
/*//////////////////////////////////////////////////////////////////////////
// Popup player
//////////////////////////////////////////////////////////////////////////*/
@@ -98,7 +116,7 @@ private void initPopup() {
updateScreenSize();
- popupLayoutParams = retrievePopupLayoutParamsFromPrefs(this);
+ popupLayoutParams = retrievePopupLayoutParamsFromPrefs();
binding.surfaceView.setHeights(popupLayoutParams.height, popupLayoutParams.height);
checkPopupPositionBounds();
@@ -446,6 +464,92 @@ public boolean isInsideClosingRadius(@NonNull final MotionEvent popupMotionEvent
//endregion
+ /*//////////////////////////////////////////////////////////////////////////
+ // Popup & closing overlay layout params + saving popup position and size
+ //////////////////////////////////////////////////////////////////////////*/
+ //region Popup & closing overlay layout params + saving popup position and size
+
+ /**
+ * {@code screenWidth} and {@code screenHeight} must have been initialized.
+ * @return the popup starting layout params
+ */
+ @SuppressLint("RtlHardcoded")
+ public WindowManager.LayoutParams retrievePopupLayoutParamsFromPrefs() {
+ final SharedPreferences prefs = getPlayer().getPrefs();
+ final Context context = getPlayer().getContext();
+
+ final boolean popupRememberSizeAndPos = prefs.getBoolean(
+ context.getString(R.string.popup_remember_size_pos_key), true);
+ final float defaultSize = context.getResources().getDimension(R.dimen.popup_default_width);
+ final float popupWidth = popupRememberSizeAndPos
+ ? prefs.getFloat(context.getString(R.string.popup_saved_width_key), defaultSize)
+ : defaultSize;
+ final float popupHeight = getMinimumVideoHeight(popupWidth);
+
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ (int) popupWidth, (int) popupHeight,
+ popupLayoutParamType(),
+ IDLE_WINDOW_FLAGS,
+ PixelFormat.TRANSLUCENT);
+ params.gravity = Gravity.LEFT | Gravity.TOP;
+ params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+
+ final int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
+ final int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
+ params.x = popupRememberSizeAndPos
+ ? prefs.getInt(context.getString(R.string.popup_saved_x_key), centerX) : centerX;
+ params.y = popupRememberSizeAndPos
+ ? prefs.getInt(context.getString(R.string.popup_saved_y_key), centerY) : centerY;
+
+ return params;
+ }
+
+ public void savePopupPositionAndSizeToPrefs() {
+ if (getPopupLayoutParams() != null) {
+ final Context context = getPlayer().getContext();
+ getPlayer().getPrefs().edit()
+ .putFloat(context.getString(R.string.popup_saved_width_key),
+ popupLayoutParams.width)
+ .putInt(context.getString(R.string.popup_saved_x_key),
+ popupLayoutParams.x)
+ .putInt(context.getString(R.string.popup_saved_y_key),
+ popupLayoutParams.y)
+ .apply();
+ }
+ }
+
+ @SuppressLint("RtlHardcoded")
+ public static WindowManager.LayoutParams buildCloseOverlayLayoutParams() {
+ final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+
+ final WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
+ popupLayoutParamType(),
+ flags,
+ PixelFormat.TRANSLUCENT);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // Setting maximum opacity allowed for touch events to other apps for Android 12 and
+ // higher to prevent non interaction when using other apps with the popup player
+ closeOverlayLayoutParams.alpha = MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER;
+ }
+
+ closeOverlayLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ closeOverlayLayoutParams.softInputMode =
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+ return closeOverlayLayoutParams;
+ }
+
+ public static int popupLayoutParamType() {
+ return Build.VERSION.SDK_INT < Build.VERSION_CODES.O
+ ? WindowManager.LayoutParams.TYPE_PHONE
+ : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ }
+ //endregion
+
+
/*//////////////////////////////////////////////////////////////////////////
// Getters
//////////////////////////////////////////////////////////////////////////*/
From 61c1da144e4b0a824d4816d9ecad6a59b53d9cf3 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Sat, 9 Jul 2022 17:17:30 +0200
Subject: [PATCH 042/152] Some refactorings after review comments
---
.../fragments/detail/VideoDetailFragment.java | 11 +++--
.../newpipe/local/dialog/PlaylistDialog.java | 2 +-
.../schabi/newpipe/player/PlayerService.java | 23 ++++-----
.../newpipe/player/ui/MainPlayerUi.java | 47 ++++++++-----------
.../newpipe/player/ui/VideoPlayerUi.java | 19 +++-----
5 files changed, 42 insertions(+), 60 deletions(-)
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 8ffff2f9ef1..5dc6bb436de 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
@@ -1311,11 +1311,12 @@ private void addVideoPlayerView() {
setHeightThumbnail();
// Prevent from re-adding a view multiple times
- new Handler().post(() -> player.UIs().get(MainPlayerUi.class).ifPresent(playerUi -> {
- playerUi.removeViewFromParent();
- binding.playerPlaceholder.addView(playerUi.getBinding().getRoot());
- playerUi.setupVideoSurfaceIfNeeded();
- }));
+ new Handler(Looper.getMainLooper()).post(() ->
+ player.UIs().get(MainPlayerUi.class).ifPresent(playerUi -> {
+ playerUi.removeViewFromParent();
+ binding.playerPlaceholder.addView(playerUi.getBinding().getRoot());
+ playerUi.setupVideoSurfaceIfNeeded();
+ }));
}
private void removeVideoPlayerView() {
diff --git a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java
index dec8b05b230..612c3818187 100644
--- a/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java
+++ b/app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java
@@ -168,7 +168,7 @@ public static Disposable showForPlayQueue(
final List streamEntities = Stream.of(player.getPlayQueue())
.filter(Objects::nonNull)
- .flatMap(playQueue -> Objects.requireNonNull(playQueue).getStreams().stream())
+ .flatMap(playQueue -> playQueue.getStreams().stream())
.map(StreamEntity::new)
.collect(Collectors.toList());
if (streamEntities.isEmpty()) {
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
index 326b0159006..14e8262d6fb 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
@@ -33,8 +33,6 @@
/**
* One service for all players.
- *
- * @author mauriciocolli
*/
public final class PlayerService extends Service {
private static final String TAG = PlayerService.class.getSimpleName();
@@ -72,14 +70,16 @@ public int onStartCommand(final Intent intent, final int flags, final int startI
+ "], flags = [" + flags + "], startId = [" + startId + "]");
}
- if (!Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
- || player.getPlayQueue() != null) {
- // ^ no need to process media button's action if player is not working
+ if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
+ && player.getPlayQueue() == null) {
+ // No need to process media button's actions if the player is not working, otherwise the
+ // player service would strangely start with nothing to play
+ return START_NOT_STICKY;
+ }
- player.handleIntent(intent);
- if (player.getMediaSessionManager() != null) {
- player.getMediaSessionManager().handleMediaButtonIntent(intent);
- }
+ player.handleIntent(intent);
+ if (player.getMediaSessionManager() != null) {
+ player.getMediaSessionManager().handleMediaButtonIntent(intent);
}
return START_NOT_STICKY;
@@ -97,11 +97,6 @@ public void stopForImmediateReusing() {
// We can't just pause the player here because it will make transition
// from one stream to a new stream not smooth
player.smoothStopForImmediateReusing();
-
- // Notification shows information about old stream but if a user selects
- // a stream from backStack it's not actual anymore
- // So we should hide the notification at all.
- // When autoplay enabled such notification flashing is annoying so skip this case
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
index d9f5ea7f43c..278e4f1fffa 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
@@ -75,6 +75,11 @@
public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutChangeListener {
private static final String TAG = MainPlayerUi.class.getSimpleName();
+ // see the Javadoc of calculateMaxEndScreenThumbnailHeight for information
+ private static final int DETAIL_ROOT_MINIMUM_HEIGHT = 85; // dp
+ private static final int DETAIL_TITLE_TEXT_SIZE_TV = 16; // sp
+ private static final int DETAIL_TITLE_TEXT_SIZE_TABLET = 15; // sp
+
private boolean isFullscreen = false;
private boolean isVerticalVideo = false;
private boolean fragmentIsVisible = false;
@@ -262,13 +267,8 @@ protected void setupElementsVisibility() {
binding.topControls.setClickable(true);
binding.topControls.setFocusable(true);
- if (isFullscreen) {
- binding.titleTextView.setVisibility(View.VISIBLE);
- binding.channelTextView.setVisibility(View.VISIBLE);
- } else {
- binding.titleTextView.setVisibility(View.GONE);
- binding.channelTextView.setVisibility(View.GONE);
- }
+ binding.titleTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
+ binding.channelTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
}
@Override
@@ -450,13 +450,12 @@ public void hideSystemUIIfNeeded() {
* The calculating follows these rules:
*
* -
- * Show at least stream title and content creator on TVs and tablets
- * when in landscape (always the case for TVs) and not in fullscreen mode.
- * This requires to have at least
85dp
free space for {@link R.id.detail_root}
- * and additional space for the stream title text size
- * ({@link R.id.detail_title_root_layout}).
- * The text size is 15sp
on tablets and 16sp
on TVs,
- * see {@link R.id.titleTextView}.
+ * Show at least stream title and content creator on TVs and tablets when in landscape
+ * (always the case for TVs) and not in fullscreen mode. This requires to have at least
+ * {@link #DETAIL_ROOT_MINIMUM_HEIGHT} free space for {@link R.id.detail_root} and
+ * additional space for the stream title text size ({@link R.id.detail_title_root_layout}).
+ * The text size is {@link #DETAIL_TITLE_TEXT_SIZE_TABLET} on tablets and
+ * {@link #DETAIL_TITLE_TEXT_SIZE_TV} on TVs, see {@link R.id.titleTextView}.
*
* -
* Otherwise, the max thumbnail height is the screen height.
@@ -472,12 +471,12 @@ protected float calculateMaxEndScreenThumbnailHeight(@NonNull final Bitmap bitma
final int screenHeight = context.getResources().getDisplayMetrics().heightPixels;
if (DeviceUtils.isTv(context) && !isFullscreen()) {
- final int videoInfoHeight =
- DeviceUtils.dpToPx(85, context) + DeviceUtils.spToPx(16, context);
+ final int videoInfoHeight = DeviceUtils.dpToPx(DETAIL_ROOT_MINIMUM_HEIGHT, context)
+ + DeviceUtils.spToPx(DETAIL_TITLE_TEXT_SIZE_TV, context);
return Math.min(bitmap.getHeight(), screenHeight - videoInfoHeight);
} else if (DeviceUtils.isTablet(context) && isLandscape() && !isFullscreen()) {
- final int videoInfoHeight =
- DeviceUtils.dpToPx(85, context) + DeviceUtils.spToPx(15, context);
+ final int videoInfoHeight = DeviceUtils.dpToPx(DETAIL_ROOT_MINIMUM_HEIGHT, context)
+ + DeviceUtils.spToPx(DETAIL_TITLE_TEXT_SIZE_TABLET, context);
return Math.min(bitmap.getHeight(), screenHeight - videoInfoHeight);
} else { // fullscreen player: max height is the device height
return Math.min(bitmap.getHeight(), screenHeight);
@@ -933,15 +932,9 @@ public void toggleFullscreen() {
}
fragmentListener.onFullscreenStateChanged(isFullscreen);
- if (isFullscreen) {
- binding.titleTextView.setVisibility(View.VISIBLE);
- binding.channelTextView.setVisibility(View.VISIBLE);
- binding.playerCloseButton.setVisibility(View.GONE);
- } else {
- binding.titleTextView.setVisibility(View.GONE);
- binding.channelTextView.setVisibility(View.GONE);
- binding.playerCloseButton.setVisibility(View.VISIBLE);
- }
+ binding.titleTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
+ binding.channelTextView.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
+ binding.playerCloseButton.setVisibility(isFullscreen ? View.GONE : View.VISIBLE);
setupScreenRotationButton();
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index 5b0be6f648c..4d106511251 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -1,7 +1,6 @@
package org.schabi.newpipe.player.ui;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
-import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
@@ -912,18 +911,12 @@ public void onShuffleClicked() {
public void onRepeatModeChanged(@RepeatMode final int repeatMode) {
super.onRepeatModeChanged(repeatMode);
- switch (repeatMode) {
- case REPEAT_MODE_OFF:
- binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_off);
- break;
- case REPEAT_MODE_ONE:
- binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_one);
- break;
- case REPEAT_MODE_ALL:
- binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_all);
- break;
- default:
- break; // unreachable
+ if (repeatMode == REPEAT_MODE_ALL) {
+ binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_all);
+ } else if (repeatMode == REPEAT_MODE_ONE) {
+ binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_one);
+ } else /* repeatMode == REPEAT_MODE_OFF */ {
+ binding.repeatButton.setImageResource(R.drawable.exo_controls_repeat_off);
}
}
From c03eac1dc99e9e61b863b5984444407dc8ee13a2 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Sat, 9 Jul 2022 17:50:12 +0200
Subject: [PATCH 043/152] Some SonarLint refactors
---
.../player/gesture/BasePlayerGestureListener.kt | 3 ++-
.../newpipe/player/gesture/DoubleTapListener.kt | 6 +++---
.../org/schabi/newpipe/player/ui/MainPlayerUi.java | 11 +++++------
.../org/schabi/newpipe/player/ui/PopupPlayerUi.java | 3 +--
.../org/schabi/newpipe/player/ui/VideoPlayerUi.java | 3 ++-
5 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt
index b006e73aac7..555c34f9632 100644
--- a/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt
+++ b/app/src/main/java/org/schabi/newpipe/player/gesture/BasePlayerGestureListener.kt
@@ -1,6 +1,7 @@
package org.schabi.newpipe.player.gesture
import android.os.Handler
+import android.os.Looper
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
@@ -130,7 +131,7 @@ abstract class BasePlayerGestureListener(
}
private var doubleTapDelay = DOUBLE_TAP_DELAY
- private val doubleTapHandler: Handler = Handler()
+ private val doubleTapHandler: Handler = Handler(Looper.getMainLooper())
private val doubleTapRunnable = Runnable {
if (DEBUG)
Log.d(TAG, "doubleTapRunnable called")
diff --git a/app/src/main/java/org/schabi/newpipe/player/gesture/DoubleTapListener.kt b/app/src/main/java/org/schabi/newpipe/player/gesture/DoubleTapListener.kt
index 1a0b141e648..fc026abd9b2 100644
--- a/app/src/main/java/org/schabi/newpipe/player/gesture/DoubleTapListener.kt
+++ b/app/src/main/java/org/schabi/newpipe/player/gesture/DoubleTapListener.kt
@@ -1,7 +1,7 @@
package org.schabi.newpipe.player.gesture
interface DoubleTapListener {
- fun onDoubleTapStarted(portion: DisplayPortion) {}
- fun onDoubleTapProgressDown(portion: DisplayPortion) {}
- fun onDoubleTapFinished() {}
+ fun onDoubleTapStarted(portion: DisplayPortion)
+ fun onDoubleTapProgressDown(portion: DisplayPortion)
+ fun onDoubleTapFinished()
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
index 278e4f1fffa..52a486addc6 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
@@ -1,5 +1,6 @@
package org.schabi.newpipe.player.ui;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
@@ -21,6 +22,7 @@
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Handler;
+import android.os.Looper;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -156,7 +158,7 @@ protected void initListeners() {
.ifPresent(fragmentManager ->
PlaylistDialog.showForPlayQueue(player, fragmentManager)));
- settingsContentObserver = new ContentObserver(new Handler()) {
+ settingsContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(final boolean selfChange) {
setupScreenRotationButton();
@@ -237,8 +239,7 @@ public void smoothStopForImmediateReusing() {
private void initVideoPlayer() {
// restore last resize mode
setResizeMode(PlayerHelper.retrieveResizeModeFromPrefs(player));
- binding.getRoot().setLayoutParams(new FrameLayout.LayoutParams(
- FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
+ binding.getRoot().setLayoutParams(new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
@Override
@@ -253,8 +254,7 @@ protected void setupElementsVisibility() {
binding.getRoot().findViewById(R.id.metadataView).setVisibility(View.VISIBLE);
binding.moreOptionsButton.setVisibility(View.VISIBLE);
binding.topControls.setOrientation(LinearLayout.VERTICAL);
- binding.primaryControls.getLayoutParams().width
- = LinearLayout.LayoutParams.MATCH_PARENT;
+ binding.primaryControls.getLayoutParams().width = MATCH_PARENT;
binding.secondaryControls.setVisibility(View.INVISIBLE);
binding.moreOptionsButton.setImageDrawable(AppCompatResources.getDrawable(context,
R.drawable.ic_expand_more));
@@ -459,7 +459,6 @@ public void hideSystemUIIfNeeded() {
*
* -
* Otherwise, the max thumbnail height is the screen height.
- * TODO investigate why this is done on popup player, too
*
*
*
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
index 46396a84036..bb810f86bc1 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java
@@ -287,8 +287,7 @@ public void changePopupSize(final int width) {
}
final float minimumWidth = context.getResources().getDimension(R.dimen.popup_minimum_width);
- final int actualWidth = (int) (width > screenWidth ? screenWidth
- : (width < minimumWidth ? minimumWidth : width));
+ final int actualWidth = Math.min((int) Math.max(width, minimumWidth), screenWidth);
final int actualHeight = (int) getMinimumVideoHeight(width);
if (DEBUG) {
Log.d(TAG, "updatePopupSize() updated values:"
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index 4d106511251..bdb327df186 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -25,6 +25,7 @@
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
@@ -103,7 +104,7 @@ public abstract class VideoPlayerUi extends PlayerUi
//////////////////////////////////////////////////////////////////////////*/
protected PlayerBinding binding;
- private final Handler controlsVisibilityHandler = new Handler();
+ private final Handler controlsVisibilityHandler = new Handler(Looper.getMainLooper());
@Nullable private SurfaceHolderCallback surfaceHolderCallback;
boolean surfaceIsSetup = false;
@Nullable private Bitmap thumbnail = null;
From 4443c908cb203e97df5e2624c34681aea2cfe129 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Sat, 9 Jul 2022 17:58:03 +0200
Subject: [PATCH 044/152] Fix SonarLint java:S5320, restrict broadcasts to app
package
---
.../java/org/schabi/newpipe/player/ui/VideoPlayerUi.java | 5 ++++-
.../settings/custom/NotificationActionsPreference.java | 5 ++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index bdb327df186..d38c8cfe4bd 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -57,6 +57,7 @@
import com.google.android.exoplayer2.ui.CaptionStyleCompat;
import com.google.android.exoplayer2.video.VideoSize;
+import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.PlayerBinding;
import org.schabi.newpipe.extractor.MediaFormat;
@@ -1372,7 +1373,9 @@ public void onClick(final View v) {
} else if (v.getId() == binding.switchMute.getId()) {
player.toggleMute();
} else if (v.getId() == binding.playerCloseButton.getId()) {
- context.sendBroadcast(new Intent(VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER));
+ // set package to this app's package to prevent the intent from being seen outside
+ context.sendBroadcast(new Intent(VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER)
+ .setPackage(App.PACKAGE_NAME));
} else if (v.getId() == binding.playbackSpeed.getId()) {
onPlaybackSpeedClicked();
} else if (v.getId() == binding.qualityTextView.getId()) {
diff --git a/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java b/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java
index b4f6d598a43..03b5a5a9507 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/custom/NotificationActionsPreference.java
@@ -25,6 +25,7 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
+import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
@@ -62,7 +63,9 @@ public void onBindViewHolder(@NonNull final PreferenceViewHolder holder) {
public void onDetached() {
super.onDetached();
saveChanges();
- getContext().sendBroadcast(new Intent(ACTION_RECREATE_NOTIFICATION));
+ // set package to this app's package to prevent the intent from being seen outside
+ getContext().sendBroadcast(new Intent(ACTION_RECREATE_NOTIFICATION)
+ .setPackage(App.PACKAGE_NAME));
}
From 8187a3bc04704e8b1cc380ccbf0c0274a4514494 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Sun, 10 Jul 2022 23:05:37 +0200
Subject: [PATCH 045/152] Move PlayerType into its own class and add
documentation
Also replace some `isPlayerOpen` with direct `playerType == null` checks.
---
.../org/schabi/newpipe/RouterActivity.java | 6 ++--
.../fragments/detail/VideoDetailFragment.java | 2 +-
.../list/channel/ChannelFragment.java | 2 +-
.../list/playlist/PlaylistFragment.java | 2 +-
.../local/playlist/LocalPlaylistFragment.java | 2 +-
.../org/schabi/newpipe/player/Player.java | 4 +--
.../schabi/newpipe/player/PlayerService.java | 5 ---
.../org/schabi/newpipe/player/PlayerType.java | 32 +++++++++++++++++++
.../newpipe/player/helper/PlayerHelper.java | 9 ------
.../newpipe/player/helper/PlayerHolder.java | 7 ++--
.../schabi/newpipe/util/NavigationHelper.java | 28 ++++++++--------
11 files changed, 58 insertions(+), 41 deletions(-)
create mode 100644 app/src/main/java/org/schabi/newpipe/player/PlayerType.java
diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java
index 1194b406850..d055da1e8f6 100644
--- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java
@@ -60,7 +60,7 @@
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
-import org.schabi.newpipe.player.PlayerService;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
@@ -630,8 +630,8 @@ private boolean canHandleChoiceLikeShowInfo(final String selectedChoiceKey) {
}
// ...the player is not running or in normal Video-mode/type
- final PlayerService.PlayerType playerType = PlayerHolder.getInstance().getType();
- return playerType == null || playerType == PlayerService.PlayerType.MAIN;
+ final PlayerType playerType = PlayerHolder.getInstance().getType();
+ return playerType == null || playerType == PlayerType.MAIN;
}
private void openAddToPlaylistDialog() {
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 5dc6bb436de..92e7e4f160b 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
@@ -90,7 +90,7 @@
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.PlayerService;
-import org.schabi.newpipe.player.PlayerService.PlayerType;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.event.OnKeyDownListener;
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
import org.schabi.newpipe.player.helper.PlayerHelper;
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
index aabd64744c0..e44048473aa 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
@@ -43,7 +43,7 @@
import org.schabi.newpipe.ktx.AnimationType;
import org.schabi.newpipe.local.subscription.SubscriptionManager;
import org.schabi.newpipe.local.feed.notifications.NotificationHelper;
-import org.schabi.newpipe.player.PlayerService.PlayerType;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.util.ExtractorHelper;
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
index 65fd8ada1c6..e3caeb522b0 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
@@ -43,7 +43,7 @@
import org.schabi.newpipe.info_list.dialog.StreamDialogDefaultEntry;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
-import org.schabi.newpipe.player.PlayerService.PlayerType;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
import org.schabi.newpipe.util.ExtractorHelper;
diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java
index 3bec07dcc59..7fc72e06418 100644
--- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java
@@ -43,7 +43,7 @@
import org.schabi.newpipe.info_list.dialog.InfoItemDialog;
import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager;
-import org.schabi.newpipe.player.PlayerService.PlayerType;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.util.Localization;
diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java
index 2d44c644918..17b5a1985c0 100644
--- a/app/src/main/java/org/schabi/newpipe/player/Player.java
+++ b/app/src/main/java/org/schabi/newpipe/player/Player.java
@@ -32,7 +32,6 @@
import static org.schabi.newpipe.player.helper.PlayerHelper.isPlaybackResumeEnabled;
import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode;
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs;
-import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlayerTypeFromIntent;
import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences;
import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs;
import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_CLOSE;
@@ -95,7 +94,6 @@
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager;
-import org.schabi.newpipe.player.PlayerService.PlayerType;
import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.event.PlayerServiceEventListener;
import org.schabi.newpipe.player.helper.AudioReactor;
@@ -308,7 +306,7 @@ public void handleIntent(@NonNull final Intent intent) {
}
final PlayerType oldPlayerType = playerType;
- playerType = retrievePlayerTypeFromIntent(intent);
+ playerType = PlayerType.retrieveFromIntent(intent);
initUIsForCurrentPlayerType();
// We need to setup audioOnly before super(), see "sourceOf"
isAudioOnly = audioPlayerSelected();
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
index 14e8262d6fb..8d982617a64 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
@@ -42,11 +42,6 @@ public final class PlayerService extends Service {
private final IBinder mBinder = new PlayerService.LocalBinder();
- public enum PlayerType {
- MAIN,
- AUDIO,
- POPUP
- }
/*//////////////////////////////////////////////////////////////////////////
// Service's LifeCycle
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerType.java b/app/src/main/java/org/schabi/newpipe/player/PlayerType.java
new file mode 100644
index 00000000000..171a703953c
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayerType.java
@@ -0,0 +1,32 @@
+package org.schabi.newpipe.player;
+
+import static org.schabi.newpipe.player.Player.PLAYER_TYPE;
+
+import android.content.Intent;
+
+public enum PlayerType {
+ MAIN,
+ AUDIO,
+ POPUP;
+
+ /**
+ * @return an integer representing this {@link PlayerType}, to be used to save it in intents
+ * @see #retrieveFromIntent(Intent) Use retrieveFromIntent() to retrieve and convert player type
+ * integers from an intent
+ */
+ public int valueForIntent() {
+ return ordinal();
+ }
+
+ /**
+ * @param intent the intent to retrieve a player type from
+ * @return the player type integer retrieved from the intent, converted back into a {@link
+ * PlayerType}, or {@link PlayerType#MAIN} if there is no player type extra in the
+ * intent
+ * @throws ArrayIndexOutOfBoundsException if the intent contains an invalid player type integer
+ * @see #valueForIntent() Use valueForIntent() to obtain valid player type integers
+ */
+ public static PlayerType retrieveFromIntent(final Intent intent) {
+ return values()[intent.getIntExtra(PLAYER_TYPE, MAIN.valueForIntent())];
+ }
+}
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 d1d29dd71a1..fb346f5ba05 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
@@ -3,7 +3,6 @@
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
-import static org.schabi.newpipe.player.Player.PLAYER_TYPE;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_ALWAYS;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_NEVER;
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_WIFI;
@@ -14,7 +13,6 @@
import android.annotation.SuppressLint;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.view.accessibility.CaptioningManager;
@@ -44,7 +42,6 @@
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
import org.schabi.newpipe.extractor.utils.Utils;
import org.schabi.newpipe.player.Player;
-import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
@@ -428,12 +425,6 @@ private static SinglePlayQueue getAutoQueuedSinglePlayQueue(
// Utils used by player
////////////////////////////////////////////////////////////////////////////
- public static PlayerService.PlayerType retrievePlayerTypeFromIntent(final Intent intent) {
- // If you want to open popup from the app just include Constants.POPUP_ONLY into an extra
- return PlayerService.PlayerType.values()[
- intent.getIntExtra(PLAYER_TYPE, PlayerService.PlayerType.MAIN.ordinal())];
- }
-
public static boolean isPlaybackResumeEnabled(final Player player) {
return player.getPrefs().getBoolean(
player.getContext().getString(R.string.enable_watch_history_key), true)
diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java
index cb613f8541e..5eaecd48dec 100644
--- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java
@@ -18,6 +18,7 @@
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.Player;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.event.PlayerServiceEventListener;
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
import org.schabi.newpipe.player.playqueue.PlayQueue;
@@ -46,13 +47,13 @@ public static synchronized PlayerHolder getInstance() {
@Nullable private Player player;
/**
- * Returns the current {@link PlayerService.PlayerType} of the {@link PlayerService} service,
- * otherwise `null` if no service running.
+ * Returns the current {@link PlayerType} of the {@link PlayerService} service,
+ * otherwise `null` if no service is running.
*
* @return Current PlayerType
*/
@Nullable
- public PlayerService.PlayerType getType() {
+ public PlayerType getType() {
if (player == null) {
return null;
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java
index 36b2bd46d4f..3b2c52691c5 100644
--- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java
@@ -51,9 +51,9 @@
import org.schabi.newpipe.local.subscription.SubscriptionFragment;
import org.schabi.newpipe.local.subscription.SubscriptionsImportFragment;
import org.schabi.newpipe.player.PlayerService;
-import org.schabi.newpipe.player.PlayerService.PlayerType;
import org.schabi.newpipe.player.PlayQueueActivity;
import org.schabi.newpipe.player.Player;
+import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.PlayQueue;
@@ -91,7 +91,7 @@ public static Intent getPlayerIntent(@NonNull final Context context,
intent.putExtra(Player.PLAY_QUEUE_KEY, cacheKey);
}
}
- intent.putExtra(Player.PLAYER_TYPE, PlayerService.PlayerType.MAIN.ordinal());
+ intent.putExtra(Player.PLAYER_TYPE, PlayerType.MAIN.valueForIntent());
intent.putExtra(Player.RESUME_PLAYBACK, resumePlayback);
return intent;
@@ -164,7 +164,7 @@ public static void playOnPopupPlayer(final Context context,
Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
final Intent intent = getPlayerIntent(context, PlayerService.class, queue, resumePlayback);
- intent.putExtra(Player.PLAYER_TYPE, PlayerService.PlayerType.POPUP.ordinal());
+ intent.putExtra(Player.PLAYER_TYPE, PlayerType.POPUP.valueForIntent());
ContextCompat.startForegroundService(context, intent);
}
@@ -175,7 +175,7 @@ public static void playOnBackgroundPlayer(final Context context,
.show();
final Intent intent = getPlayerIntent(context, PlayerService.class, queue, resumePlayback);
- intent.putExtra(Player.PLAYER_TYPE, PlayerService.PlayerType.AUDIO.ordinal());
+ intent.putExtra(Player.PLAYER_TYPE, PlayerType.AUDIO.valueForIntent());
ContextCompat.startForegroundService(context, intent);
}
@@ -186,15 +186,15 @@ public static void enqueueOnPlayer(final Context context,
Toast.makeText(context, R.string.enqueued, Toast.LENGTH_SHORT).show();
final Intent intent = getPlayerEnqueueIntent(context, PlayerService.class, queue);
- intent.putExtra(Player.PLAYER_TYPE, playerType.ordinal());
+ intent.putExtra(Player.PLAYER_TYPE, playerType.valueForIntent());
ContextCompat.startForegroundService(context, intent);
}
public static void enqueueOnPlayer(final Context context, final PlayQueue queue) {
PlayerType playerType = PlayerHolder.getInstance().getType();
- if (!PlayerHolder.getInstance().isPlayerOpen()) {
+ if (playerType == null) {
Log.e(TAG, "Enqueueing but no player is open; defaulting to background player");
- playerType = PlayerService.PlayerType.AUDIO;
+ playerType = PlayerType.AUDIO;
}
enqueueOnPlayer(context, queue, playerType);
@@ -203,14 +203,14 @@ public static void enqueueOnPlayer(final Context context, final PlayQueue queue)
/* ENQUEUE NEXT */
public static void enqueueNextOnPlayer(final Context context, final PlayQueue queue) {
PlayerType playerType = PlayerHolder.getInstance().getType();
- if (!PlayerHolder.getInstance().isPlayerOpen()) {
+ if (playerType == null) {
Log.e(TAG, "Enqueueing next but no player is open; defaulting to background player");
- playerType = PlayerService.PlayerType.AUDIO;
+ playerType = PlayerType.AUDIO;
}
Toast.makeText(context, R.string.enqueued_next, Toast.LENGTH_SHORT).show();
final Intent intent = getPlayerEnqueueNextIntent(context, PlayerService.class, queue);
- intent.putExtra(Player.PLAYER_TYPE, playerType.ordinal());
+ intent.putExtra(Player.PLAYER_TYPE, playerType.valueForIntent());
ContextCompat.startForegroundService(context, intent);
}
@@ -414,14 +414,14 @@ public static void openVideoDetailFragment(@NonNull final Context context,
final boolean switchingPlayers) {
final boolean autoPlay;
- @Nullable final PlayerService.PlayerType playerType = PlayerHolder.getInstance().getType();
- if (!PlayerHolder.getInstance().isPlayerOpen()) {
+ @Nullable final PlayerType playerType = PlayerHolder.getInstance().getType();
+ if (playerType == null) {
// no player open
autoPlay = PlayerHelper.isAutoplayAllowedByUser(context);
} else if (switchingPlayers) {
// switching player to main player
autoPlay = PlayerHolder.getInstance().isPlaying(); // keep play/pause state
- } else if (playerType == PlayerService.PlayerType.MAIN) {
+ } else if (playerType == PlayerType.MAIN) {
// opening new stream while already playing in main player
autoPlay = PlayerHelper.isAutoplayAllowedByUser(context);
} else {
@@ -436,7 +436,7 @@ public static void openVideoDetailFragment(@NonNull final Context context,
// Situation when user switches from players to main player. All needed data is
// here, we can start watching (assuming newQueue equals playQueue).
// Starting directly in fullscreen if the previous player type was popup.
- detailFragment.openVideoPlayer(playerType == PlayerService.PlayerType.POPUP
+ detailFragment.openVideoPlayer(playerType == PlayerType.POPUP
|| PlayerHelper.isStartMainPlayerFullscreenEnabled(context));
} else {
detailFragment.selectAndLoadVideo(serviceId, url, title, playQueue);
From 4536e8b55b59502471cd0b409f8b68e8cff600d2 Mon Sep 17 00:00:00 2001
From: TacoTheDank
Date: Thu, 14 Jul 2022 01:48:52 -0400
Subject: [PATCH 046/152] Update some miscellaneous libraries
---
app/build.gradle | 18 +++++++++---------
build.gradle | 2 +-
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 9867037e6a9..787dd7833f4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -95,7 +95,7 @@ android {
}
ext {
- checkstyleVersion = '10.0'
+ checkstyleVersion = '10.3.1'
androidxLifecycleVersion = '2.3.1'
androidxRoomVersion = '2.4.2'
@@ -110,7 +110,7 @@ ext {
leakCanaryVersion = '2.5'
stethoVersion = '1.6.0'
mockitoVersion = '4.0.0'
- assertJVersion = '3.22.0'
+ assertJVersion = '3.23.1'
}
configurations {
@@ -179,7 +179,7 @@ sonarqube {
dependencies {
/** Desugaring **/
- coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'
/** NewPipe libraries **/
// You can use a local version by uncommenting a few lines in settings.gradle
@@ -191,7 +191,7 @@ dependencies {
/** Checkstyle **/
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
- ktlint 'com.pinterest:ktlint:0.44.0'
+ ktlint 'com.pinterest:ktlint:0.45.2'
/** Kotlin **/
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
@@ -199,14 +199,14 @@ dependencies {
/** AndroidX **/
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.cardview:cardview:1.0.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
- implementation 'androidx.core:core-ktx:1.6.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.fragment:fragment-ktx:1.3.6'
implementation "androidx.lifecycle:lifecycle-livedata:${androidxLifecycleVersion}"
implementation "androidx.lifecycle:lifecycle-viewmodel:${androidxLifecycleVersion}"
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
- implementation 'androidx.media:media:1.5.0'
+ implementation 'androidx.media:media:1.6.0'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation "androidx.room:room-runtime:${androidxRoomVersion}"
@@ -226,7 +226,7 @@ dependencies {
kapt "frankiesardo:icepick-processor:${icepickVersion}"
// HTML parser
- implementation "org.jsoup:jsoup:1.14.3"
+ implementation "org.jsoup:jsoup:1.15.2"
// HTTP client
//noinspection GradleDependency --> do not update okhttp to keep supporting Android 4.4 users
@@ -274,7 +274,7 @@ dependencies {
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
// Date and time formatting
- implementation "org.ocpsoft.prettytime:prettytime:5.0.2.Final"
+ implementation "org.ocpsoft.prettytime:prettytime:5.0.3.Final"
/** Debugging **/
// Memory leak detection
diff --git a/build.gradle b/build.gradle
index bea444fab92..322a47a6f8e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.2.0'
+ classpath 'com.android.tools.build:gradle:7.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
From c1e78cf55bf6e4178ac3ef3b4f7bae52c7f992c0 Mon Sep 17 00:00:00 2001
From: TacoTheDank
Date: Thu, 14 Jul 2022 03:23:45 -0400
Subject: [PATCH 047/152] Update OkHttp to 4.x
---
app/build.gradle | 3 +--
app/src/main/java/org/schabi/newpipe/DownloaderImpl.java | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 9867037e6a9..b5e26e8fc15 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -229,8 +229,7 @@ dependencies {
implementation "org.jsoup:jsoup:1.14.3"
// HTTP client
- //noinspection GradleDependency --> do not update okhttp to keep supporting Android 4.4 users
- implementation "com.squareup.okhttp3:okhttp:3.12.13"
+ implementation "com.squareup.okhttp3:okhttp:4.10.0"
// Media player
implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}"
diff --git a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java
index f2803dc2fb1..79d2ad7b7dd 100644
--- a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java
+++ b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java
@@ -135,7 +135,7 @@ public Response execute(@NonNull final Request request)
RequestBody requestBody = null;
if (dataToSend != null) {
- requestBody = RequestBody.create(null, dataToSend);
+ requestBody = RequestBody.create(dataToSend);
}
final okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder()
From cc7a8fb1a611299bab6b574b75b602b38a23b2d9 Mon Sep 17 00:00:00 2001
From: krlvm <51774833+krlvm@users.noreply.github.com>
Date: Tue, 21 Jun 2022 20:22:39 +0300
Subject: [PATCH 048/152] Improve image placeholders
- Show placeholders until the image is loaded because timeout can be very long and missing profile pictures and video thumbnails make app inconvenient to use
- Adapt profile picture and video thumbnail placeholders to light theme
- Replace profile picture and video thumbnail placeholders with vector graphics
---
.../fragments/detail/VideoDetailFragment.java | 4 +-
.../schabi/newpipe/util/PicassoHelper.java | 17 +++-
app/src/main/res/drawable-nodpi/buddy.png | Bin 1168 -> 0 bytes
.../res/drawable-nodpi/buddy_channel_item.png | Bin 1051 -> 0 bytes
.../res/drawable-nodpi/dummy_thumbnail.png | Bin 956 -> 0 bytes
.../drawable-nodpi/dummy_thumbnail_dark.png | Bin 105 -> 134 bytes
.../dummy_thumbnail_playlist.png | Bin 1225 -> 0 bytes
app/src/main/res/drawable/buddy.xml | 31 ++++++++
app/src/main/res/drawable/dummy_thumbnail.xml | 22 ++++++
.../res/drawable/dummy_thumbnail_playlist.xml | 30 +++++++
.../res/layout/list_channel_grid_item.xml | 2 +-
.../res/layout/list_channel_mini_item.xml | 2 +-
.../res/layout/list_comments_mini_item.xml | 2 +-
.../res/layout/picker_subscription_item.xml | 2 +-
app/src/main/res/values-night/colors.xml | 3 +
app/src/main/res/values/colors.xml | 3 +
assets/buddy_channel_item.svg | 73 ------------------
assets/dummy_thumbnail.svg | 7 ++
assets/dummy_thumbnail_playlist.svg | 8 ++
19 files changed, 125 insertions(+), 81 deletions(-)
delete mode 100644 app/src/main/res/drawable-nodpi/buddy.png
delete mode 100644 app/src/main/res/drawable-nodpi/buddy_channel_item.png
delete mode 100644 app/src/main/res/drawable-nodpi/dummy_thumbnail.png
delete mode 100644 app/src/main/res/drawable-nodpi/dummy_thumbnail_playlist.png
create mode 100644 app/src/main/res/drawable/buddy.xml
create mode 100644 app/src/main/res/drawable/dummy_thumbnail.xml
create mode 100644 app/src/main/res/drawable/dummy_thumbnail_playlist.xml
delete mode 100644 assets/buddy_channel_item.svg
create mode 100644 assets/dummy_thumbnail.svg
create mode 100644 assets/dummy_thumbnail_playlist.svg
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 278d472d4c6..78f3772e904 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
@@ -714,7 +714,7 @@ private View.OnTouchListener getOnControlsTouchListener() {
}
private void initThumbnailViews(@NonNull final StreamInfo info) {
- PicassoHelper.loadThumbnail(info.getThumbnailUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadDetailsThumbnail(info.getThumbnailUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailThumbnailImageView, new Callback() {
@Override
public void onSuccess() {
@@ -2361,7 +2361,7 @@ private void updateOverlayData(@Nullable final String overlayTitle,
binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle);
binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
binding.overlayThumbnail.setImageResource(R.drawable.dummy_thumbnail_dark);
- PicassoHelper.loadThumbnail(thumbnailUrl).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadDetailsThumbnail(thumbnailUrl).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.overlayThumbnail);
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
index aabc459d015..223e8ac9caa 100644
--- a/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
@@ -104,6 +104,10 @@ public static RequestCreator loadThumbnail(final String url) {
return loadImageDefault(url, R.drawable.dummy_thumbnail);
}
+ public static RequestCreator loadDetailsThumbnail(final String url) {
+ return loadImageDefault(url, R.drawable.dummy_thumbnail, false);
+ }
+
public static RequestCreator loadBanner(final String url) {
return loadImageDefault(url, R.drawable.channel_banner);
}
@@ -189,15 +193,24 @@ public void onPrepareLoad(final Drawable placeHolderDrawable) {
private static RequestCreator loadImageDefault(final String url, final int placeholderResId) {
+ return loadImageDefault(url, placeholderResId, true);
+ }
+
+ private static RequestCreator loadImageDefault(final String url, final int placeholderResId,
+ final boolean showPlaceholderWhileLoading) {
if (!shouldLoadImages || isBlank(url)) {
return picassoInstance
.load((String) null)
.placeholder(placeholderResId) // show placeholder when no image should load
.error(placeholderResId);
} else {
- return picassoInstance
+ final RequestCreator requestCreator = picassoInstance
.load(url)
- .error(placeholderResId); // don't show placeholder while loading, only on error
+ .error(placeholderResId);
+ if (showPlaceholderWhileLoading) {
+ requestCreator.placeholder(placeholderResId);
+ }
+ return requestCreator;
}
}
}
diff --git a/app/src/main/res/drawable-nodpi/buddy.png b/app/src/main/res/drawable-nodpi/buddy.png
deleted file mode 100644
index 8713ee02bfa8cd492bf79ed4730ca4060ceeb631..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1168
zcmV;B1aJF^P)b~j1!&(iVkGA*yRLsUHxctK)V
zbrwUKLgK~AqOlZmKgKJ|YYQQFIo?ozuk3;}eY~-(u?X@o$J-OLt0fRsC3shIYX#(-
zNuCL1%5yBL~_YZH(P`V$pD
zqy|Nz=7uyeXe13Uq?I5_ww#bl3bN7*A4KIKEK_Wd1xQxb3@jDYkVb%~h8CjwU@E7D)L^S7h2&r>r-a;rv3o+u0E`Xk
zAPrb+$RGt+E2toy1Zz?eLH1y7PXrl(xiJmoD!`n$l0ZtZSCT*`U~fzTQ3=?K6#?V~
z12qJY9SpP~fJ|VZ2?3-B1NHPn6pYkqhqN%#Njs#1k@nglYZz&x9WsTHrrIF`7-^^-
z(ua{U?T{2kO0`2Ij3l)~1dJ5>0ucdX86@`ppFO<%W-wA;J7j3tN0jiPaRVc*wL|tW
z(m^}q2qU%LA3lWRpvN%`H1XxgbV~qfVW4BUR(0a6bI$P>d_(L(AznCe$_5LNcT*v+jXfvEir
znCq2FKcw!%K>b=XJ&yxYb}t60>+zM-w&x0SWt3!Cq&I*
zNwe-fkfsM~>K)$>DFtk5^F~NFgJn&-w?NJrtSh^`9@3_;u;ln!NFBq<;`()vQozzg
z`5MShz}m$2<&X`mZuwHk3YNEi8DtCV+q?vFD`0)1d>(Ru3yJzU$T5Z!#m&=@OA1Fy
zFHb?b49=9RCm;nJYW{yn1*fY12RX-Zs`&IDNDjx!)juH{IM?Q1kXFFCMEf^H4d7q{
z^%vw8PPYFO(j{=RwEF|Hgrlu~hg@SgT73NtGKaG*euZ2GoK0MRfvn(g>z|NL!r^51
z1G0nDl|LYTI9>J~a)jfx-ym~1-r_4nC2+jtE94%|*L;C2;C#z3kRF_`_Zf1A2VFiv
zDtJ)!2~xm==AR%p@Sy%`|M
z$uorG8CUd71_tH>o-U3d6}R4;Zxmo);9%JJhx3$K|NgTH#ezx%!PgEjI8j$!K5O|Z
zzLvy2;(yc}-&{ENO`)%0bIaX(=gaM!R6~nC-9PwPV)Ci;kG~avnkTi?=a=2jTl4N{
zx83>Fc`SZLVO{lFf$g#n=dZlDu5RW8EBOcZD);-Ra}@48_}^gXWceW8kKC7nDm?av
z{7}t$snUMO=#NqLMCqU`n}bt=oWDu=2UgEil(xxLHhi++!=AZ&CIl^H4fW#QnYATp
z-6p3wuHM%=xgr;BUAkm~*Fw`!POgnF5?&l>dGbPKx=@gGNm7=gqISuY(;O>>OQu)|
zDq5Fp6BaabN>AogG;e*E$K+Hb5W&qcv*ExL`y-M927R_qIE2){P2ly&x#?`@_^8`9
zg-Iy*n*g`aG+Pzc&MCG>8e9&^Epl)=I^oA9p|5Gv|9_O;FYs6>^>zA1iRm9dwuc(C
zHD=zanXpxM$-BblK7*9o({(RbU6}0qM(zE{jZVSpOW18czUVz*{WmegW?q`K#E&;8
zIozMM@LrYpw@^xI>NEM`BpI9A=8v3S9eR{`I96BZiOuzlqdMoBoK|%@RYxi+A9<^5
zwW<2Je9uCyzi!yp4gH%GgXh|nsmIJ$}Rs%;$ZVd<&qPs
zt>P~&b376sblSD>L>`vk$|pWayFmy*8bpJ
zDRAea_X(MUx-~5p%@2A$3j{SdK2%I$V>9Mg0=K=XbS{$IP4O
z{n?Q9EWx0EHvgt=%|hblFXA#zo8%>#r^fe*&f;-Q{rKYTc1xbzcb$J8XBILuTkltv
z5oR&^XcH35FX-~?gUqFvqkWdPs{=l)e{oXdf!djZXKw!r)ap6^?$Eit+B>((C@Ahr
z%8CD%wr7ifRPy0|&a>oA>)UI$``IM7zB>BV)^x8?{0f`8h6Y=%9gnIuywI@r*jZu|
znvoyGwTrDTQesQewD3gn@o>{EqW2>-&>r*LXZ_(Z|zYQa)$A*kiinPNr$lkNR(`
zm;6sR%zC#cI!)?-n#K9myA;1)`|)ty({I&=+su4<5++@__3=@4bX@G?s;5ox
STg?c}*bJVoelF{r5}E*aKG6LD
diff --git a/app/src/main/res/drawable-nodpi/dummy_thumbnail.png b/app/src/main/res/drawable-nodpi/dummy_thumbnail.png
deleted file mode 100644
index 86f454186e1f39cf9ca3ac28dd95502fdbce4655..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 956
zcmeAS@N?(olHy`uVBq!ia0y~yU|a=cf8YQT3?*{6LDa*vT`5;~7`oJ0;^v
zbkO&@i;A40S_@}sggCW&t!Uwz8UW%7X@xkchOB7uS`olGH2}z62;_nkpmA}jU-kOz
z?QT77ynJ~dP~_Fwoytz3TYq1XT)67y-s}+O@=*J%Z%?i;Mux_3
zttx%jux8czTeWX`0zzf=t(8Met1B)GE?gC5W4~Bx?de}%la}pR;k0Z=9mDFTWjn$`
zFNj=Ub!z6LsL;URn2^Ojg@LhG){9#l-MR`adqqS%^n}QD{)96?Wl{-U-LH!OR=otO
zRE(Y`e_)B`y3nto-Qsg60IAvE!BqKrE0CQfuM(X^i>I|_E!nISGXK@})Aa@JqL$g8
zm}h)>kQeHDc2>Ysn;nZ+MeTdl5Wos#o!Z^fmi4Rp@(R0a^3&@*dbEBXlnuRl__lyn
z$kvL&a|?hT{wv|os`YerO&ch7mWLgHnG*aK9*E?oBd!%lXN&;yEws~T?4U2%!8
zGZ1W|y^5RZ-?x4t?_ckKX>j0(Z0M6x$B_N^avJup4{*IV!SU;B-T3be3%P7WzHRvT
zT2`;>NC4{}%cpy^(mWcq62G*+x*om%eZ6_e{GzzjHa))zrV$y6Uoi3%n%#7VP>pe=l=;*57T*`9qKWzO`aqa+~mqO>CQ2
z)THPwm^~vpdBvu@-i2HhD|K63m`>kT3RDwn0E0NDPwL>%ybA~*haoIVPItuU|?H)Z&(<0e9y%;t!Ks7D}w%g6j_y9
zd%x&~zu$seOMqsVMa~vk_4YR(N9eKgi2-l3#XkMwT{Y!;egH2oIOXC?*T@N(n0)X>
Ym3dv9k!XF~Gf=klboFyt=akR{0K-zPssI20
diff --git a/app/src/main/res/drawable-nodpi/dummy_thumbnail_dark.png b/app/src/main/res/drawable-nodpi/dummy_thumbnail_dark.png
index 02f698918fff753ac9d5bfe6091ac8349435243b..0e73416edeb6371b992c6c150b42d46a1c22f156 100644
GIT binary patch
literal 134
zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaMs(j9#r85lP9
zbN@+X1@buyJR*yMny-N{YhX3vTXZ8bmyq+$OArj%q2?+^5_!$^k
V7#Ru_Qn`T=44$rjF6*2UngBC(9*6({
literal 105
zcmeAS@N?(olHy`uVBq!ia0vp^?m(=;2qYLEakt!I&(;+6**`aRLM5QNh-iK2A&*Qo$V9E1zaSW-r_2yzD4^RoyhCjTU&MyAT<3;rZUGZhj37hA-&Z3Ve?Q;Lp*yG@)pezZZRsB|P*hnYQrnlAje`Hk3S|LIAbp7KR{)xjUW9eGv}CnXjKosifj&vP{)
z{F(dzylTf|5>uUyZFrlof^F{pzEkUxCV%AMNDSI2zNq~zhh%cdvoxM%iL(y|@LKVM
zj8;tU@ls6AYRP4AHcj8~jpa7OykiS~Yq
zIX!PnLS(|NYz7z!bj^~
zZ=+f1Q{rrYJ0Hu6Q=7bT>b}GJ{6=YkH`g|%JekfenO*pyt7mzUT|+Nz(U+W(+CO@x_M8ooTwdrYDaq@nHhE&a9MCF8Dyo_L9U1(RTviPS^Ur$ZX;p6|W
zncGadSpV0}?OJ}ynuom&F)JPwd-F;Dy`G0IbQBJ(j>R>r@XP{JfC-?%^>7C`(3r<)-(T2l)gh!>>E3+i$JRmUbd(d
z&UHSqL)-N>gOT2n`cUKPZ@Ls7e+b?3S0Q<$p6hKEBfb6QnRhuZ9yV*~X%@c-B)fw^
zl8=Knyfu5660>x{f0bKp6AJ4Da_vvtun-5DwxZ_gUcb8=?kYU4`lJSw`}nit+wpHN
v9Drp2gTsXVUlpc1f%7!MjLuFbP0l+XkK#Ah!m
diff --git a/app/src/main/res/drawable/buddy.xml b/app/src/main/res/drawable/buddy.xml
new file mode 100644
index 00000000000..b7d23c4b108
--- /dev/null
+++ b/app/src/main/res/drawable/buddy.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/dummy_thumbnail.xml b/app/src/main/res/drawable/dummy_thumbnail.xml
new file mode 100644
index 00000000000..5114fda3283
--- /dev/null
+++ b/app/src/main/res/drawable/dummy_thumbnail.xml
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/dummy_thumbnail_playlist.xml b/app/src/main/res/drawable/dummy_thumbnail_playlist.xml
new file mode 100644
index 00000000000..683b814c9a6
--- /dev/null
+++ b/app/src/main/res/drawable/dummy_thumbnail_playlist.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/list_channel_grid_item.xml b/app/src/main/res/layout/list_channel_grid_item.xml
index d9084bbe97d..9f92c35a70e 100644
--- a/app/src/main/res/layout/list_channel_grid_item.xml
+++ b/app/src/main/res/layout/list_channel_grid_item.xml
@@ -18,7 +18,7 @@
android:layout_centerHorizontal="true"
android:layout_margin="2dp"
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
- android:src="@drawable/buddy_channel_item"
+ android:src="@drawable/buddy"
app:shapeAppearance="@style/CircularImageView"
tools:ignore="RtlHardcoded" />
diff --git a/app/src/main/res/layout/list_channel_mini_item.xml b/app/src/main/res/layout/list_channel_mini_item.xml
index b66e07a12c5..e03f7c2fa83 100644
--- a/app/src/main/res/layout/list_channel_mini_item.xml
+++ b/app/src/main/res/layout/list_channel_mini_item.xml
@@ -17,7 +17,7 @@
android:layout_centerVertical="true"
android:layout_marginStart="3dp"
android:layout_marginRight="15dp"
- android:src="@drawable/buddy_channel_item"
+ android:src="@drawable/buddy"
app:shapeAppearance="@style/CircularImageView"
tools:ignore="RtlHardcoded" />
diff --git a/app/src/main/res/layout/list_comments_mini_item.xml b/app/src/main/res/layout/list_comments_mini_item.xml
index 6bd36331101..ba984e0ff94 100644
--- a/app/src/main/res/layout/list_comments_mini_item.xml
+++ b/app/src/main/res/layout/list_comments_mini_item.xml
@@ -17,7 +17,7 @@
android:layout_centerVertical="true"
android:layout_marginStart="3dp"
android:layout_marginRight="15dp"
- android:src="@drawable/buddy_channel_item"
+ android:src="@drawable/buddy"
app:shapeAppearance="@style/CircularImageView"
tools:ignore="RtlHardcoded" />
diff --git a/app/src/main/res/layout/picker_subscription_item.xml b/app/src/main/res/layout/picker_subscription_item.xml
index c858ccc4e1a..f6e5f358799 100644
--- a/app/src/main/res/layout/picker_subscription_item.xml
+++ b/app/src/main/res/layout/picker_subscription_item.xml
@@ -22,7 +22,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
app:shapeAppearance="@style/CircularImageView"
- tools:src="@drawable/buddy_channel_item" />
+ tools:src="@drawable/buddy" />
@color/white
@color/white
+
+ #6C6C6C
+ #999999