From a6e9a34024973d366b21b6461fa5cc3088e15bb8 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Mon, 3 May 2021 03:16:40 +0900 Subject: [PATCH] Switch to use exo controls --- .../adapters/SliderItemsAdapter.java | 9 +- .../viewholder/SliderVideoViewHolder.java | 27 +- .../viewholder/feed/FeedSliderViewHolder.java | 2 +- .../viewholder/feed/FeedVideoViewHolder.java | 2 +- .../customviews/VideoPlayerViewHelper.java | 505 +++++++++--------- .../fragments/PostViewV2Fragment.java | 240 ++++----- app/src/main/res/layout/dialog_post_view.xml | 60 +-- .../res/layout/layout_exo_custom_controls.xml | 163 ++++-- .../layout_video_player_with_thumbnail.xml | 29 +- 9 files changed, 556 insertions(+), 481 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/adapters/SliderItemsAdapter.java b/app/src/main/java/awais/instagrabber/adapters/SliderItemsAdapter.java index c805d316..615bff38 100644 --- a/app/src/main/java/awais/instagrabber/adapters/SliderItemsAdapter.java +++ b/app/src/main/java/awais/instagrabber/adapters/SliderItemsAdapter.java @@ -12,7 +12,6 @@ import awais.instagrabber.adapters.viewholder.SliderPhotoViewHolder; import awais.instagrabber.adapters.viewholder.SliderVideoViewHolder; import awais.instagrabber.customviews.VerticalDragHelper; import awais.instagrabber.databinding.ItemSliderPhotoBinding; -import awais.instagrabber.databinding.LayoutExoCustomControlsBinding; import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding; import awais.instagrabber.models.enums.MediaItemType; import awais.instagrabber.repositories.responses.Media; @@ -22,7 +21,7 @@ public final class SliderItemsAdapter extends ListAdapter DIFF_CALLBACK = new DiffUtil.ItemCallback() { @Override @@ -37,14 +36,14 @@ public final class SliderItemsAdapter extends ListAdapter { // final float newVol = videoPlayerViewHelper.toggleMute(); @@ -163,15 +162,15 @@ public class SliderVideoViewHolder extends SliderItemViewHolder { videoPlayerViewHelper.releasePlayer(); } - public void resetPlayerTimeline() { - if (videoPlayerViewHelper == null) return; - videoPlayerViewHelper.resetTimeline(); - } - - public void removeCallbacks() { - if (videoPlayerViewHelper == null) return; - videoPlayerViewHelper.removeCallbacks(); - } + // public void resetPlayerTimeline() { + // if (videoPlayerViewHelper == null) return; + // videoPlayerViewHelper.resetTimeline(); + // } + // + // public void removeCallbacks() { + // if (videoPlayerViewHelper == null) return; + // videoPlayerViewHelper.removeCallbacks(); + // } // private void setDimensions(final FeedModel feedModel, final int spanCount, final boolean animate) { // final ViewGroup.LayoutParams layoutParams = binding.imageViewer.getLayoutParams(); diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedSliderViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedSliderViewHolder.java index b9271d6f..3d5b5587 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedSliderViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedSliderViewHolder.java @@ -45,7 +45,7 @@ public class FeedSliderViewHolder extends FeedItemViewHolder { final String text = "1/" + sliderItemLen; binding.mediaCounter.setText(text); binding.mediaList.setOffscreenPageLimit(1); - final SliderItemsAdapter adapter = new SliderItemsAdapter(null, null, false, new SliderCallbackAdapter() { + final SliderItemsAdapter adapter = new SliderItemsAdapter(null, false, new SliderCallbackAdapter() { @Override public void onItemClicked(final int position) { feedItemCallback.onSliderClick(feedModel, position); diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedVideoViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedVideoViewHolder.java index 33ae8757..3d56551b 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedVideoViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedVideoViewHolder.java @@ -97,7 +97,7 @@ public class FeedVideoViewHolder extends FeedItemViewHolder { aspectRatio, ResponseBodyUtils.getThumbUrl(media), false, - null, + // null, videoPlayerCallback); binding.videoPost.thumbnail.post(() -> { if (media.getOriginalHeight() > 0.8 * Utils.displayMetrics.heightPixels) { diff --git a/app/src/main/java/awais/instagrabber/customviews/VideoPlayerViewHelper.java b/app/src/main/java/awais/instagrabber/customviews/VideoPlayerViewHelper.java index b8776bfd..56ed8976 100644 --- a/app/src/main/java/awais/instagrabber/customviews/VideoPlayerViewHelper.java +++ b/app/src/main/java/awais/instagrabber/customviews/VideoPlayerViewHelper.java @@ -3,14 +3,11 @@ package awais.instagrabber.customviews; import android.content.Context; import android.graphics.drawable.Animatable; import android.net.Uri; -import android.os.Handler; import android.os.Looper; import android.util.Log; import android.view.View; import androidx.annotation.NonNull; -import androidx.appcompat.view.ContextThemeWrapper; -import androidx.appcompat.widget.AppCompatTextView; import androidx.appcompat.widget.PopupMenu; import com.facebook.drawee.backends.pipeline.Fresco; @@ -21,103 +18,95 @@ import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequestBuilder; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.audio.AudioListener; import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.material.slider.LabelFormatter; -import com.google.android.material.slider.Slider; +import com.google.android.material.button.MaterialButton; import awais.instagrabber.R; -import awais.instagrabber.databinding.LayoutExoCustomControlsBinding; import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding; -import awais.instagrabber.utils.TextUtils; - -import static com.google.android.exoplayer2.C.TIME_UNSET; -import static com.google.android.exoplayer2.Player.STATE_ENDED; -import static com.google.android.exoplayer2.Player.STATE_IDLE; -import static com.google.android.exoplayer2.Player.STATE_READY; public class VideoPlayerViewHelper implements Player.EventListener { private static final String TAG = "VideoPlayerViewHelper"; - private static final long INITIAL_DELAY = 0; - private static final long RECURRING_DELAY = 60; + // private static final long INITIAL_DELAY = 0; + // private static final long RECURRING_DELAY = 60; private final Context context; - private final awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding binding; + private final LayoutVideoPlayerWithThumbnailBinding binding; private final float initialVolume; private final float thumbnailAspectRatio; private final String thumbnailUrl; private final boolean loadPlayerOnClick; - private final awais.instagrabber.databinding.LayoutExoCustomControlsBinding controlsBinding; + // private final LayoutExoCustomControlsBinding controlsBinding; private final VideoPlayerCallback videoPlayerCallback; private final String videoUrl; private final DefaultDataSourceFactory dataSourceFactory; private SimpleExoPlayer player; private PopupMenu speedPopup; - private PositionCheckRunnable positionChecker; - private Handler positionUpdateHandler; + // private PositionCheckRunnable positionChecker; + // private Handler positionUpdateHandler; - private final Player.EventListener listener = new Player.EventListener() { - @Override - public void onPlaybackStateChanged(final int state) { - switch (state) { - case Player.STATE_BUFFERING: - case STATE_IDLE: - case STATE_ENDED: - positionUpdateHandler.removeCallbacks(positionChecker); - return; - case STATE_READY: - setupTimeline(); - positionUpdateHandler.postDelayed(positionChecker, INITIAL_DELAY); - break; - } - } - - @Override - public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason) { - updatePlayPauseDrawable(playWhenReady); - if (positionUpdateHandler == null || positionChecker == null) return; - if (playWhenReady) { - positionUpdateHandler.removeCallbacks(positionChecker); - positionUpdateHandler.postDelayed(positionChecker, INITIAL_DELAY); - } - } - }; + // private final Player.EventListener listener = new Player.EventListener() { + // @Override + // public void onPlaybackStateChanged(final int state) { + // // switch (state) { + // // case Player.STATE_BUFFERING: + // // case STATE_IDLE: + // // case STATE_ENDED: + // // positionUpdateHandler.removeCallbacks(positionChecker); + // // return; + // // case STATE_READY: + // // setupTimeline(); + // // positionUpdateHandler.postDelayed(positionChecker, INITIAL_DELAY); + // // break; + // // } + // } + // + // @Override + // public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason) { + // // updatePlayPauseDrawable(playWhenReady); + // // if (positionUpdateHandler == null || positionChecker == null) return; + // // if (playWhenReady) { + // // positionUpdateHandler.removeCallbacks(positionChecker); + // // positionUpdateHandler.postDelayed(positionChecker, INITIAL_DELAY); + // // } + // } + // }; private final AudioListener audioListener = new AudioListener() { @Override public void onVolumeChanged(final float volume) { updateMuteIcon(volume); } }; - private final Slider.OnChangeListener onChangeListener = (slider, value, fromUser) -> { - if (!fromUser) return; - long actualValue = (long) value; - if (actualValue < 0) { - actualValue = 0; - } else if (actualValue > player.getDuration()) { - actualValue = player.getDuration(); - } - player.seekTo(actualValue); - }; - private final View.OnClickListener onClickListener = v -> player.setPlayWhenReady(!player.getPlayWhenReady()); - private final LabelFormatter labelFormatter = value -> TextUtils.millisToTimeString((long) value); + // private final Slider.OnChangeListener onChangeListener = (slider, value, fromUser) -> { + // if (!fromUser) return; + // long actualValue = (long) value; + // if (actualValue < 0) { + // actualValue = 0; + // } else if (actualValue > player.getDuration()) { + // actualValue = player.getDuration(); + // } + // player.seekTo(actualValue); + // }; + // private final View.OnClickListener onClickListener = v -> player.setPlayWhenReady(!player.getPlayWhenReady()); + // // private final LabelFormatter labelFormatter = value -> TextUtils.millisToTimeString((long) value); private final View.OnClickListener muteOnClickListener = v -> toggleMute(); - private final View.OnClickListener rewOnClickListener = v -> { - final long positionMs = player.getCurrentPosition() - 5000; - player.seekTo(positionMs < 0 ? 0 : positionMs); - }; - private final View.OnClickListener ffOnClickListener = v -> { - long positionMs = player.getCurrentPosition() + 5000; - long duration = player.getDuration(); - if (duration == TIME_UNSET) { - duration = 0; - } - player.seekTo(Math.min(positionMs, duration)); - }; - private final View.OnClickListener showMenu = this::showMenu; + private MaterialButton mute; + // private final View.OnClickListener rewOnClickListener = v -> { + // final long positionMs = player.getCurrentPosition() - 5000; + // player.seekTo(positionMs < 0 ? 0 : positionMs); + // }; + // private final View.OnClickListener ffOnClickListener = v -> { + // long positionMs = player.getCurrentPosition() + 5000; + // long duration = player.getDuration(); + // if (duration == TIME_UNSET) { + // duration = 0; + // } + // player.seekTo(Math.min(positionMs, duration)); + // }; + // private final View.OnClickListener showMenu = this::showMenu; public VideoPlayerViewHelper(@NonNull final Context context, @NonNull final LayoutVideoPlayerWithThumbnailBinding binding, @@ -126,7 +115,7 @@ public class VideoPlayerViewHelper implements Player.EventListener { final float thumbnailAspectRatio, final String thumbnailUrl, final boolean loadPlayerOnClick, - final LayoutExoCustomControlsBinding controlsBinding, + // final LayoutExoCustomControlsBinding controlsBinding, final VideoPlayerCallback videoPlayerCallback) { this.context = context; this.binding = binding; @@ -134,7 +123,7 @@ public class VideoPlayerViewHelper implements Player.EventListener { this.thumbnailAspectRatio = thumbnailAspectRatio; this.thumbnailUrl = thumbnailUrl; this.loadPlayerOnClick = loadPlayerOnClick; - this.controlsBinding = controlsBinding; + // this.controlsBinding = controlsBinding; this.videoPlayerCallback = videoPlayerCallback; this.videoUrl = videoUrl; this.dataSourceFactory = new DefaultDataSourceFactory(binding.getRoot().getContext(), "instagram"); @@ -151,7 +140,7 @@ public class VideoPlayerViewHelper implements Player.EventListener { } }); setThumbnail(); - setupControls(); + // setupControls(); } private void setThumbnail() { @@ -200,12 +189,13 @@ public class VideoPlayerViewHelper implements Player.EventListener { player = new SimpleExoPlayer.Builder(context) .setLooper(Looper.getMainLooper()) .build(); - positionUpdateHandler = new Handler(); - positionChecker = new PositionCheckRunnable(positionUpdateHandler, - player, - controlsBinding.timeline, - controlsBinding.fromTime); + // positionUpdateHandler = new Handler(); + // positionChecker = new PositionCheckRunnable(positionUpdateHandler, + // player, + // controlsBinding.timeline, + // controlsBinding.fromTime); player.addListener(this); + player.addAudioListener(audioListener); player.setVolume(initialVolume); player.setPlayWhenReady(true); player.setRepeatMode(Player.REPEAT_MODE_ALL); @@ -213,124 +203,134 @@ public class VideoPlayerViewHelper implements Player.EventListener { final MediaItem mediaItem = MediaItem.fromUri(videoUrl); final ProgressiveMediaSource mediaSource = sourceFactory.createMediaSource(mediaItem); player.setMediaSource(mediaSource); - setupControls(); + // setupControls(); player.prepare(); binding.playerView.setPlayer(player); - } - - private void setupControls() { - if (controlsBinding == null) return; - binding.playerView.setUseController(false); - if (player == null) { - enableControls(false); - // controlsBinding.playPause.setEnabled(true); - // controlsBinding.playPause.setOnClickListener(new NoPlayerPlayPauseClickListener(binding.thumbnailParent)); - return; + binding.playerView.setShowFastForwardButton(false); + binding.playerView.setShowRewindButton(false); + // binding.controls.setPlayer(player); + mute = binding.playerView.findViewById(R.id.mute); + // mute = binding.controls.findViewById(R.id.mute); + if (mute != null) { + mute.setOnClickListener(muteOnClickListener); } - enableControls(true); - updatePlayPauseDrawable(player.getPlayWhenReady()); updateMuteIcon(player.getVolume()); - player.addListener(listener); - player.addAudioListener(audioListener); - controlsBinding.timeline.addOnChangeListener(onChangeListener); - controlsBinding.timeline.setLabelFormatter(labelFormatter); - controlsBinding.playPause.setOnClickListener(onClickListener); - controlsBinding.mute.setOnClickListener(muteOnClickListener); - controlsBinding.rewWithAmount.setOnClickListener(rewOnClickListener); - controlsBinding.ffWithAmount.setOnClickListener(ffOnClickListener); - controlsBinding.speed.setOnClickListener(showMenu); } - private void setupTimeline() { - final long duration = player.getDuration(); - controlsBinding.timeline.setEnabled(true); - controlsBinding.timeline.setValueFrom(0); - controlsBinding.timeline.setValueTo(duration); - controlsBinding.fromTime.setText(TextUtils.millisToTimeString(0)); - controlsBinding.toTime.setText(TextUtils.millisToTimeString(duration)); - } + // private void setupControls() { + // if (controlsBinding == null) return; + // // binding.playerView.setUseController(false); + // if (player == null) { + // // enableControls(false); + // // controlsBinding.playPause.setEnabled(true); + // // controlsBinding.playPause.setOnClickListener(new NoPlayerPlayPauseClickListener(binding.thumbnailParent)); + // return; + // } + // // enableControls(true); + // // updatePlayPauseDrawable(player.getPlayWhenReady()); + // // updateMuteIcon(player.getVolume()); + // player.addListener(listener); + // // player.addAudioListener(audioListener); + // // controlsBinding.timeline.addOnChangeListener(onChangeListener); + // // controlsBinding.timeline.setLabelFormatter(labelFormatter); + // // controlsBinding.playPause.setOnClickListener(onClickListener); + // // controlsBinding.mute.setOnClickListener(muteOnClickListener); + // // controlsBinding.rewWithAmount.setOnClickListener(rewOnClickListener); + // // controlsBinding.ffWithAmount.setOnClickListener(ffOnClickListener); + // // controlsBinding.speed.setOnClickListener(showMenu); + // } - private void enableControls(final boolean enable) { - controlsBinding.speed.setEnabled(enable); - controlsBinding.speed.setClickable(enable); - controlsBinding.mute.setEnabled(enable); - controlsBinding.mute.setClickable(enable); - controlsBinding.ffWithAmount.setEnabled(enable); - controlsBinding.ffWithAmount.setClickable(enable); - controlsBinding.rewWithAmount.setEnabled(enable); - controlsBinding.rewWithAmount.setClickable(enable); - controlsBinding.fromTime.setEnabled(enable); - controlsBinding.toTime.setEnabled(enable); - controlsBinding.playPause.setEnabled(enable); - controlsBinding.playPause.setClickable(enable); - controlsBinding.timeline.setEnabled(enable); - } + // private void setupTimeline() { + // final long duration = player.getDuration(); + // controlsBinding.timeline.setEnabled(true); + // controlsBinding.timeline.setValueFrom(0); + // controlsBinding.timeline.setValueTo(duration); + // controlsBinding.fromTime.setText(TextUtils.millisToTimeString(0)); + // controlsBinding.toTime.setText(TextUtils.millisToTimeString(duration)); + // } - public void showMenu(View anchor) { - PopupMenu popup = getPopupMenu(anchor); - popup.show(); - } + // private void enableControls(final boolean enable) { + // controlsBinding.speed.setEnabled(enable); + // controlsBinding.speed.setClickable(enable); + // controlsBinding.mute.setEnabled(enable); + // controlsBinding.mute.setClickable(enable); + // controlsBinding.ffWithAmount.setEnabled(enable); + // controlsBinding.ffWithAmount.setClickable(enable); + // controlsBinding.rewWithAmount.setEnabled(enable); + // controlsBinding.rewWithAmount.setClickable(enable); + // // controlsBinding.fromTime.setEnabled(enable); + // // controlsBinding.toTime.setEnabled(enable); + // controlsBinding.playPause.setEnabled(enable); + // controlsBinding.playPause.setClickable(enable); + // // controlsBinding.timeline.setEnabled(enable); + // } - @NonNull - private PopupMenu getPopupMenu(final View anchor) { - if (speedPopup != null) { - return speedPopup; - } - final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.popupMenuStyle); - // final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.Widget_MaterialComponents_PopupMenu_Exoplayer); - speedPopup = new PopupMenu(themeWrapper, anchor); - speedPopup.getMenuInflater().inflate(R.menu.speed_menu, speedPopup.getMenu()); - speedPopup.setOnMenuItemClickListener(item -> { - float nextSpeed; - int textResId; - int itemId = item.getItemId(); - if (itemId == R.id.pt_two_five_x) { - nextSpeed = 0.25f; - textResId = R.string.pt_two_five_x; - } else if (itemId == R.id.pt_five_x) { - nextSpeed = 0.5f; - textResId = R.string.pt_five_x; - } else if (itemId == R.id.pt_seven_five_x) { - nextSpeed = 0.75f; - textResId = R.string.pt_seven_five_x; - } else if (itemId == R.id.one_x) { - nextSpeed = 1f; - textResId = R.string.one_x; - } else if (itemId == R.id.one_pt_two_five_x) { - nextSpeed = 1.25f; - textResId = R.string.one_pt_two_five_x; - } else if (itemId == R.id.one_pt_five_x) { - nextSpeed = 1.5f; - textResId = R.string.one_pt_five_x; - } else if (itemId == R.id.two_x) { - nextSpeed = 2f; - textResId = R.string.two_x; - } else { - nextSpeed = 1; - textResId = R.string.one_x; - } - player.setPlaybackParameters(new PlaybackParameters(nextSpeed)); - controlsBinding.speed.setText(textResId); - return true; - }); - return speedPopup; - } + // public void showMenu(View anchor) { + // PopupMenu popup = getPopupMenu(anchor); + // popup.show(); + // } + + // @NonNull + // private PopupMenu getPopupMenu(final View anchor) { + // if (speedPopup != null) { + // return speedPopup; + // } + // final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.popupMenuStyle); + // // final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(context, R.style.Widget_MaterialComponents_PopupMenu_Exoplayer); + // speedPopup = new PopupMenu(themeWrapper, anchor); + // speedPopup.getMenuInflater().inflate(R.menu.speed_menu, speedPopup.getMenu()); + // speedPopup.setOnMenuItemClickListener(item -> { + // float nextSpeed; + // int textResId; + // int itemId = item.getItemId(); + // if (itemId == R.id.pt_two_five_x) { + // nextSpeed = 0.25f; + // textResId = R.string.pt_two_five_x; + // } else if (itemId == R.id.pt_five_x) { + // nextSpeed = 0.5f; + // textResId = R.string.pt_five_x; + // } else if (itemId == R.id.pt_seven_five_x) { + // nextSpeed = 0.75f; + // textResId = R.string.pt_seven_five_x; + // } else if (itemId == R.id.one_x) { + // nextSpeed = 1f; + // textResId = R.string.one_x; + // } else if (itemId == R.id.one_pt_two_five_x) { + // nextSpeed = 1.25f; + // textResId = R.string.one_pt_two_five_x; + // } else if (itemId == R.id.one_pt_five_x) { + // nextSpeed = 1.5f; + // textResId = R.string.one_pt_five_x; + // } else if (itemId == R.id.two_x) { + // nextSpeed = 2f; + // textResId = R.string.two_x; + // } else { + // nextSpeed = 1; + // textResId = R.string.one_x; + // } + // player.setPlaybackParameters(new PlaybackParameters(nextSpeed)); + // controlsBinding.speed.setText(textResId); + // return true; + // }); + // return speedPopup; + // } private void updateMuteIcon(final float volume) { + if (mute == null) return; if (volume == 0) { - controlsBinding.mute.setIconResource(R.drawable.ic_volume_off_24_states); + mute.setIconResource(R.drawable.ic_volume_off_24_states); return; } - controlsBinding.mute.setIconResource(R.drawable.ic_volume_up_24_states); + mute.setIconResource(R.drawable.ic_volume_up_24_states); } - private void updatePlayPauseDrawable(final boolean playWhenReady) { - if (playWhenReady) { - controlsBinding.playPause.setIconResource(R.drawable.ic_pause_24); - return; - } - controlsBinding.playPause.setIconResource(R.drawable.ic_play_states); - } + // private void updatePlayPauseDrawable(final boolean playWhenReady) { + // if (playWhenReady) { + // controlsBinding.playPause.setIconResource(R.drawable.ic_pause_24); + // return; + // } + // controlsBinding.playPause.setIconResource(R.drawable.ic_play_states); + // } @Override public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason) { @@ -343,15 +343,14 @@ public class VideoPlayerViewHelper implements Player.EventListener { } @Override - public void onPlayerError(final ExoPlaybackException error) { + public void onPlayerError(@NonNull final ExoPlaybackException error) { Log.e(TAG, "onPlayerError", error); } - public float toggleMute() { - if (player == null) return 0; + private void toggleMute() { + if (player == null) return; final float vol = player.getVolume() == 0f ? 1f : 0f; player.setVolume(vol); - return vol; } // public void togglePlayback() { @@ -370,85 +369,85 @@ public class VideoPlayerViewHelper implements Player.EventListener { player.release(); player = null; } - if (positionUpdateHandler != null) { - if (positionChecker != null) { - positionUpdateHandler.removeCallbacks(positionChecker); - positionChecker = null; - } - positionUpdateHandler = null; - } + // if (positionUpdateHandler != null) { + // if (positionChecker != null) { + // positionUpdateHandler.removeCallbacks(positionChecker); + // positionChecker = null; + // } + // positionUpdateHandler = null; + // } } public void pause() { if (player != null) { player.pause(); } - if (positionUpdateHandler != null) { - if (positionChecker != null) { - positionUpdateHandler.removeCallbacks(positionChecker); - } - } + // if (positionUpdateHandler != null) { + // if (positionChecker != null) { + // positionUpdateHandler.removeCallbacks(positionChecker); + // } + // } } - public void resetTimeline() { - if (player == null) { - enableControls(false); - return; - } - setupTimeline(); - final long currentPosition = player.getCurrentPosition(); - controlsBinding.timeline.setValue(Math.min(currentPosition, player.getDuration())); - setupControls(); - } + // public void resetTimeline() { + // if (player == null) { + // enableControls(false); + // return; + // } + // setupTimeline(); + // final long currentPosition = player.getCurrentPosition(); + // controlsBinding.timeline.setValue(Math.min(currentPosition, player.getDuration())); + // setupControls(); + // } - public void removeCallbacks() { - if (player != null) { - player.removeListener(listener); - player.removeAudioListener(audioListener); - } - controlsBinding.timeline.removeOnChangeListener(onChangeListener); - controlsBinding.timeline.setLabelFormatter(null); - controlsBinding.playPause.setOnClickListener(null); - controlsBinding.mute.setOnClickListener(null); - controlsBinding.rewWithAmount.setOnClickListener(null); - controlsBinding.ffWithAmount.setOnClickListener(null); - controlsBinding.speed.setOnClickListener(null); - } + // public void removeCallbacks() { + // if (player != null) { + // player.removeListener(listener); + // player.removeAudioListener(audioListener); + // } + // controlsBinding.timeline.removeOnChangeListener(onChangeListener); + // controlsBinding.timeline.setLabelFormatter(null); + // controlsBinding.playPause.setOnClickListener(null); + // controlsBinding.mute.setOnClickListener(null); + // controlsBinding.rewWithAmount.setOnClickListener(null); + // controlsBinding.ffWithAmount.setOnClickListener(null); + // controlsBinding.speed.setOnClickListener(null); + // } - private static class PositionCheckRunnable implements Runnable { - private final Handler positionUpdateHandler; - private final SimpleExoPlayer player; - private final Slider timeline; - private final AppCompatTextView fromTime; - - public PositionCheckRunnable(final Handler positionUpdateHandler, - final SimpleExoPlayer simpleExoPlayer, - final Slider slider, - final AppCompatTextView fromTime) { - this.positionUpdateHandler = positionUpdateHandler; - this.player = simpleExoPlayer; - this.timeline = slider; - this.fromTime = fromTime; - } - - @Override - public void run() { - if (positionUpdateHandler == null) return; - positionUpdateHandler.removeCallbacks(this); - if (player == null) return; - final long currentPosition = player.getCurrentPosition(); - final long duration = player.getDuration(); - if (duration == TIME_UNSET) { - timeline.setValueFrom(0); - timeline.setValueTo(0); - timeline.setEnabled(false); - return; - } - timeline.setValue(Math.min(currentPosition, duration)); - fromTime.setText(TextUtils.millisToTimeString(currentPosition)); - positionUpdateHandler.postDelayed(this, RECURRING_DELAY); - } - } + // private static class PositionCheckRunnable implements Runnable { + // private final Handler positionUpdateHandler; + // private final SimpleExoPlayer player; + // private final Slider timeline; + // private final AppCompatTextView fromTime; + // + // public PositionCheckRunnable(final Handler positionUpdateHandler, + // final SimpleExoPlayer simpleExoPlayer, + // final Slider slider, + // final AppCompatTextView fromTime) { + // this.positionUpdateHandler = positionUpdateHandler; + // this.player = simpleExoPlayer; + // this.timeline = slider; + // this.fromTime = fromTime; + // } + // + // @Override + // public void run() { + // if (positionUpdateHandler == null) return; + // positionUpdateHandler.removeCallbacks(this); + // if (player == null) return; + // final long currentPosition = player.getCurrentPosition(); + // final long duration = player.getDuration(); + // if (duration == TIME_UNSET) { + // timeline.setValueFrom(0); + // timeline.setValueTo(0); + // timeline.setEnabled(false); + // return; + // } + // timeline.setValue(Math.min(currentPosition, duration)); + // fromTime.setText(TextUtils.millisToTimeString(currentPosition)); + // positionUpdateHandler.postDelayed(this, RECURRING_DELAY); + // } + // } public interface VideoPlayerCallback { void onThumbnailLoaded(); diff --git a/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java b/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java index dc37c372..9f79871e 100644 --- a/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java @@ -27,7 +27,6 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.ViewAnimationUtils; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; @@ -44,7 +43,6 @@ import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.widget.PopupMenu; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.PermissionChecker; -import androidx.core.view.ViewCompat; import androidx.core.widget.NestedScrollView; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentActivity; @@ -119,10 +117,11 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im // private MediaService mediaService; private Context context; private BottomSheetBehavior bottomSheetBehavior; - private boolean detailsVisible = true, video; + private boolean detailsVisible = true; + private boolean video; private VideoPlayerViewHelper videoPlayerViewHelper; private SliderItemsAdapter sliderItemsAdapter; - private boolean wasControlsVisible; + // private boolean wasControlsVisible; private boolean wasPaused; private int captionState = BottomSheetBehavior.STATE_HIDDEN; private int sliderPosition = -1; @@ -883,9 +882,9 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im switch (bottomSheetBehavior.getState()) { case BottomSheetBehavior.STATE_HIDDEN: binding.captionParent.fullScroll(ScrollView.FOCUS_UP); // reset scroll position - if (binding.playerControls.getRoot().getVisibility() == View.VISIBLE) { - hidePlayerControls(); - } + // if (binding.playerControls.getRoot().getVisibility() == View.VISIBLE) { + // hidePlayerControls(); + // } bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); return; case BottomSheetBehavior.STATE_COLLAPSED: @@ -993,8 +992,8 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im private void setupPostImage() { binding.videoPost.root.setVisibility(View.GONE); binding.sliderParent.setVisibility(View.GONE); - binding.playerControlsToggle.setVisibility(View.GONE); - binding.playerControls.getRoot().setVisibility(View.GONE); + // binding.playerControlsToggle.setVisibility(View.GONE); + // binding.playerControls.getRoot().setVisibility(View.GONE); binding.mediaCounter.setVisibility(View.GONE); binding.postImage.setVisibility(View.VISIBLE); if (!wasPaused && sharedMainPostElement != null) { @@ -1049,8 +1048,8 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im final Media media = viewModel.getMedia(); binding.postImage.setVisibility(View.GONE); binding.videoPost.root.setVisibility(View.GONE); - binding.playerControlsToggle.setVisibility(View.GONE); - binding.playerControls.getRoot().setVisibility(View.GONE); + // binding.playerControlsToggle.setVisibility(View.GONE); + // binding.playerControls.getRoot().setVisibility(View.GONE); binding.sliderParent.setVisibility(View.VISIBLE); binding.mediaCounter.setVisibility(View.VISIBLE); if (!wasPaused && sharedMainPostElement != null) { @@ -1070,7 +1069,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im }); } } - sliderItemsAdapter = new SliderItemsAdapter(null, binding.playerControls, true, new SliderCallbackAdapter() { + sliderItemsAdapter = new SliderItemsAdapter(null, true, new SliderCallbackAdapter() { @Override public void onThumbnailLoaded(final int position) { if (position != 0) return; @@ -1087,8 +1086,8 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im final FragmentActivity activity = getActivity(); if (activity == null) return; Utils.enabledKeepScreenOn(activity); - if (!detailsVisible || hasBeenToggled) return; - showPlayerControls(); + // if (!detailsVisible || hasBeenToggled) return; + // showPlayerControls(); } @Override @@ -1137,27 +1136,29 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im binding.mediaCounter.setText(text); final Media childMedia = media.getCarouselMedia().get(position); final View view = binding.sliderParent.getChildAt(0); - if (prevPosition != -1) { - if (view instanceof RecyclerView) { - final RecyclerView.ViewHolder viewHolder = ((RecyclerView) view).findViewHolderForAdapterPosition(prevPosition); - if (viewHolder instanceof SliderVideoViewHolder) { - ((SliderVideoViewHolder) viewHolder).removeCallbacks(); - } - } - } + // if (prevPosition != -1) { + // if (view instanceof RecyclerView) { + // final RecyclerView.ViewHolder viewHolder = ((RecyclerView) view).findViewHolderForAdapterPosition(prevPosition); + // if (viewHolder instanceof SliderVideoViewHolder) { + // ((SliderVideoViewHolder) viewHolder).removeCallbacks(); + // } + // } + // } + video = false; if (childMedia.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO) { - if (view instanceof RecyclerView) { - final RecyclerView.ViewHolder viewHolder = ((RecyclerView) view).findViewHolderForAdapterPosition(position); - if (viewHolder instanceof SliderVideoViewHolder) { - ((SliderVideoViewHolder) viewHolder).resetPlayerTimeline(); - } - } - enablePlayerControls(true); + // if (view instanceof RecyclerView) { + // final RecyclerView.ViewHolder viewHolder = ((RecyclerView) view).findViewHolderForAdapterPosition(position); + // if (viewHolder instanceof SliderVideoViewHolder) { + // ((SliderVideoViewHolder) viewHolder).resetPlayerTimeline(); + // } + // } + // enablePlayerControls(true); + video = true; viewModel.setViewCount(childMedia.getViewCount()); return; } viewModel.setViewCount(null); - enablePlayerControls(false); + // enablePlayerControls(false); } private void pausePlayerAtPosition(final int position, final RecyclerView view) { @@ -1196,6 +1197,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im @SuppressLint("ClickableViewAccessibility") private void setupVideo() { + video = true; final Media media = viewModel.getMedia(); binding.postImage.setVisibility(View.GONE); binding.sliderParent.setVisibility(View.GONE); @@ -1211,7 +1213,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im // final VerticalDragHelper playerVerticalDragHelper = new VerticalDragHelper(binding.videoPost.playerView); // thumbnailVerticalDragHelper.setOnVerticalDragListener(onVerticalDragListener); // playerVerticalDragHelper.setOnVerticalDragListener(onVerticalDragListener); - enablePlayerControls(true); + // enablePlayerControls(true); // binding.videoPost.thumbnailParent.setOnTouchListener((v, event) -> { // final boolean onDragTouch = thumbnailVerticalDragHelper.onDragTouch(event); // if (onDragTouch) { @@ -1293,96 +1295,96 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im aspectRatio, ResponseBodyUtils.getThumbUrl(media), true, - binding.playerControls, + // /*binding.playerControls*/null, videoPlayerCallback); } } - private void enablePlayerControls(final boolean enable) { - video = enable; - if (enable) { - binding.playerControlsToggle.setVisibility(View.VISIBLE); - binding.playerControlsToggle.setOnClickListener(v -> { - final int visibility = binding.playerControls.getRoot().getVisibility(); - if (visibility == View.GONE) { - showPlayerControls(); - return; - } - hidePlayerControls(); - }); - return; - } - binding.playerControlsToggle.setVisibility(View.GONE); - hidePlayerControls(); - } + // private void enablePlayerControls(final boolean enable) { + // video = enable; + // if (enable) { + // binding.playerControlsToggle.setVisibility(View.VISIBLE); + // binding.playerControlsToggle.setOnClickListener(v -> { + // final int visibility = binding.playerControls.getRoot().getVisibility(); + // if (visibility == View.GONE) { + // showPlayerControls(); + // return; + // } + // hidePlayerControls(); + // }); + // return; + // } + // binding.playerControlsToggle.setVisibility(View.GONE); + // hidePlayerControls(); + // } private void hideCaption() { if (bottomSheetBehavior == null) return; bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); } - private void showPlayerControls() { - hideCaption(); - // previously invisible view - View view = binding.playerControls.getRoot(); - if (view.getVisibility() == View.VISIBLE) { - return; - } - if (!ViewCompat.isAttachedToWindow(view)) { - view.setVisibility(View.VISIBLE); - return; - } - // get the center for the clipping circle - int cx = view.getWidth() / 2; - // int cy = view.getHeight() / 2; - int cy = view.getHeight(); + // private void showPlayerControls() { + // hideCaption(); + // // previously invisible view + // View view = binding.playerControls.getRoot(); + // if (view.getVisibility() == View.VISIBLE) { + // return; + // } + // if (!ViewCompat.isAttachedToWindow(view)) { + // view.setVisibility(View.VISIBLE); + // return; + // } + // // get the center for the clipping circle + // int cx = view.getWidth() / 2; + // // int cy = view.getHeight() / 2; + // int cy = view.getHeight(); + // + // // get the final radius for the clipping circle + // float finalRadius = (float) Math.hypot(cx, cy); + // + // // create the animator for this view (the start radius is zero) + // Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0f, finalRadius); + // + // // make the view visible and start the animation + // view.setVisibility(View.VISIBLE); + // anim.start(); + // + // } - // get the final radius for the clipping circle - float finalRadius = (float) Math.hypot(cx, cy); - - // create the animator for this view (the start radius is zero) - Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0f, finalRadius); - - // make the view visible and start the animation - view.setVisibility(View.VISIBLE); - anim.start(); - - } - - private void hidePlayerControls() { - // previously visible view - final View view = binding.playerControls.getRoot(); - if (view.getVisibility() == View.GONE) { - return; - } - if (!ViewCompat.isAttachedToWindow(view)) { - view.setVisibility(View.GONE); - return; - } - - // get the center for the clipping circle - int cx = view.getWidth() / 2; - // int cy = view.getHeight() / 2; - int cy = view.getHeight(); - - // get the initial radius for the clipping circle - float initialRadius = (float) Math.hypot(cx, cy); - - // create the animation (the final radius is zero) - Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, 0f); - - // make the view invisible when the animation is done - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - view.setVisibility(View.GONE); - } - }); - - // start the animation - anim.start(); - } + // private void hidePlayerControls() { + // // previously visible view + // final View view = binding.playerControls.getRoot(); + // if (view.getVisibility() == View.GONE) { + // return; + // } + // if (!ViewCompat.isAttachedToWindow(view)) { + // view.setVisibility(View.GONE); + // return; + // } + // + // // get the center for the clipping circle + // int cx = view.getWidth() / 2; + // // int cy = view.getHeight() / 2; + // int cy = view.getHeight(); + // + // // get the initial radius for the clipping circle + // float initialRadius = (float) Math.hypot(cx, cy); + // + // // create the animation (the final radius is zero) + // Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, 0f); + // + // // make the view invisible when the animation is done + // anim.addListener(new AnimatorListenerAdapter() { + // @Override + // public void onAnimationEnd(Animator animation) { + // super.onAnimationEnd(animation); + // view.setVisibility(View.GONE); + // } + // }); + // + // // start the animation + // anim.start(); + // } private void setupOptions(final Boolean show) { if (!show) { @@ -1536,7 +1538,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im binding.date.setVisibility(View.GONE); binding.comment.setVisibility(View.GONE); binding.captionToggle.setVisibility(View.GONE); - binding.playerControlsToggle.setVisibility(View.GONE); + // binding.playerControlsToggle.setVisibility(View.GONE); binding.like.setVisibility(View.GONE); binding.save.setVisibility(View.GONE); binding.share.setVisibility(View.GONE); @@ -1547,10 +1549,10 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im if (options != null && !options.isEmpty()) { binding.options.setVisibility(View.GONE); } - wasControlsVisible = binding.playerControls.getRoot().getVisibility() == View.VISIBLE; - if (wasControlsVisible) { - hidePlayerControls(); - } + // wasControlsVisible = binding.playerControls.getRoot().getVisibility() == View.VISIBLE; + // if (wasControlsVisible) { + // hidePlayerControls(); + // } return; } if (media.getUser() != null) { @@ -1584,12 +1586,12 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im binding.save.setVisibility(View.VISIBLE); } if (video) { - binding.playerControlsToggle.setVisibility(View.VISIBLE); + // binding.playerControlsToggle.setVisibility(View.VISIBLE); binding.viewsCount.setVisibility(View.VISIBLE); } - if (wasControlsVisible) { - showPlayerControls(); - } + // if (wasControlsVisible) { + // showPlayerControls(); + // } if (media.getMediaType() == MediaItemType.MEDIA_TYPE_SLIDER) { binding.mediaCounter.setVisibility(View.VISIBLE); } diff --git a/app/src/main/res/layout/dialog_post_view.xml b/app/src/main/res/layout/dialog_post_view.xml index b56dd31c..f843c15d 100644 --- a/app/src/main/res/layout/dialog_post_view.xml +++ b/app/src/main/res/layout/dialog_post_view.xml @@ -164,7 +164,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - tools:visibility="gone"> + tools:visibility="visible"> - + + + + + + + + + + - + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/layout_exo_custom_controls.xml b/app/src/main/res/layout/layout_exo_custom_controls.xml index 4292ebbc..14fe87a7 100644 --- a/app/src/main/res/layout/layout_exo_custom_controls.xml +++ b/app/src/main/res/layout/layout_exo_custom_controls.xml @@ -3,52 +3,83 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@color/black_a80" - android:padding="8dp"> + android:layout_height="match_parent"> + + + + + + + + + - + + + + + + + + + + + + + + + + + + + app:layout_constraintBottom_toTopOf="@id/progress_barrier" + app:layout_constraintEnd_toStartOf="@id/exo_duration" + app:layout_constraintStart_toEndOf="@id/exo_position" + app:layout_constraintVertical_bias="1" + app:layout_constraintVertical_chainStyle="packed" /> + + - + @@ -101,25 +138,47 @@ app:icon="@drawable/ic_volume_off_24_states" app:iconSize="24dp" app:iconTint="@color/white" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toStartOf="@id/speed" - app:layout_constraintStart_toEndOf="@id/ff_with_amount" - app:layout_constraintTop_toBottomOf="@id/timeline" + app:layout_constraintBottom_toTopOf="@id/bottom_barrier" + app:layout_constraintEnd_toStartOf="@id/exo_settings" + app:layout_constraintStart_toEndOf="@id/exo_ffwd_with_amount" + app:layout_constraintTop_toBottomOf="@id/progress_barrier" tools:enabled="false" tools:visibility="visible" /> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_video_player_with_thumbnail.xml b/app/src/main/res/layout/layout_video_player_with_thumbnail.xml index c1ee50c3..84075752 100644 --- a/app/src/main/res/layout/layout_video_player_with_thumbnail.xml +++ b/app/src/main/res/layout/layout_video_player_with_thumbnail.xml @@ -25,11 +25,28 @@ app:srcCompat="@drawable/ic_video_24" /> - + android:layout_height="match_parent"> + + + + + + + + + + + + \ No newline at end of file