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" /> + +