mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 11:35:34 +00:00 
			
		
		
		
	Add fullscreen mode to post view
This commit is contained in:
		
							parent
							
								
									3dde61d91a
								
							
						
					
					
						commit
						5744a1a687
					
				| @ -1,11 +1,17 @@ | ||||
| package awais.instagrabber.adapters; | ||||
| 
 | ||||
| import android.view.View; | ||||
| 
 | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerView; | ||||
| 
 | ||||
| import awais.instagrabber.repositories.responses.Media; | ||||
| 
 | ||||
| public class SliderCallbackAdapter implements SliderItemsAdapter.SliderCallback { | ||||
|     @Override | ||||
|     public void onThumbnailLoaded(final int position) {} | ||||
| 
 | ||||
|     @Override | ||||
|     public void onItemClicked(final int position) {} | ||||
|     public void onItemClicked(final int position, final Media media, final View view) {} | ||||
| 
 | ||||
|     @Override | ||||
|     public void onPlayerPlay(final int position) {} | ||||
| @ -15,4 +21,12 @@ public class SliderCallbackAdapter implements SliderItemsAdapter.SliderCallback | ||||
| 
 | ||||
|     @Override | ||||
|     public void onPlayerRelease(final int position) {} | ||||
| 
 | ||||
|     @Override | ||||
|     public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {} | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isInFullScreen() { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,16 +1,18 @@ | ||||
| package awais.instagrabber.adapters; | ||||
| 
 | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.recyclerview.widget.DiffUtil; | ||||
| import androidx.recyclerview.widget.ListAdapter; | ||||
| 
 | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerView; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.viewholder.SliderItemViewHolder; | ||||
| 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.LayoutVideoPlayerWithThumbnailBinding; | ||||
| import awais.instagrabber.models.enums.MediaItemType; | ||||
| @ -18,10 +20,8 @@ import awais.instagrabber.repositories.responses.Media; | ||||
| 
 | ||||
| public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewHolder> { | ||||
| 
 | ||||
|     private final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener; | ||||
|     private final boolean loadVideoOnItemClick; | ||||
|     private final SliderCallback sliderCallback; | ||||
|     // private final LayoutExoCustomControlsBinding controlsBinding; | ||||
| 
 | ||||
|     private static final DiffUtil.ItemCallback<Media> DIFF_CALLBACK = new DiffUtil.ItemCallback<Media>() { | ||||
|         @Override | ||||
| @ -35,15 +35,11 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     public SliderItemsAdapter(final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener, | ||||
|                               // final LayoutExoCustomControlsBinding controlsBinding, | ||||
|                               final boolean loadVideoOnItemClick, | ||||
|     public SliderItemsAdapter(final boolean loadVideoOnItemClick, | ||||
|                               final SliderCallback sliderCallback) { | ||||
|         super(DIFF_CALLBACK); | ||||
|         this.onVerticalDragListener = onVerticalDragListener; | ||||
|         this.loadVideoOnItemClick = loadVideoOnItemClick; | ||||
|         this.sliderCallback = sliderCallback; | ||||
|         // this.controlsBinding = controlsBinding; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
| @ -54,12 +50,12 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH | ||||
|         switch (mediaItemType) { | ||||
|             case MEDIA_TYPE_VIDEO: { | ||||
|                 final LayoutVideoPlayerWithThumbnailBinding binding = LayoutVideoPlayerWithThumbnailBinding.inflate(inflater, parent, false); | ||||
|                 return new SliderVideoViewHolder(binding, onVerticalDragListener, loadVideoOnItemClick); | ||||
|                 return new SliderVideoViewHolder(binding, loadVideoOnItemClick); | ||||
|             } | ||||
|             case MEDIA_TYPE_IMAGE: | ||||
|             default: | ||||
|                 final ItemSliderPhotoBinding binding = ItemSliderPhotoBinding.inflate(inflater, parent, false); | ||||
|                 return new SliderPhotoViewHolder(binding, onVerticalDragListener); | ||||
|                 return new SliderPhotoViewHolder(binding); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -142,12 +138,16 @@ public final class SliderItemsAdapter extends ListAdapter<Media, SliderItemViewH | ||||
|     public interface SliderCallback { | ||||
|         void onThumbnailLoaded(int position); | ||||
| 
 | ||||
|         void onItemClicked(int position); | ||||
|         void onItemClicked(int position, final Media media, final View view); | ||||
| 
 | ||||
|         void onPlayerPlay(int position); | ||||
| 
 | ||||
|         void onPlayerPause(int position); | ||||
| 
 | ||||
|         void onPlayerRelease(int position); | ||||
| 
 | ||||
|         void onFullScreenModeChanged(boolean isFullScreen, final StyledPlayerView playerView); | ||||
| 
 | ||||
|         boolean isInFullScreen(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,7 +2,6 @@ package awais.instagrabber.adapters.viewholder; | ||||
| 
 | ||||
| import android.graphics.drawable.Animatable; | ||||
| import android.net.Uri; | ||||
| import android.view.GestureDetector; | ||||
| import android.view.MotionEvent; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| @ -14,8 +13,8 @@ import com.facebook.imagepipeline.request.ImageRequest; | ||||
| import com.facebook.imagepipeline.request.ImageRequestBuilder; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.SliderItemsAdapter; | ||||
| import awais.instagrabber.customviews.VerticalDragHelper; | ||||
| import awais.instagrabber.customviews.drawee.AnimatedZoomableController; | ||||
| import awais.instagrabber.customviews.drawee.DoubleTapGestureListener; | ||||
| import awais.instagrabber.databinding.ItemSliderPhotoBinding; | ||||
| import awais.instagrabber.repositories.responses.Media; | ||||
| import awais.instagrabber.utils.ResponseBodyUtils; | ||||
| @ -24,13 +23,10 @@ public class SliderPhotoViewHolder extends SliderItemViewHolder { | ||||
|     private static final String TAG = "FeedSliderPhotoViewHolder"; | ||||
| 
 | ||||
|     private final ItemSliderPhotoBinding binding; | ||||
|     private final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener; | ||||
| 
 | ||||
|     public SliderPhotoViewHolder(@NonNull final ItemSliderPhotoBinding binding, | ||||
|                                  final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener) { | ||||
|     public SliderPhotoViewHolder(@NonNull final ItemSliderPhotoBinding binding) { | ||||
|         super(binding.getRoot()); | ||||
|         this.binding = binding; | ||||
|         this.onVerticalDragListener = onVerticalDragListener; | ||||
|     } | ||||
| 
 | ||||
|     public void bind(@NonNull final Media model, | ||||
| @ -62,74 +58,19 @@ public class SliderPhotoViewHolder extends SliderItemViewHolder { | ||||
|                                     }) | ||||
|                                     .setLowResImageRequest(ImageRequest.fromUri(ResponseBodyUtils.getThumbUrl(model))) | ||||
|                                     .build()); | ||||
|         // binding.getRoot().setOnClickListener(v -> { | ||||
|         //     if (sliderCallback != null) { | ||||
|         //         sliderCallback.onItemClicked(position); | ||||
|         //     } | ||||
|         // }); | ||||
|         binding.getRoot().setTapListener(new GestureDetector.SimpleOnGestureListener() { | ||||
|         final DoubleTapGestureListener tapListener = new DoubleTapGestureListener(binding.getRoot()) { | ||||
|             @Override | ||||
|             public boolean onSingleTapUp(final MotionEvent e) { | ||||
|             public boolean onSingleTapConfirmed(final MotionEvent e) { | ||||
|                 if (sliderCallback != null) { | ||||
|                     sliderCallback.onItemClicked(position); | ||||
|                     return true; | ||||
|                     sliderCallback.onItemClicked(position, model, binding.getRoot()); | ||||
|                 } | ||||
|                 return false; | ||||
|                 return super.onSingleTapConfirmed(e); | ||||
|             } | ||||
|         }); | ||||
|         }; | ||||
|         binding.getRoot().setTapListener(tapListener); | ||||
|         final AnimatedZoomableController zoomableController = AnimatedZoomableController.newInstance(); | ||||
|         zoomableController.setMaxScaleFactor(3f); | ||||
|         binding.getRoot().setZoomableController(zoomableController); | ||||
|         if (onVerticalDragListener != null) { | ||||
|             binding.getRoot().setOnVerticalDragListener(onVerticalDragListener); | ||||
|         binding.getRoot().setZoomingEnabled(true); | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     // private void setDimensions(final FeedModel feedModel, final int spanCount, final boolean animate) { | ||||
|     //     final ViewGroup.LayoutParams layoutParams = binding.imageViewer.getLayoutParams(); | ||||
|     //     final int deviceWidth = Utils.displayMetrics.widthPixels; | ||||
|     //     final int spanWidth = deviceWidth / spanCount; | ||||
|     //     final int spanHeight = NumberUtils.getResultingHeight(spanWidth, feedModel.getImageHeight(), feedModel.getImageWidth()); | ||||
|     //     final int width = spanWidth == 0 ? deviceWidth : spanWidth; | ||||
|     //     final int height = spanHeight == 0 ? deviceWidth + 1 : spanHeight; | ||||
|     //     if (animate) { | ||||
|     //         Animation animation = AnimationUtils.expand( | ||||
|     //                 binding.imageViewer, | ||||
|     //                 layoutParams.width, | ||||
|     //                 layoutParams.height, | ||||
|     //                 width, | ||||
|     //                 height, | ||||
|     //                 new Animation.AnimationListener() { | ||||
|     //                     @Override | ||||
|     //                     public void onAnimationStart(final Animation animation) { | ||||
|     //                         showOrHideDetails(spanCount); | ||||
|     //                     } | ||||
|     // | ||||
|     //                     @Override | ||||
|     //                     public void onAnimationEnd(final Animation animation) { | ||||
|     //                         // showOrHideDetails(spanCount); | ||||
|     //                     } | ||||
|     // | ||||
|     //                     @Override | ||||
|     //                     public void onAnimationRepeat(final Animation animation) { | ||||
|     // | ||||
|     //                     } | ||||
|     //                 }); | ||||
|     //         binding.imageViewer.startAnimation(animation); | ||||
|     //     } else { | ||||
|     //         layoutParams.width = width; | ||||
|     //         layoutParams.height = height; | ||||
|     //         binding.imageViewer.requestLayout(); | ||||
|     //     } | ||||
|     // } | ||||
|     // | ||||
|     // private void showOrHideDetails(final int spanCount) { | ||||
|     //     if (spanCount == 1) { | ||||
|     //         binding.itemFeedTop.getRoot().setVisibility(View.VISIBLE); | ||||
|     //         binding.itemFeedBottom.getRoot().setVisibility(View.VISIBLE); | ||||
|     //     } else { | ||||
|     //         binding.itemFeedTop.getRoot().setVisibility(View.GONE); | ||||
|     //         binding.itemFeedBottom.getRoot().setVisibility(View.GONE); | ||||
|     //     } | ||||
|     // } | ||||
| } | ||||
|  | ||||
| @ -7,10 +7,11 @@ import android.view.ViewGroup; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerView; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.SliderItemsAdapter; | ||||
| import awais.instagrabber.customviews.VerticalDragHelper; | ||||
| import awais.instagrabber.customviews.VideoPlayerCallbackAdapter; | ||||
| import awais.instagrabber.customviews.VideoPlayerViewHelper; | ||||
| import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding; | ||||
| @ -27,40 +28,23 @@ public class SliderVideoViewHolder extends SliderItemViewHolder { | ||||
|     private static final String TAG = "SliderVideoViewHolder"; | ||||
| 
 | ||||
|     private final LayoutVideoPlayerWithThumbnailBinding binding; | ||||
|     // private final LayoutExoCustomControlsBinding controlsBinding; | ||||
|     private final boolean loadVideoOnItemClick; | ||||
|     private final GestureDetector.OnGestureListener videoPlayerViewGestureListener = new GestureDetector.SimpleOnGestureListener() { | ||||
| 
 | ||||
|     private VideoPlayerViewHelper videoPlayerViewHelper; | ||||
| 
 | ||||
|     @SuppressLint("ClickableViewAccessibility") | ||||
|     public SliderVideoViewHolder(@NonNull final LayoutVideoPlayerWithThumbnailBinding binding, | ||||
|                                  final boolean loadVideoOnItemClick) { | ||||
|         super(binding.getRoot()); | ||||
|         this.binding = binding; | ||||
|         this.loadVideoOnItemClick = loadVideoOnItemClick; | ||||
|         final GestureDetector.OnGestureListener videoPlayerViewGestureListener = new GestureDetector.SimpleOnGestureListener() { | ||||
|             @Override | ||||
|             public boolean onSingleTapConfirmed(final MotionEvent e) { | ||||
|                 binding.playerView.performClick(); | ||||
|                 return true; | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|     private VideoPlayerViewHelper videoPlayerViewHelper; | ||||
| 
 | ||||
|     @SuppressLint("ClickableViewAccessibility") | ||||
|     public SliderVideoViewHolder(@NonNull final LayoutVideoPlayerWithThumbnailBinding binding, | ||||
|                                  final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener, | ||||
|                                  // final LayoutExoCustomControlsBinding controlsBinding, | ||||
|                                  final boolean loadVideoOnItemClick) { | ||||
|         super(binding.getRoot()); | ||||
|         this.binding = binding; | ||||
|         // this.controlsBinding = controlsBinding; | ||||
|         this.loadVideoOnItemClick = loadVideoOnItemClick; | ||||
|         // if (onVerticalDragListener != null) { | ||||
|         //     final VerticalDragHelper thumbnailVerticalDragHelper = new VerticalDragHelper(binding.thumbnailParent); | ||||
|         //     final VerticalDragHelper playerVerticalDragHelper = new VerticalDragHelper(binding.playerView); | ||||
|         //     thumbnailVerticalDragHelper.setOnVerticalDragListener(onVerticalDragListener); | ||||
|         //     playerVerticalDragHelper.setOnVerticalDragListener(onVerticalDragListener); | ||||
|         //     binding.thumbnailParent.setOnTouchListener((v, event) -> { | ||||
|         //         final boolean onDragTouch = thumbnailVerticalDragHelper.onDragTouch(event); | ||||
|         //         if (onDragTouch) { | ||||
|         //             return true; | ||||
|         //         } | ||||
|         //         return thumbnailVerticalDragHelper.onGestureTouchEvent(event); | ||||
|         //     }); | ||||
|         // } | ||||
|         final GestureDetector gestureDetector = new GestureDetector(itemView.getContext(), videoPlayerViewGestureListener); | ||||
|         binding.playerView.setOnTouchListener((v, event) -> { | ||||
|             gestureDetector.onTouchEvent(event); | ||||
| @ -77,7 +61,7 @@ public class SliderVideoViewHolder extends SliderItemViewHolder { | ||||
|             @Override | ||||
|             public void onThumbnailClick() { | ||||
|                 if (sliderCallback != null) { | ||||
|                     sliderCallback.onItemClicked(position); | ||||
|                     sliderCallback.onItemClicked(position, media, binding.getRoot()); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| @ -120,6 +104,21 @@ public class SliderVideoViewHolder extends SliderItemViewHolder { | ||||
|                     sliderCallback.onPlayerRelease(position); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) { | ||||
|                 if (sliderCallback != null) { | ||||
|                     sliderCallback.onFullScreenModeChanged(isFullScreen, playerView); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public boolean isInFullScreen() { | ||||
|                 if (sliderCallback != null) { | ||||
|                     return sliderCallback.isInFullScreen(); | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|         }; | ||||
|         final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight(); | ||||
|         String videoUrl = null; | ||||
| @ -138,16 +137,10 @@ public class SliderVideoViewHolder extends SliderItemViewHolder { | ||||
|                                                           aspectRatio, | ||||
|                                                           ResponseBodyUtils.getThumbUrl(media), | ||||
|                                                           loadVideoOnItemClick, | ||||
|                                                           // controlsBinding, | ||||
|                                                           videoPlayerCallback); | ||||
|         // binding.itemFeedBottom.btnMute.setOnClickListener(v -> { | ||||
|         //     final float newVol = videoPlayerViewHelper.toggleMute(); | ||||
|         //     setMuteIcon(newVol); | ||||
|         //     Utils.sessionVolumeFull = newVol == 1f; | ||||
|         // }); | ||||
|         binding.playerView.setOnClickListener(v -> { | ||||
|             if (sliderCallback != null) { | ||||
|                 sliderCallback.onItemClicked(position); | ||||
|                 sliderCallback.onItemClicked(position, media, binding.getRoot()); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| @ -161,62 +154,4 @@ public class SliderVideoViewHolder extends SliderItemViewHolder { | ||||
|         if (videoPlayerViewHelper == null) return; | ||||
|         videoPlayerViewHelper.releasePlayer(); | ||||
|     } | ||||
| 
 | ||||
|     // 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(); | ||||
|     //     final int deviceWidth = Utils.displayMetrics.widthPixels; | ||||
|     //     final int spanWidth = deviceWidth / spanCount; | ||||
|     //     final int spanHeight = NumberUtils.getResultingHeight(spanWidth, feedModel.getImageHeight(), feedModel.getImageWidth()); | ||||
|     //     final int width = spanWidth == 0 ? deviceWidth : spanWidth; | ||||
|     //     final int height = spanHeight == 0 ? deviceWidth + 1 : spanHeight; | ||||
|     //     if (animate) { | ||||
|     //         Animation animation = AnimationUtils.expand( | ||||
|     //                 binding.imageViewer, | ||||
|     //                 layoutParams.width, | ||||
|     //                 layoutParams.height, | ||||
|     //                 width, | ||||
|     //                 height, | ||||
|     //                 new Animation.AnimationListener() { | ||||
|     //                     @Override | ||||
|     //                     public void onAnimationStart(final Animation animation) { | ||||
|     //                         showOrHideDetails(spanCount); | ||||
|     //                     } | ||||
|     // | ||||
|     //                     @Override | ||||
|     //                     public void onAnimationEnd(final Animation animation) { | ||||
|     //                         // showOrHideDetails(spanCount); | ||||
|     //                     } | ||||
|     // | ||||
|     //                     @Override | ||||
|     //                     public void onAnimationRepeat(final Animation animation) { | ||||
|     // | ||||
|     //                     } | ||||
|     //                 }); | ||||
|     //         binding.imageViewer.startAnimation(animation); | ||||
|     //     } else { | ||||
|     //         layoutParams.width = width; | ||||
|     //         layoutParams.height = height; | ||||
|     //         binding.imageViewer.requestLayout(); | ||||
|     //     } | ||||
|     // } | ||||
|     // | ||||
|     // private void showOrHideDetails(final int spanCount) { | ||||
|     //     if (spanCount == 1) { | ||||
|     //         binding.itemFeedTop.getRoot().setVisibility(View.VISIBLE); | ||||
|     //         binding.itemFeedBottom.getRoot().setVisibility(View.VISIBLE); | ||||
|     //     } else { | ||||
|     //         binding.itemFeedTop.getRoot().setVisibility(View.GONE); | ||||
|     //         binding.itemFeedBottom.getRoot().setVisibility(View.GONE); | ||||
|     //     } | ||||
|     // } | ||||
| } | ||||
|  | ||||
| @ -45,9 +45,9 @@ public class FeedSliderViewHolder extends FeedItemViewHolder { | ||||
|         final String text = "1/" + sliderItemLen; | ||||
|         binding.mediaCounter.setText(text); | ||||
|         binding.mediaList.setOffscreenPageLimit(1); | ||||
|         final SliderItemsAdapter adapter = new SliderItemsAdapter(null, false, new SliderCallbackAdapter() { | ||||
|         final SliderItemsAdapter adapter = new SliderItemsAdapter(false, new SliderCallbackAdapter() { | ||||
|             @Override | ||||
|             public void onItemClicked(final int position) { | ||||
|             public void onItemClicked(final int position, final Media media, final View view) { | ||||
|                 feedItemCallback.onSliderClick(feedModel, position); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| package awais.instagrabber.customviews; | ||||
| 
 | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerView; | ||||
| 
 | ||||
| public class VideoPlayerCallbackAdapter implements VideoPlayerViewHelper.VideoPlayerCallback { | ||||
|     @Override | ||||
|     public void onThumbnailLoaded() {} | ||||
| @ -18,4 +20,12 @@ public class VideoPlayerCallbackAdapter implements VideoPlayerViewHelper.VideoPl | ||||
| 
 | ||||
|     @Override | ||||
|     public void onRelease() {} | ||||
| 
 | ||||
|     @Override | ||||
|     public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) {} | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isInFullScreen() { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,15 +1,19 @@ | ||||
| package awais.instagrabber.customviews; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.res.ColorStateList; | ||||
| import android.content.res.Resources; | ||||
| import android.graphics.drawable.Animatable; | ||||
| import android.net.Uri; | ||||
| import android.os.Looper; | ||||
| import android.util.Log; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.ImageView; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.appcompat.widget.PopupMenu; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.widget.AppCompatImageButton; | ||||
| 
 | ||||
| import com.facebook.drawee.backends.pipeline.Fresco; | ||||
| import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder; | ||||
| @ -23,18 +27,23 @@ 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.source.TrackGroupArray; | ||||
| import com.google.android.exoplayer2.trackselection.TrackSelectionArray; | ||||
| import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerControlView; | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerView; | ||||
| import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; | ||||
| import com.google.android.material.button.MaterialButton; | ||||
| 
 | ||||
| import java.lang.reflect.Field; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding; | ||||
| import awais.instagrabber.utils.Utils; | ||||
| 
 | ||||
| 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 String TAG = VideoPlayerViewHelper.class.getSimpleName(); | ||||
| 
 | ||||
|     private final Context context; | ||||
|     private final LayoutVideoPlayerWithThumbnailBinding binding; | ||||
| @ -42,74 +51,20 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|     private final float thumbnailAspectRatio; | ||||
|     private final String thumbnailUrl; | ||||
|     private final boolean loadPlayerOnClick; | ||||
|     // 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 AppCompatImageButton mute; | ||||
| 
 | ||||
|     // 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 View.OnClickListener muteOnClickListener = v -> toggleMute(); | ||||
|     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; | ||||
|     private Object layoutManager; | ||||
| 
 | ||||
|     public VideoPlayerViewHelper(@NonNull final Context context, | ||||
|                                  @NonNull final LayoutVideoPlayerWithThumbnailBinding binding, | ||||
| @ -118,7 +73,6 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|                                  final float thumbnailAspectRatio, | ||||
|                                  final String thumbnailUrl, | ||||
|                                  final boolean loadPlayerOnClick, | ||||
|                                  // final LayoutExoCustomControlsBinding controlsBinding, | ||||
|                                  final VideoPlayerCallback videoPlayerCallback) { | ||||
|         this.context = context; | ||||
|         this.binding = binding; | ||||
| @ -126,7 +80,6 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|         this.thumbnailAspectRatio = thumbnailAspectRatio; | ||||
|         this.thumbnailUrl = thumbnailUrl; | ||||
|         this.loadPlayerOnClick = loadPlayerOnClick; | ||||
|         // this.controlsBinding = controlsBinding; | ||||
|         this.videoPlayerCallback = videoPlayerCallback; | ||||
|         this.videoUrl = videoUrl; | ||||
|         this.dataSourceFactory = new DefaultDataSourceFactory(binding.getRoot().getContext(), "instagram"); | ||||
| @ -143,7 +96,6 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|             } | ||||
|         }); | ||||
|         setThumbnail(); | ||||
|         // setupControls(); | ||||
|     } | ||||
| 
 | ||||
|     private void setThumbnail() { | ||||
| @ -196,11 +148,6 @@ 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); | ||||
|         player.addListener(this); | ||||
|         player.addAudioListener(audioListener); | ||||
|         player.setVolume(initialVolume); | ||||
| @ -210,138 +157,118 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|         final MediaItem mediaItem = MediaItem.fromUri(videoUrl); | ||||
|         final ProgressiveMediaSource mediaSource = sourceFactory.createMediaSource(mediaItem); | ||||
|         player.setMediaSource(mediaSource); | ||||
|         // setupControls(); | ||||
|         player.prepare(); | ||||
|         binding.playerView.setPlayer(player); | ||||
|         // binding.playerView.setShowFastForwardButton(false); | ||||
|         // binding.playerView.setShowRewindButton(false); | ||||
|         binding.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT); | ||||
|         binding.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT); | ||||
|         binding.playerView.setShowNextButton(false); | ||||
|         binding.playerView.setShowPreviousButton(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); | ||||
|         binding.playerView.setControllerOnFullScreenModeChangedListener(isFullScreen -> { | ||||
|             if (videoPlayerCallback == null) return; | ||||
|             videoPlayerCallback.onFullScreenModeChanged(isFullScreen, binding.playerView); | ||||
|         }); | ||||
|         setupControllerView(); | ||||
|     } | ||||
| 
 | ||||
|     private void setupControllerView() { | ||||
|         try { | ||||
|             final StyledPlayerControlView controllerView = getStyledPlayerControlView(); | ||||
|             if (controllerView == null) return; | ||||
|             layoutManager = setControlViewLayoutManager(controllerView); | ||||
|             if (videoPlayerCallback != null && videoPlayerCallback.isInFullScreen()) { | ||||
|                 setControllerViewToFullScreenMode(controllerView); | ||||
|             } | ||||
|             final ViewGroup exoBasicControls = controllerView.findViewById(R.id.exo_basic_controls); | ||||
|             if (exoBasicControls == null) return; | ||||
|             mute = new AppCompatImageButton(context); | ||||
|             final Resources resources = context.getResources(); | ||||
|             if (resources == null) return; | ||||
|             final int width = resources.getDimensionPixelSize(R.dimen.exo_small_icon_width); | ||||
|             final int height = resources.getDimensionPixelSize(R.dimen.exo_small_icon_height); | ||||
|             final int margin = resources.getDimensionPixelSize(R.dimen.exo_small_icon_horizontal_margin); | ||||
|             final int paddingHorizontal = resources.getDimensionPixelSize(R.dimen.exo_small_icon_padding_horizontal); | ||||
|             final int paddingVertical = resources.getDimensionPixelSize(R.dimen.exo_small_icon_padding_vertical); | ||||
|             final ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(width, height); | ||||
|             layoutParams.setMargins(margin, 0, margin, 0); | ||||
|             mute.setLayoutParams(layoutParams); | ||||
|             mute.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); | ||||
|             mute.setScaleType(ImageView.ScaleType.FIT_XY); | ||||
|             mute.setBackgroundResource(Utils.getAttrResId(context, android.R.attr.selectableItemBackground)); | ||||
|             mute.setImageTintList(ColorStateList.valueOf(resources.getColor(R.color.white))); | ||||
|             updateMuteIcon(player.getVolume()); | ||||
|             exoBasicControls.addView(mute, 0); | ||||
|             mute.setOnClickListener(muteOnClickListener); | ||||
|         } catch (Exception e) { | ||||
|             Log.e(TAG, "loadPlayer: ", e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // 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); | ||||
|     // } | ||||
|     @Nullable | ||||
|     private Object setControlViewLayoutManager(@NonNull final StyledPlayerControlView controllerView) | ||||
|             throws NoSuchFieldException, IllegalAccessException { | ||||
|         final Field controlViewLayoutManagerField = controllerView.getClass().getDeclaredField("controlViewLayoutManager"); | ||||
|         controlViewLayoutManagerField.setAccessible(true); | ||||
|         return controlViewLayoutManagerField.get(controllerView); | ||||
|     } | ||||
| 
 | ||||
|     // 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 setControllerViewToFullScreenMode(@NonNull final StyledPlayerControlView controllerView) | ||||
|             throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { | ||||
|         // Exoplayer doesn't expose the fullscreen state, so using reflection | ||||
|         final Field fullScreenButtonField = controllerView.getClass().getDeclaredField("fullScreenButton"); | ||||
|         fullScreenButtonField.setAccessible(true); | ||||
|         final ImageView fullScreenButton = (ImageView) fullScreenButtonField.get(controllerView); | ||||
|         final Field isFullScreen = controllerView.getClass().getDeclaredField("isFullScreen"); | ||||
|         isFullScreen.setAccessible(true); | ||||
|         isFullScreen.set(controllerView, true); | ||||
|         final Method updateFullScreenButtonForState = controllerView | ||||
|                 .getClass() | ||||
|                 .getDeclaredMethod("updateFullScreenButtonForState", ImageView.class, boolean.class); | ||||
|         updateFullScreenButtonForState.setAccessible(true); | ||||
|         updateFullScreenButtonForState.invoke(controllerView, fullScreenButton, true); | ||||
| 
 | ||||
|     // 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); | ||||
|     // } | ||||
|     } | ||||
| 
 | ||||
|     // public void showMenu(View anchor) { | ||||
|     //     PopupMenu popup = getPopupMenu(anchor); | ||||
|     //     popup.show(); | ||||
|     // } | ||||
|     @Nullable | ||||
|     private StyledPlayerControlView getStyledPlayerControlView() throws NoSuchFieldException, IllegalAccessException { | ||||
|         final Field controller = binding.playerView.getClass().getDeclaredField("controller"); | ||||
|         controller.setAccessible(true); | ||||
|         return (StyledPlayerControlView) controller.get(binding.playerView); | ||||
|     } | ||||
| 
 | ||||
|     // @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; | ||||
|     // } | ||||
|     @Override | ||||
|     public void onTracksChanged(@NonNull TrackGroupArray trackGroups, @NonNull TrackSelectionArray trackSelections) { | ||||
|         if (trackGroups.isEmpty()) { | ||||
|             setHasAudio(false); | ||||
|             return; | ||||
|         } | ||||
|         boolean hasAudio = false; | ||||
|         for (int i = 0; i < trackGroups.length; i++) { | ||||
|             for (int g = 0; g < trackGroups.get(i).length; g++) { | ||||
|                 final String sampleMimeType = trackGroups.get(i).getFormat(g).sampleMimeType; | ||||
|                 if (sampleMimeType != null && sampleMimeType.contains("audio")) { | ||||
|                     hasAudio = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         setHasAudio(hasAudio); | ||||
|     } | ||||
| 
 | ||||
|     private void setHasAudio(final boolean hasAudio) { | ||||
|         if (mute == null) return; | ||||
|         mute.setEnabled(hasAudio); | ||||
|         mute.setAlpha(hasAudio ? 1f : 0.5f); | ||||
|         updateMuteIcon(hasAudio ? 1f : 0f); | ||||
|     } | ||||
| 
 | ||||
|     private void updateMuteIcon(final float volume) { | ||||
|         if (mute == null) return; | ||||
|         if (volume == 0) { | ||||
|             mute.setIconResource(R.drawable.ic_volume_off_24_states); | ||||
|             mute.setImageResource(R.drawable.ic_volume_off_24); | ||||
|             return; | ||||
|         } | ||||
|         mute.setIconResource(R.drawable.ic_volume_up_24_states); | ||||
|         mute.setImageResource(R.drawable.ic_volume_up_24); | ||||
|     } | ||||
| 
 | ||||
|     // 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) { | ||||
|         if (videoPlayerCallback == null) return; | ||||
| @ -359,18 +286,18 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
| 
 | ||||
|     private void toggleMute() { | ||||
|         if (player == null) return; | ||||
|         if (layoutManager != null) { | ||||
|             try { | ||||
|                 final Method resetHideCallbacks = layoutManager.getClass().getDeclaredMethod("resetHideCallbacks"); | ||||
|                 resetHideCallbacks.invoke(layoutManager); | ||||
|             } catch (Exception e) { | ||||
|                 Log.e(TAG, "toggleMute: ", e); | ||||
|             } | ||||
|         } | ||||
|         final float vol = player.getVolume() == 0f ? 1f : 0f; | ||||
|         player.setVolume(vol); | ||||
|     } | ||||
| 
 | ||||
|     // public void togglePlayback() { | ||||
|     //     if (player == null) return; | ||||
|     //     final int playbackState = player.getPlaybackState(); | ||||
|     //     if (playbackState == STATE_IDLE || playbackState == STATE_ENDED) return; | ||||
|     //     final boolean playWhenReady = player.getPlayWhenReady(); | ||||
|     //     player.setPlayWhenReady(!playWhenReady); | ||||
|     // } | ||||
| 
 | ||||
|     public void releasePlayer() { | ||||
|         if (videoPlayerCallback != null) { | ||||
|             videoPlayerCallback.onRelease(); | ||||
| @ -379,86 +306,14 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|             player.release(); | ||||
|             player = 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); | ||||
|         //     } | ||||
|         // } | ||||
|     } | ||||
| 
 | ||||
|     // 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); | ||||
|     // } | ||||
| 
 | ||||
|     // 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(); | ||||
| 
 | ||||
| @ -471,5 +326,9 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|         void onPause(); | ||||
| 
 | ||||
|         void onRelease(); | ||||
| 
 | ||||
|         void onFullScreenModeChanged(boolean isFullScreen, final StyledPlayerView playerView); | ||||
| 
 | ||||
|         boolean isInFullScreen(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -6,6 +6,7 @@ import android.content.pm.PackageManager; | ||||
| import android.content.res.ColorStateList; | ||||
| import android.content.res.Resources; | ||||
| import android.graphics.Rect; | ||||
| import android.graphics.drawable.ColorDrawable; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.net.Uri; | ||||
| import android.os.Bundle; | ||||
| @ -14,15 +15,18 @@ import android.text.Spanned; | ||||
| import android.util.Log; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.MenuItem; | ||||
| import android.view.MotionEvent; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| import android.widget.Toast; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.app.ActionBar; | ||||
| import androidx.appcompat.content.res.AppCompatResources; | ||||
| import androidx.appcompat.view.ContextThemeWrapper; | ||||
| import androidx.appcompat.widget.PopupMenu; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import androidx.constraintlayout.widget.ConstraintLayout; | ||||
| import androidx.core.content.PermissionChecker; | ||||
| import androidx.fragment.app.Fragment; | ||||
| @ -44,6 +48,8 @@ import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; | ||||
| import com.facebook.drawee.interfaces.DraweeController; | ||||
| import com.facebook.imagepipeline.request.ImageRequest; | ||||
| import com.facebook.imagepipeline.request.ImageRequestBuilder; | ||||
| import com.google.android.exoplayer2.ui.StyledPlayerView; | ||||
| import com.google.android.material.appbar.CollapsingToolbarLayout; | ||||
| import com.google.android.material.snackbar.BaseTransientBottomBar; | ||||
| import com.google.android.material.snackbar.Snackbar; | ||||
| import com.skydoves.balloon.ArrowOrientation; | ||||
| @ -59,6 +65,7 @@ import java.io.Serializable; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.activities.MainActivity; | ||||
| import awais.instagrabber.adapters.SliderCallbackAdapter; | ||||
| import awais.instagrabber.adapters.SliderItemsAdapter; | ||||
| import awais.instagrabber.adapters.viewholder.SliderVideoViewHolder; | ||||
| @ -67,6 +74,7 @@ import awais.instagrabber.customviews.VideoPlayerCallbackAdapter; | ||||
| import awais.instagrabber.customviews.VideoPlayerViewHelper; | ||||
| import awais.instagrabber.customviews.drawee.AnimatedZoomableController; | ||||
| import awais.instagrabber.customviews.drawee.DoubleTapGestureListener; | ||||
| import awais.instagrabber.customviews.drawee.ZoomableController; | ||||
| import awais.instagrabber.customviews.drawee.ZoomableDraweeView; | ||||
| import awais.instagrabber.databinding.DialogPostViewBinding; | ||||
| import awais.instagrabber.databinding.LayoutPostViewBottomBinding; | ||||
| @ -117,6 +125,12 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|     @Nullable | ||||
|     private ViewPager2 sliderParent; | ||||
|     private LayoutPostViewBottomBinding bottom; | ||||
|     private View postView; | ||||
|     private int originalHeight; | ||||
|     private int originalSystemUi; | ||||
|     private boolean isInFullScreenMode; | ||||
|     private StyledPlayerView playerView; | ||||
|     private int playerViewOriginalHeight; | ||||
| 
 | ||||
|     private final Observer<Object> backStackSavedStateObserver = result -> { | ||||
|         if (result == null) return; | ||||
| @ -127,6 +141,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|         // clear result | ||||
|         backStackSavedStateResultLiveData.postValue(null); | ||||
|     }; | ||||
|     private Drawable originalRootBackground; | ||||
| 
 | ||||
|     public void setOnDeleteListener(final OnDeleteListener onDeleteListener) { | ||||
|         if (onDeleteListener == null) return; | ||||
| @ -197,6 +212,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|     @Override | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         showSystemUI(); | ||||
|         final Media media = viewModel.getMedia(); | ||||
|         if (media == null) return; | ||||
|         switch (media.getMediaType()) { | ||||
| @ -753,7 +769,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|     } | ||||
| 
 | ||||
|     private void setupPostImage() { | ||||
|         binding.mediaCounter.setVisibility(View.GONE); | ||||
|         // binding.mediaCounter.setVisibility(View.GONE); | ||||
|         final Context context = getContext(); | ||||
|         if (context == null) return; | ||||
|         final Resources resources = context.getResources(); | ||||
| @ -762,12 +778,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|         final String imageUrl = ResponseBodyUtils.getImageUrl(media); | ||||
|         if (TextUtils.isEmpty(imageUrl)) return; | ||||
|         final ZoomableDraweeView postImage = new ZoomableDraweeView(context); | ||||
|         postView = postImage; | ||||
|         final NullSafePair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(media.getOriginalHeight(), | ||||
|                                                                                             media.getOriginalWidth(), | ||||
|                                                                                             (int) (Utils.displayMetrics.heightPixels * 0.8), | ||||
|                                                                                             Utils.displayMetrics.widthPixels); | ||||
|         final int height = widthHeight.second; | ||||
|         final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, height); | ||||
|         originalHeight = widthHeight.second; | ||||
|         final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, | ||||
|                                                                                              originalHeight); | ||||
|         layoutParams.topToBottom = binding.topBarrier.getId(); | ||||
|         layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId(); | ||||
|         layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID; | ||||
| @ -788,10 +806,22 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|         zoomableController.setGestureZoomEnabled(true); | ||||
|         zoomableController.setEnabled(true); | ||||
|         postImage.setZoomingEnabled(true); | ||||
|         postImage.setTapListener(new DoubleTapGestureListener(postImage)); | ||||
|         final DoubleTapGestureListener tapListener = new DoubleTapGestureListener(postImage) { | ||||
|             @Override | ||||
|             public boolean onSingleTapConfirmed(final MotionEvent e) { | ||||
|                 if (!isInFullScreenMode) { | ||||
|                     zoomableController.reset(); | ||||
|                     hideSystemUI(); | ||||
|                 } else { | ||||
|                     showSystemUI(); | ||||
|                     binding.getRoot().postDelayed(zoomableController::reset, 500); | ||||
|                 } | ||||
|                 return super.onSingleTapConfirmed(e); | ||||
|             } | ||||
|         }; | ||||
|         postImage.setTapListener(tapListener); | ||||
|         // postImage.setAllowTouchInterceptionWhileZoomed(true); | ||||
|         binding.contentRoot.addView(postImage, 0); | ||||
|         // binding.postImage.setAllowTouchInterceptionWhileZoomed(true); | ||||
|         // binding.postImage.setOnVerticalDragListener(onVerticalDragListener); | ||||
|     } | ||||
| 
 | ||||
|     private void setupSlider() { | ||||
| @ -818,13 +848,15 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|                                                                                             maxHW.second, | ||||
|                                                                                             (int) (Utils.displayMetrics.heightPixels * 0.8), | ||||
|                                                                                             Utils.displayMetrics.widthPixels); | ||||
|         originalHeight = widthHeight.second; | ||||
|         final ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, | ||||
|                                                                                              widthHeight.second); | ||||
|                                                                                              originalHeight); | ||||
|         layoutParams.topToBottom = binding.topBarrier.getId(); | ||||
|         layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId(); | ||||
|         layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID; | ||||
|         layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID; | ||||
|         sliderParent.setLayoutParams(layoutParams); | ||||
|         postView = sliderParent; | ||||
|         binding.contentRoot.addView(sliderParent, 0); | ||||
| 
 | ||||
|         final boolean hasVideo = media.getCarouselMedia() | ||||
| @ -841,16 +873,23 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         sliderItemsAdapter = new SliderItemsAdapter(null, true, new SliderCallbackAdapter() { | ||||
|         sliderItemsAdapter = new SliderItemsAdapter(true, new SliderCallbackAdapter() { | ||||
|             @Override | ||||
|             public void onThumbnailLoaded(final int position) { | ||||
|                 if (position != 0) return; | ||||
|                 startPostponedEnterTransition(); | ||||
|             public void onItemClicked(final int position, final Media media, final View view) { | ||||
|                 if (media == null | ||||
|                         || media.getMediaType() != MediaItemType.MEDIA_TYPE_IMAGE | ||||
|                         || !(view instanceof ZoomableDraweeView)) { | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onItemClicked(final int position) { | ||||
|                 // toggleDetails(); | ||||
|                 final ZoomableController zoomableController = ((ZoomableDraweeView) view).getZoomableController(); | ||||
|                 if (!(zoomableController instanceof AnimatedZoomableController)) return; | ||||
|                 if (!isInFullScreenMode) { | ||||
|                     ((AnimatedZoomableController) zoomableController).reset(); | ||||
|                     hideSystemUI(); | ||||
|                     return; | ||||
|                 } | ||||
|                 showSystemUI(); | ||||
|                 binding.getRoot().postDelayed(((AnimatedZoomableController) zoomableController)::reset, 500); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
| @ -877,6 +916,21 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|                 if (activity == null) return; | ||||
|                 Utils.disableKeepScreenOn(activity); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) { | ||||
|                 PostViewV2Fragment.this.playerView = playerView; | ||||
|                 if (isFullScreen) { | ||||
|                     hideSystemUI(); | ||||
|                     return; | ||||
|                 } | ||||
|                 showSystemUI(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public boolean isInFullScreen() { | ||||
|                 return isInFullScreenMode; | ||||
|             } | ||||
|         }); | ||||
|         sliderParent.setAdapter(sliderItemsAdapter); | ||||
|         if (sliderPosition >= 0 && sliderPosition < media.getCarouselMedia().size()) { | ||||
| @ -981,12 +1035,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|                                                                                             (int) (Utils.displayMetrics.heightPixels * 0.8), | ||||
|                                                                                             Utils.displayMetrics.widthPixels); | ||||
|         layoutParams.width = ConstraintLayout.LayoutParams.MATCH_PARENT; | ||||
|         layoutParams.height = widthHeight.second; | ||||
|         originalHeight = widthHeight.second; | ||||
|         layoutParams.height = originalHeight; | ||||
|         layoutParams.topToBottom = binding.topBarrier.getId(); | ||||
|         layoutParams.bottomToTop = bottom.buttonsTopBarrier.getId(); | ||||
|         layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID; | ||||
|         layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID; | ||||
|         binding.contentRoot.addView(videoPost.getRoot(), 0); | ||||
|         postView = videoPost.getRoot(); | ||||
|         binding.contentRoot.addView(postView, 0); | ||||
| 
 | ||||
|         // final GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { | ||||
|         //     @Override | ||||
| @ -1041,6 +1097,16 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|                 if (activity == null) return; | ||||
|                 Utils.disableKeepScreenOn(activity); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onFullScreenModeChanged(final boolean isFullScreen, final StyledPlayerView playerView) { | ||||
|                 PostViewV2Fragment.this.playerView = playerView; | ||||
|                 if (isFullScreen) { | ||||
|                     hideSystemUI(); | ||||
|                     return; | ||||
|                 } | ||||
|                 showSystemUI(); | ||||
|             } | ||||
|         }; | ||||
|         final float aspectRatio = (float) media.getOriginalWidth() / media.getOriginalHeight(); | ||||
|         String videoUrl = null; | ||||
| @ -1064,92 +1130,6 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // 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(); | ||||
|     // | ||||
|     //     // 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 setupOptions(final Boolean show) { | ||||
|         if (!show) { | ||||
|             binding.options.setVisibility(View.GONE); | ||||
| @ -1282,29 +1262,49 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|     } | ||||
| 
 | ||||
|     private void toggleDetails() { | ||||
|         // hasBeenToggled = true; | ||||
|         final boolean hasBeenToggled = true; | ||||
|         final Media media = viewModel.getMedia(); | ||||
|         binding.getRoot().post(() -> { | ||||
|             TransitionManager.beginDelayedTransition(binding.getRoot()); | ||||
|             if (detailsVisible) { | ||||
|                 final Context context = getContext(); | ||||
|                 if (context == null) return; | ||||
|                 originalRootBackground = binding.getRoot().getBackground(); | ||||
|                 final Resources resources = context.getResources(); | ||||
|                 if (resources == null) return; | ||||
|                 final ColorDrawable colorDrawable = new ColorDrawable(resources.getColor(R.color.black)); | ||||
|                 binding.getRoot().setBackground(colorDrawable); | ||||
|                 if (postView != null) { | ||||
|                     // Make post match parent | ||||
|                     final ViewGroup.LayoutParams layoutParams = postView.getLayoutParams(); | ||||
|                     final int fullHeight = Utils.displayMetrics.heightPixels + Utils.getNavigationBarSize(context).y; | ||||
|                     layoutParams.height = fullHeight; | ||||
|                     binding.contentRoot.getLayoutParams().height = fullHeight; | ||||
|                     if (playerView != null) { | ||||
|                         playerViewOriginalHeight = playerView.getLayoutParams().height; | ||||
|                         playerView.getLayoutParams().height = fullHeight; | ||||
|                     } | ||||
|                 } | ||||
|                 detailsVisible = false; | ||||
|                 if (media.getUser() != null) { | ||||
|                     binding.profilePic.setVisibility(View.GONE); | ||||
|                     binding.title.setVisibility(View.GONE); | ||||
|                     binding.subtitle.setVisibility(View.GONE); | ||||
|                     // binding.topBg.setVisibility(View.GONE); | ||||
|                 } | ||||
|                 if (media.getLocation() != null) { | ||||
|                     binding.location.setVisibility(View.GONE); | ||||
|                 } | ||||
|                 // bottom.bottomBg.setVisibility(View.GONE); | ||||
|                 // bottom.likesCount.setVisibility(View.GONE); | ||||
|                 // bottom.commentsCount.setVisibility(View.GONE); | ||||
|                 if (media.getCaption() != null && !TextUtils.isEmpty(media.getCaption().getText())) { | ||||
|                     bottom.caption.setVisibility(View.GONE); | ||||
|                     bottom.translate.setVisibility(View.GONE); | ||||
|                 } | ||||
|                 bottom.likesCount.setVisibility(View.GONE); | ||||
|                 bottom.commentsCount.setVisibility(View.GONE); | ||||
|                 bottom.date.setVisibility(View.GONE); | ||||
|                 bottom.comment.setVisibility(View.GONE); | ||||
|                 bottom.like.setVisibility(View.GONE); | ||||
|                 bottom.save.setVisibility(View.GONE); | ||||
|                 // bottom.share.setVisibility(View.GONE); | ||||
|                 bottom.share.setVisibility(View.GONE); | ||||
|                 bottom.download.setVisibility(View.GONE); | ||||
|                 binding.mediaCounter.setVisibility(View.GONE); | ||||
|                 bottom.viewsCount.setVisibility(View.GONE); | ||||
| @ -1312,12 +1312,21 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|                 if (options != null && !options.isEmpty()) { | ||||
|                     binding.options.setVisibility(View.GONE); | ||||
|                 } | ||||
|                 // wasControlsVisible = binding.playerControls.getRoot().getVisibility() == View.VISIBLE; | ||||
|                 // if (wasControlsVisible) { | ||||
|                 //     hidePlayerControls(); | ||||
|                 // } | ||||
|                 return; | ||||
|             } | ||||
|             if (originalRootBackground != null) { | ||||
|                 binding.getRoot().setBackground(originalRootBackground); | ||||
|             } | ||||
|             if (postView != null) { | ||||
|                 // Make post height back to original | ||||
|                 final ViewGroup.LayoutParams layoutParams = postView.getLayoutParams(); | ||||
|                 layoutParams.height = originalHeight; | ||||
|                 binding.contentRoot.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; | ||||
|                 if (playerView != null) { | ||||
|                     playerView.getLayoutParams().height = playerViewOriginalHeight; | ||||
|                     playerView = null; | ||||
|                 } | ||||
|             } | ||||
|             if (media.getUser() != null) { | ||||
|                 binding.profilePic.setVisibility(View.VISIBLE); | ||||
|                 binding.title.setVisibility(View.VISIBLE); | ||||
| @ -1327,17 +1336,20 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|             if (media.getLocation() != null) { | ||||
|                 binding.location.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             // bottom.bottomBg.setVisibility(View.VISIBLE); | ||||
|             if (media.getCaption() != null && !TextUtils.isEmpty(media.getCaption().getText())) { | ||||
|                 bottom.caption.setVisibility(View.VISIBLE); | ||||
|                 bottom.translate.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             if (viewModel.hasPk()) { | ||||
|                 // bottom.likesCount.setVisibility(View.VISIBLE); | ||||
|                 bottom.likesCount.setVisibility(View.VISIBLE); | ||||
|                 bottom.date.setVisibility(View.VISIBLE); | ||||
|                 // binding.captionParent.setVisibility(View.VISIBLE); | ||||
|                 // binding.captionToggle.setVisibility(View.VISIBLE); | ||||
|                 // bottom.share.setVisibility(View.VISIBLE); | ||||
|                 bottom.share.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             if (viewModel.hasPk() && !viewModel.getMedia().isCommentsDisabled()) { | ||||
|                 bottom.comment.setVisibility(View.VISIBLE); | ||||
|                 // bottom.commentsCount.setVisibility(View.VISIBLE); | ||||
|                 bottom.commentsCount.setVisibility(View.VISIBLE); | ||||
|             } | ||||
|             bottom.download.setVisibility(View.VISIBLE); | ||||
|             final List<Integer> options = viewModel.getOptions().getValue(); | ||||
| @ -1362,6 +1374,64 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     private void hideSystemUI() { | ||||
|         if (detailsVisible) { | ||||
|             toggleDetails(); | ||||
|         } | ||||
|         final MainActivity activity = (MainActivity) getActivity(); | ||||
|         if (activity == null) return; | ||||
|         final ActionBar actionBar = activity.getSupportActionBar(); | ||||
|         if (actionBar != null) { | ||||
|             actionBar.hide(); | ||||
|         } | ||||
|         final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView(); | ||||
|         if (appbarLayout != null) { | ||||
|             appbarLayout.setVisibility(View.GONE); | ||||
|         } | ||||
|         final Toolbar toolbar = activity.getToolbar(); | ||||
|         if (toolbar != null) { | ||||
|             toolbar.setVisibility(View.GONE); | ||||
|         } | ||||
|         final View decorView = activity.getWindow().getDecorView(); | ||||
|         originalSystemUi = decorView.getSystemUiVisibility(); | ||||
|         decorView.setSystemUiVisibility( | ||||
|                 View.SYSTEM_UI_FLAG_IMMERSIVE | ||||
|                         // Set the content to appear under the system bars so that the | ||||
|                         // content doesn't resize when the system bars hide and show. | ||||
|                         | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | ||||
|                         | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | ||||
|                         | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | ||||
|                         // Hide the nav bar and status bar | ||||
|                         | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | ||||
|                         | View.SYSTEM_UI_FLAG_FULLSCREEN); | ||||
|         isInFullScreenMode = true; | ||||
|     } | ||||
| 
 | ||||
|     // Shows the system bars by removing all the flags | ||||
|     // except for the ones that make the content appear under the system bars. | ||||
|     private void showSystemUI() { | ||||
|         if (!detailsVisible) { | ||||
|             toggleDetails(); | ||||
|         } | ||||
|         final MainActivity activity = (MainActivity) getActivity(); | ||||
|         if (activity == null) return; | ||||
|         final ActionBar actionBar = activity.getSupportActionBar(); | ||||
|         if (actionBar != null) { | ||||
|             actionBar.show(); | ||||
|         } | ||||
|         final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView(); | ||||
|         if (appbarLayout != null) { | ||||
|             appbarLayout.setVisibility(View.VISIBLE); | ||||
|         } | ||||
|         final Toolbar toolbar = activity.getToolbar(); | ||||
|         if (toolbar != null) { | ||||
|             toolbar.setVisibility(View.VISIBLE); | ||||
|         } | ||||
|         final View decorView = activity.getWindow().getDecorView(); | ||||
|         decorView.setSystemUiVisibility(originalSystemUi); | ||||
|         isInFullScreenMode = false; | ||||
|     } | ||||
| 
 | ||||
|     private void navigateToProfile(final String username) { | ||||
|         final NavController navController = getNavController(); | ||||
|         if (navController == null) return; | ||||
|  | ||||
| @ -10,6 +10,7 @@ import android.content.Intent; | ||||
| import android.content.res.Resources; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.Point; | ||||
| import android.graphics.Rect; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.media.MediaScannerConnection; | ||||
| @ -22,6 +23,7 @@ import android.util.DisplayMetrics; | ||||
| import android.util.Log; | ||||
| import android.util.Pair; | ||||
| import android.util.TypedValue; | ||||
| import android.view.Display; | ||||
| import android.view.Gravity; | ||||
| import android.view.View; | ||||
| import android.view.Window; | ||||
| @ -294,6 +296,12 @@ public final class Utils { | ||||
|         return outValue.data; | ||||
|     } | ||||
| 
 | ||||
|     public static int getAttrResId(@NonNull final Context context, final int attr) { | ||||
|         final TypedValue outValue = new TypedValue(); | ||||
|         context.getTheme().resolveAttribute(attr, outValue, true); | ||||
|         return outValue.resourceId; | ||||
|     } | ||||
| 
 | ||||
|     public static void transparentStatusBar(final Activity activity, | ||||
|                                             final boolean enable, | ||||
|                                             final boolean fullscreen) { | ||||
| @ -517,4 +525,41 @@ public final class Utils { | ||||
|         if (navRootString == null || tabOrderString == null) return false; | ||||
|         return tabOrderString.contains(navRootString); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static Point getNavigationBarSize(@NonNull Context context) { | ||||
|         Point appUsableSize = getAppUsableScreenSize(context); | ||||
|         Point realScreenSize = getRealScreenSize(context); | ||||
| 
 | ||||
|         // navigation bar on the right | ||||
|         if (appUsableSize.x < realScreenSize.x) { | ||||
|             return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y); | ||||
|         } | ||||
| 
 | ||||
|         // navigation bar at the bottom | ||||
|         if (appUsableSize.y < realScreenSize.y) { | ||||
|             return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y); | ||||
|         } | ||||
| 
 | ||||
|         // navigation bar is not present | ||||
|         return new Point(); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static Point getAppUsableScreenSize(@NonNull Context context) { | ||||
|         WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); | ||||
|         Display display = windowManager.getDefaultDisplay(); | ||||
|         Point size = new Point(); | ||||
|         display.getSize(size); | ||||
|         return size; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static Point getRealScreenSize(@NonNull Context context) { | ||||
|         WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); | ||||
|         Display display = windowManager.getDefaultDisplay(); | ||||
|         Point size = new Point(); | ||||
|         display.getRealSize(size); | ||||
|         return size; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="?colorSurface" | ||||
|     tools:context=".fragments.PostViewV2Fragment"> | ||||
| 
 | ||||
|     <androidx.constraintlayout.widget.ConstraintLayout | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
|         style="@style/Widget.MaterialComponents.Button.TextButton" | ||||
|         android:layout_width="36dp" | ||||
|         android:layout_height="40dp" | ||||
|         android:background="@drawable/background_grey_ripple" | ||||
|         android:visibility="visible" | ||||
|         app:icon="@drawable/ic_not_liked" | ||||
|         app:iconGravity="textStart" | ||||
| @ -51,6 +52,7 @@ | ||||
|         android:layout_width="36dp" | ||||
|         android:layout_height="40dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:background="@drawable/background_grey_ripple" | ||||
|         app:icon="@drawable/ic_outline_comments_24" | ||||
|         app:iconPadding="0dp" | ||||
|         app:iconSize="22dp" | ||||
| @ -90,6 +92,7 @@ | ||||
|         style="@style/Widget.MaterialComponents.Button.TextButton" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="40dp" | ||||
|         android:background="@drawable/background_grey_ripple" | ||||
|         app:icon="?attr/actionModeShareDrawable" | ||||
|         app:iconGravity="textStart" | ||||
|         app:iconPadding="0dp" | ||||
| @ -104,6 +107,7 @@ | ||||
|         style="@style/Widget.MaterialComponents.Button.TextButton" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="40dp" | ||||
|         android:background="@drawable/background_grey_ripple" | ||||
|         android:visibility="visible" | ||||
|         app:icon="@drawable/ic_round_bookmark_border_24" | ||||
|         app:iconGravity="textStart" | ||||
| @ -120,6 +124,7 @@ | ||||
|         style="@style/Widget.MaterialComponents.Button.TextButton" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="40dp" | ||||
|         android:background="@drawable/background_grey_ripple" | ||||
|         android:visibility="visible" | ||||
|         app:icon="@drawable/ic_download" | ||||
|         app:iconGravity="textStart" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user