From 2ed7a5a69b08f9b983b581056cd1cc36c65c3d33 Mon Sep 17 00:00:00 2001
From: Avently <7953703+avently@users.noreply.github.com>
Date: Sat, 19 Feb 2022 23:41:17 +0300
Subject: [PATCH] Selectable back button behavior
---
.../fragments/detail/VideoDetailFragment.java | 74 ++++++++++++++++++-
.../newpipe/player/helper/PlayerHelper.java | 39 ++++++++++
app/src/main/res/values/settings_keys.xml | 25 +++++++
app/src/main/res/values/strings.xml | 9 +++
app/src/main/res/xml/video_audio_settings.xml | 9 +++
5 files changed, 154 insertions(+), 2 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 2d9abc6dc67..6c2870e2880 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
@@ -755,6 +755,28 @@ public boolean onBackPressed() {
Log.d(TAG, "onBackPressed() called");
}
+ // User can choose a behavior of the back button.
+ // We go down and check if it's OK to stop at some point based on the user's
+ // preference.
+ // For example, if the user always wants to minimize into the mini player
+ // when the backstack is empty, we have to ensure that:
+ // - nothing is in the backstack
+ // - nothing is in the PlayQueue's history
+ // - the player is in non-fullscreen mode.
+ // Otherwise it takes priority and the minimize action will not happen right now
+ final int behavior = PlayerHelper.getBackBehavior(activity);
+
+ if (behavior == PlayerHelper.BackBehavior.BACK_BEHAVIOR_CLOSE_FULLSCREEN) {
+ if (!isPlayerAvailable() || player.videoPlayerSelected()) {
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
+ requireView().postDelayed(this::rotateScreenOnPhoneIfInLandscape, 500);
+ } else {
+ // Since it's not a video playing we can't close the player
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+ }
+ return true;
+ }
+
// If we are in fullscreen mode just exit from it via first back press
if (isPlayerAvailable() && player.isFullscreen()) {
if (!DeviceUtils.isTablet(activity)) {
@@ -765,6 +787,21 @@ public boolean onBackPressed() {
return true;
}
+ if (behavior == PlayerHelper.BackBehavior.BACK_BEHAVIOR_CLOSE) {
+ if (!isPlayerAvailable() || player.videoPlayerSelected()) {
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
+ } else {
+ // Since it's not a video playing we can't close the player
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+ }
+ return true;
+ }
+
+ if (behavior == PlayerHelper.BackBehavior.BACK_BEHAVIOR_HIDE) {
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+ return true;
+ }
+
// If we have something in history of played items we replay it here
if (isPlayerAvailable()
&& player.getPlayQueue() != null
@@ -773,10 +810,30 @@ public boolean onBackPressed() {
return true; // no code here, as previous() was used in the if
}
- // That means that we are on the start of the stack,
+ // If we passed previous check at the top `player.getPlayQueue().previous()`
+ // then we can be sure that queue have no more streams in the history.
+ // If the user chose BACK_BEHAVIOR_PREV_PLAYLIST behavior
+ // we have to minimize the player into the mini player here
+ if (behavior == PlayerHelper.BackBehavior.BACK_BEHAVIOR_PREV_PLAYLIST) {
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+ return true;
+ }
+
+ // That means that we are on the start of the stack
if (stack.size() <= 1) {
restoreDefaultOrientation();
- return false; // let MainActivity handle the onBack (e.g. to minimize the mini player)
+
+ if (behavior == PlayerHelper.BackBehavior.BACK_BEHAVIOR_HIDE_OR_CLOSE) {
+ if (!isPlayerAvailable() || player.getPlayQueue() == null
+ || (player.videoPlayerSelected()
+ && !player.getPlayQueue().equals(playQueue))) {
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
+ return true;
+ }
+ }
+
+ // let MainActivity handle the onBack (e.g. to minimize the mini player)
+ return false;
}
// Remove top
@@ -1092,6 +1149,15 @@ private void toggleFullscreenIfInFullscreenMode() {
}
}
+ private void rotateScreenOnPhoneIfInLandscape() {
+ if (!DeviceUtils.isTablet(activity)
+ && !DeviceUtils.isTv(activity)
+ && DeviceUtils.isLandscape(requireContext())
+ && globalScreenOrientationLocked(activity)) {
+ onScreenRotationButtonClicked();
+ }
+ }
+
private void openBackgroundPlayer(final boolean append) {
final AudioStream audioStream = currentInfo.getAudioStreams()
.get(ListHelper.getDefaultAudioFormat(activity, currentInfo.getAudioStreams()));
@@ -2188,6 +2254,10 @@ private void showExternalPlaybackDialog() {
* Remove unneeded information while waiting for a next task
* */
private void cleanUp() {
+ // On every clean up operation we want to be in non-fullscreen mode,
+ // since it returns UI into it's initial look when nothing is played
+ toggleFullscreenIfInFullscreenMode();
+
// New beginning
stack.clear();
if (currentWorker != null) {
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 c51b6d5dde0..76678cfc12e 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
@@ -8,6 +8,12 @@
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;
+import static org.schabi.newpipe.player.helper.PlayerHelper.BackBehavior.BACK_BEHAVIOR_PREV_ANY;
+import static org.schabi.newpipe.player.helper.PlayerHelper.BackBehavior.BACK_BEHAVIOR_PREV_PLAYLIST;
+import static org.schabi.newpipe.player.helper.PlayerHelper.BackBehavior.BACK_BEHAVIOR_HIDE;
+import static org.schabi.newpipe.player.helper.PlayerHelper.BackBehavior.BACK_BEHAVIOR_HIDE_OR_CLOSE;
+import static org.schabi.newpipe.player.helper.PlayerHelper.BackBehavior.BACK_BEHAVIOR_CLOSE;
+import static org.schabi.newpipe.player.helper.PlayerHelper.BackBehavior.BACK_BEHAVIOR_CLOSE_FULLSCREEN;
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;
@@ -95,6 +101,19 @@ public final class PlayerHelper {
int MINIMIZE_ON_EXIT_MODE_POPUP = 2;
}
+ @Retention(SOURCE)
+ @IntDef({BACK_BEHAVIOR_PREV_ANY, BACK_BEHAVIOR_PREV_PLAYLIST,
+ BACK_BEHAVIOR_HIDE, BACK_BEHAVIOR_HIDE_OR_CLOSE,
+ BACK_BEHAVIOR_CLOSE, BACK_BEHAVIOR_CLOSE_FULLSCREEN})
+ public @interface BackBehavior {
+ int BACK_BEHAVIOR_PREV_ANY = 0;
+ int BACK_BEHAVIOR_PREV_PLAYLIST = 1;
+ int BACK_BEHAVIOR_HIDE = 2;
+ int BACK_BEHAVIOR_HIDE_OR_CLOSE = 3;
+ int BACK_BEHAVIOR_CLOSE = 4;
+ int BACK_BEHAVIOR_CLOSE_FULLSCREEN = 5;
+ }
+
private PlayerHelper() { }
////////////////////////////////////////////////////////////////////////////
@@ -267,6 +286,26 @@ public static int getMinimizeOnExitAction(@NonNull final Context context) {
}
}
+ @BackBehavior
+ public static int getBackBehavior(@NonNull final Context context) {
+ final String action = getPreferences(context)
+ .getString(context.getString(R.string.back_behavior_key),
+ context.getString(R.string.back_behavior_value));
+ if (action.equals(context.getString(R.string.back_behavior_prev_any_key))) {
+ return BACK_BEHAVIOR_PREV_ANY; // default
+ } else if (action.equals(context.getString(R.string.back_behavior_prev_playlist_key))) {
+ return BACK_BEHAVIOR_PREV_PLAYLIST;
+ } else if (action.equals(context.getString(R.string.back_behavior_hide_key))) {
+ return BACK_BEHAVIOR_HIDE;
+ } else if (action.equals(context.getString(R.string.back_behavior_hide_or_close_key))) {
+ return BACK_BEHAVIOR_HIDE_OR_CLOSE;
+ } else if (action.equals(context.getString(R.string.back_behavior_close_key))) {
+ return BACK_BEHAVIOR_CLOSE;
+ } else {
+ return BACK_BEHAVIOR_CLOSE_FULLSCREEN;
+ }
+ }
+
@AutoplayType
public static int getAutoplayType(@NonNull final Context context) {
final String type = getPreferences(context).getString(
diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml
index 07d98c06995..eec1fcf5855 100644
--- a/app/src/main/res/values/settings_keys.xml
+++ b/app/src/main/res/values/settings_keys.xml
@@ -89,6 +89,31 @@
- @string/never
+ back_behavior_key
+ @string/back_behavior_prev_any_key
+ back_behavior_prev_any_key
+ back_behavior_prev_playlist_key
+ back_behavior_hide_key
+ back_behavior_hide_or_close_key
+ back_behavior_close_key
+ back_behavior_close_fullscreen_key
+
+ - @string/back_behavior_prev_any_key
+ - @string/back_behavior_prev_playlist_key
+ - @string/back_behavior_hide_key
+ - @string/back_behavior_hide_or_close_key
+ - @string/back_behavior_close_key
+ - @string/back_behavior_close_fullscreen_key
+
+
+ - @string/back_behavior_prev_any_description
+ - @string/back_behavior_prev_playlist_description
+ - @string/back_behavior_hide_description
+ - @string/back_behavior_hide_or_close_description
+ - @string/back_behavior_close_description
+ - @string/back_behavior_close_fullscreen_description
+
+
seekbar_preview_thumbnail_key
seekbar_preview_thumbnail_high_quality
seekbar_preview_thumbnail_low_quality
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 54551be14c7..cd10b968ab0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -516,6 +516,15 @@
None
Minimize to background player
Minimize to popup player
+
+ Back behavior in the player
+ What to do when the back button is pressed while inside a player — %s
+ Open previous video from backstack of opened videos
+ Open previous video only if belonging to a playlist
+ Minimize into the mini player
+ Minimize into the mini player if something is playing, close otherwise
+ Close the video player
+ Close the video player even in fullscreen
Start playback automatically — %s
Only on Wi-Fi
diff --git a/app/src/main/res/xml/video_audio_settings.xml b/app/src/main/res/xml/video_audio_settings.xml
index 4dc5d5c9aed..1728221d555 100644
--- a/app/src/main/res/xml/video_audio_settings.xml
+++ b/app/src/main/res/xml/video_audio_settings.xml
@@ -138,6 +138,15 @@
app:singleLineTitle="false"
app:iconSpaceReserved="false" />
+
+