Merge pull request #9159 from Isira-Seneviratne/Refactor_VideoPlayerUi

Refactor VideoPlayerUi.
This commit is contained in:
Stypox 2022-12-31 19:01:19 +01:00 committed by GitHub
commit 661cd4c182
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 132 deletions

View File

@ -154,6 +154,16 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
protected void initListeners() { protected void initListeners() {
super.initListeners(); super.initListeners();
binding.screenRotationButton.setOnClickListener(makeOnClickListener(() -> {
// Only if it's not a vertical video or vertical video but in landscape with locked
// orientation a screen orientation can be changed automatically
if (!isVerticalVideo || (isLandscape() && globalScreenOrientationLocked(context))) {
player.getFragmentListener()
.ifPresent(PlayerServiceEventListener::onScreenRotationButtonClicked);
} else {
toggleFullscreen();
}
}));
binding.queueButton.setOnClickListener(v -> onQueueClicked()); binding.queueButton.setOnClickListener(v -> onQueueClicked());
binding.segmentsButton.setOnClickListener(v -> onSegmentsClicked()); binding.segmentsButton.setOnClickListener(v -> onSegmentsClicked());
@ -173,6 +183,14 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
settingsContentObserver); settingsContentObserver);
binding.getRoot().addOnLayoutChangeListener(this); binding.getRoot().addOnLayoutChangeListener(this);
binding.moreOptionsButton.setOnLongClickListener(v -> {
player.getFragmentListener()
.ifPresent(PlayerServiceEventListener::onMoreOptionsLongClicked);
hideControls(0, 0);
hideSystemUIIfNeeded();
return true;
});
} }
@Override @Override
@ -846,23 +864,6 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
//region Click listeners //region Click listeners
@Override
public void onClick(final View v) {
if (v.getId() == binding.screenRotationButton.getId()) {
// Only if it's not a vertical video or vertical video but in landscape with locked
// orientation a screen orientation can be changed automatically
if (!isVerticalVideo || (isLandscape() && globalScreenOrientationLocked(context))) {
player.getFragmentListener().ifPresent(
PlayerServiceEventListener::onScreenRotationButtonClicked);
} else {
toggleFullscreen();
}
}
// call it later since it calls manageControlsAfterOnClick at the end
super.onClick(v);
}
@Override @Override
protected void onPlaybackSpeedClicked() { protected void onPlaybackSpeedClicked() {
final AppCompatActivity activity = getParentActivity().orElse(null); final AppCompatActivity activity = getParentActivity().orElse(null);
@ -875,18 +876,6 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
.show(activity.getSupportFragmentManager(), null); .show(activity.getSupportFragmentManager(), null);
} }
@Override
public boolean onLongClick(final View v) {
if (v.getId() == binding.moreOptionsButton.getId() && isFullscreen) {
player.getFragmentListener().ifPresent(
PlayerServiceEventListener::onMoreOptionsLongClicked);
hideControls(0, 0);
hideSystemUIIfNeeded();
return true;
}
return super.onLongClick(v);
}
@Override @Override
public boolean onKeyDown(final int keyCode) { public boolean onKeyDown(final int keyCode) {
if (keyCode == KeyEvent.KEYCODE_SPACE && isFullscreen) { if (keyCode == KeyEvent.KEYCODE_SPACE && isFullscreen) {

View File

@ -84,11 +84,11 @@ import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.views.player.PlayerFastSeekOverlay; import org.schabi.newpipe.views.player.PlayerFastSeekOverlay;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public abstract class VideoPlayerUi extends PlayerUi public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBarChangeListener,
implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, View.OnLongClickListener,
PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener { PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
private static final String TAG = VideoPlayerUi.class.getSimpleName(); private static final String TAG = VideoPlayerUi.class.getSimpleName();
@ -132,9 +132,11 @@ public abstract class VideoPlayerUi extends PlayerUi
private GestureDetector gestureDetector; private GestureDetector gestureDetector;
private BasePlayerGestureListener playerGestureListener; private BasePlayerGestureListener playerGestureListener;
@Nullable private View.OnLayoutChangeListener onLayoutChangeListener = null; @Nullable
private View.OnLayoutChangeListener onLayoutChangeListener = null;
@NonNull private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder = @NonNull
private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder =
new SeekbarPreviewThumbnailHolder(); new SeekbarPreviewThumbnailHolder();
@ -187,13 +189,13 @@ public abstract class VideoPlayerUi extends PlayerUi
abstract BasePlayerGestureListener buildGestureListener(); abstract BasePlayerGestureListener buildGestureListener();
protected void initListeners() { protected void initListeners() {
binding.qualityTextView.setOnClickListener(this); binding.qualityTextView.setOnClickListener(makeOnClickListener(this::onQualityClicked));
binding.playbackSpeed.setOnClickListener(this); binding.playbackSpeed.setOnClickListener(makeOnClickListener(this::onPlaybackSpeedClicked));
binding.playbackSeekBar.setOnSeekBarChangeListener(this); binding.playbackSeekBar.setOnSeekBarChangeListener(this);
binding.captionTextView.setOnClickListener(this); binding.captionTextView.setOnClickListener(makeOnClickListener(this::onCaptionClicked));
binding.resizeTextView.setOnClickListener(this); binding.resizeTextView.setOnClickListener(makeOnClickListener(this::onResizeClicked));
binding.playbackLiveSync.setOnClickListener(this); binding.playbackLiveSync.setOnClickListener(makeOnClickListener(player::seekToDefault));
playerGestureListener = buildGestureListener(); playerGestureListener = buildGestureListener();
gestureDetector = new GestureDetector(context, playerGestureListener); gestureDetector = new GestureDetector(context, playerGestureListener);
@ -202,20 +204,36 @@ public abstract class VideoPlayerUi extends PlayerUi
binding.repeatButton.setOnClickListener(v -> onRepeatClicked()); binding.repeatButton.setOnClickListener(v -> onRepeatClicked());
binding.shuffleButton.setOnClickListener(v -> onShuffleClicked()); binding.shuffleButton.setOnClickListener(v -> onShuffleClicked());
binding.playPauseButton.setOnClickListener(this); binding.playPauseButton.setOnClickListener(makeOnClickListener(player::playPause));
binding.playPreviousButton.setOnClickListener(this); binding.playPreviousButton.setOnClickListener(makeOnClickListener(player::playPrevious));
binding.playNextButton.setOnClickListener(this); binding.playNextButton.setOnClickListener(makeOnClickListener(player::playNext));
binding.moreOptionsButton.setOnClickListener(this); binding.moreOptionsButton.setOnClickListener(
binding.moreOptionsButton.setOnLongClickListener(this); makeOnClickListener(this::onMoreOptionsClicked));
binding.share.setOnClickListener(this); binding.share.setOnClickListener(makeOnClickListener(() -> {
binding.share.setOnLongClickListener(this); final PlayQueueItem currentItem = player.getCurrentItem();
binding.fullScreenButton.setOnClickListener(this); if (currentItem != null) {
binding.screenRotationButton.setOnClickListener(this); ShareUtils.shareText(context, currentItem.getTitle(),
binding.playWithKodi.setOnClickListener(this); player.getVideoUrlAtCurrentTime(), currentItem.getThumbnailUrl());
binding.openInBrowser.setOnClickListener(this); }
binding.playerCloseButton.setOnClickListener(this); }));
binding.switchMute.setOnClickListener(this); binding.share.setOnLongClickListener(v -> {
ShareUtils.copyToClipboard(context, player.getVideoUrlAtCurrentTime());
return true;
});
binding.fullScreenButton.setOnClickListener(makeOnClickListener(() -> {
player.setRecovery();
NavigationHelper.playOnMainPlayer(context,
Objects.requireNonNull(player.getPlayQueue()), true);
}));
binding.playWithKodi.setOnClickListener(makeOnClickListener(this::onPlayWithKodiClicked));
binding.openInBrowser.setOnClickListener(makeOnClickListener(this::onOpenInBrowserClicked));
binding.playerCloseButton.setOnClickListener(makeOnClickListener(() ->
// 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))
));
binding.switchMute.setOnClickListener(makeOnClickListener(player::toggleMute));
ViewCompat.setOnApplyWindowInsetsListener(binding.itemsListPanel, (view, windowInsets) -> { ViewCompat.setOnApplyWindowInsetsListener(binding.itemsListPanel, (view, windowInsets) -> {
final Insets cutout = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()); final Insets cutout = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout());
@ -229,11 +247,8 @@ public abstract class VideoPlayerUi extends PlayerUi
// player_overlays and fast_seek_overlay too. Without it they will be off-centered. // player_overlays and fast_seek_overlay too. Without it they will be off-centered.
onLayoutChangeListener = onLayoutChangeListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
binding.playerOverlays.setPadding( binding.playerOverlays.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
v.getPaddingLeft(), v.getPaddingRight(), v.getPaddingBottom());
v.getPaddingTop(),
v.getPaddingRight(),
v.getPaddingBottom());
// If we added padding to the fast seek overlay, too, it would not go under the // If we added padding to the fast seek overlay, too, it would not go under the
// system ui. Instead we apply negative margins equal to the window insets of // system ui. Instead we apply negative margins equal to the window insets of
@ -1326,86 +1341,39 @@ public abstract class VideoPlayerUi extends PlayerUi
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
//region Click listeners //region Click listeners
@Override
public void onClick(final View v) {
if (DEBUG) {
Log.d(TAG, "onClick() called with: v = [" + v + "]");
}
if (v.getId() == binding.resizeTextView.getId()) {
onResizeClicked();
} else if (v.getId() == binding.captionTextView.getId()) {
onCaptionClicked();
} else if (v.getId() == binding.playbackLiveSync.getId()) {
player.seekToDefault();
} else if (v.getId() == binding.playPauseButton.getId()) {
player.playPause();
} else if (v.getId() == binding.playPreviousButton.getId()) {
player.playPrevious();
} else if (v.getId() == binding.playNextButton.getId()) {
player.playNext();
} else if (v.getId() == binding.moreOptionsButton.getId()) {
onMoreOptionsClicked();
} else if (v.getId() == binding.share.getId()) {
final PlayQueueItem currentItem = player.getCurrentItem();
if (currentItem != null) {
ShareUtils.shareText(context, currentItem.getTitle(),
player.getVideoUrlAtCurrentTime(), currentItem.getThumbnailUrl());
}
} else if (v.getId() == binding.playWithKodi.getId()) {
onPlayWithKodiClicked();
} else if (v.getId() == binding.openInBrowser.getId()) {
onOpenInBrowserClicked();
} else if (v.getId() == binding.fullScreenButton.getId()) {
player.setRecovery();
NavigationHelper.playOnMainPlayer(context, player.getPlayQueue(), true);
return;
} else if (v.getId() == binding.switchMute.getId()) {
player.toggleMute();
} else if (v.getId() == binding.playerCloseButton.getId()) {
// 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()) {
onQualityClicked();
}
manageControlsAfterOnClick(v);
}
/** /**
* Manages the controls after a click occurred on the player UI. * Create on-click listener which manages the player controls after the view on-click action.
* @param v The view that was clicked *
* @param runnable The action to be executed.
* @return The view click listener.
*/ */
public void manageControlsAfterOnClick(@NonNull final View v) { protected View.OnClickListener makeOnClickListener(@NonNull final Runnable runnable) {
if (player.getCurrentState() == STATE_COMPLETED) { return v -> {
return; if (DEBUG) {
} Log.d(TAG, "onClick() called with: v = [" + v + "]");
}
controlsVisibilityHandler.removeCallbacksAndMessages(null); runnable.run();
showHideShadow(true, DEFAULT_CONTROLS_DURATION);
animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION, // Manages the player controls after handling the view click.
AnimationType.ALPHA, 0, () -> { if (player.getCurrentState() == STATE_COMPLETED) {
if (player.getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible) { return;
if (v.getId() == binding.playPauseButton.getId() }
// Hide controls in fullscreen immediately controlsVisibilityHandler.removeCallbacksAndMessages(null);
|| (v.getId() == binding.screenRotationButton.getId() showHideShadow(true, DEFAULT_CONTROLS_DURATION);
&& isFullscreen())) { animate(binding.playbackControlRoot, true, DEFAULT_CONTROLS_DURATION,
hideControls(0, 0); AnimationType.ALPHA, 0, () -> {
} else { if (player.getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible) {
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); if (v == binding.playPauseButton
// Hide controls in fullscreen immediately
|| (v == binding.screenRotationButton && isFullscreen())) {
hideControls(0, 0);
} else {
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
}
} }
} });
}); };
}
@Override
public boolean onLongClick(final View v) {
if (v.getId() == binding.share.getId()) {
ShareUtils.copyToClipboard(context, player.getVideoUrlAtCurrentTime());
}
return true;
} }
public boolean onKeyDown(final int keyCode) { public boolean onKeyDown(final int keyCode) {