mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 11:35:34 +00:00 
			
		
		
		
	Handle multiple videos in PostViewV2Fragment. Should fix https://github.com/austinhuang0131/barinsta/issues/337 and also fix videos playing after closing view.
This commit is contained in:
		
							parent
							
								
									6b370ca251
								
							
						
					
					
						commit
						dccfcaf78a
					
				| @ -22,7 +22,7 @@ public final class SliderItemsAdapter extends ListAdapter<PostChild, SliderItemV | ||||
|     private final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener; | ||||
|     private final boolean loadVideoOnItemClick; | ||||
|     private final SliderCallback sliderCallback; | ||||
|     private final awais.instagrabber.databinding.LayoutExoCustomControlsBinding controlsBinding; | ||||
|     private final LayoutExoCustomControlsBinding controlsBinding; | ||||
| 
 | ||||
|     private static final DiffUtil.ItemCallback<PostChild> DIFF_CALLBACK = new DiffUtil.ItemCallback<PostChild>() { | ||||
|         @Override | ||||
|  | ||||
| @ -135,6 +135,16 @@ 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(); | ||||
|     } | ||||
| 
 | ||||
|     // 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; | ||||
|  | ||||
| @ -10,6 +10,7 @@ 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; | ||||
| @ -26,6 +27,8 @@ 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 awais.instagrabber.R; | ||||
| import awais.instagrabber.databinding.LayoutExoCustomControlsBinding; | ||||
| @ -39,6 +42,8 @@ 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 final Context context; | ||||
|     private final awais.instagrabber.databinding.LayoutVideoPlayerWithThumbnailBinding binding; | ||||
| @ -52,6 +57,62 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|     private final DefaultDataSourceFactory dataSourceFactory; | ||||
|     private SimpleExoPlayer player; | ||||
|     private PopupMenu speedPopup; | ||||
|     private Runnable positionChecker; | ||||
| 
 | ||||
|     private final Handler positionUpdateHandler = new Handler(); | ||||
|     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); | ||||
|         } | ||||
|     }; | ||||
|     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 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, | ||||
| @ -130,6 +191,10 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|         player = new SimpleExoPlayer.Builder(context) | ||||
|                 .setLooper(Looper.getMainLooper()) | ||||
|                 .build(); | ||||
|         positionChecker = new PositionCheckRunnable(positionUpdateHandler, | ||||
|                                                     player, | ||||
|                                                     controlsBinding.timeline, | ||||
|                                                     controlsBinding.fromTime); | ||||
|         player.addListener(this); | ||||
|         player.setVolume(initialVolume); | ||||
|         player.setPlayWhenReady(true); | ||||
| @ -148,87 +213,22 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|         binding.playerView.setUseController(false); | ||||
|         if (player == null) { | ||||
|             enableControls(false); | ||||
|             controlsBinding.playPause.setEnabled(true); | ||||
|             controlsBinding.playPause.setOnClickListener(v -> binding.thumbnailParent.performClick()); | ||||
|             // controlsBinding.playPause.setEnabled(true); | ||||
|             // controlsBinding.playPause.setOnClickListener(new NoPlayerPlayPauseClickListener(binding.thumbnailParent)); | ||||
|             return; | ||||
|         } | ||||
|         enableControls(true); | ||||
|         final Handler handler = new Handler(); | ||||
|         final long initialDelay = 0; | ||||
|         final long recurringDelay = 60; | ||||
|         final Runnable positionChecker = new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 handler.removeCallbacks(this); | ||||
|                 if (player == null) return; | ||||
|                 final long currentPosition = player.getCurrentPosition(); | ||||
|                 final long duration = player.getDuration(); | ||||
|                 if (duration == TIME_UNSET) { | ||||
|                     controlsBinding.timeline.setValueFrom(0); | ||||
|                     controlsBinding.timeline.setValueTo(0); | ||||
|                     controlsBinding.timeline.setEnabled(false); | ||||
|                     return; | ||||
|                 } | ||||
|                 controlsBinding.timeline.setValue(Math.min(currentPosition, duration)); | ||||
|                 controlsBinding.fromTime.setText(TextUtils.millisToTimeString(currentPosition)); | ||||
|                 handler.postDelayed(this, recurringDelay); | ||||
|             } | ||||
|         }; | ||||
|         updatePlayPauseDrawable(player.getPlayWhenReady()); | ||||
|         updateMuteIcon(player.getVolume()); | ||||
|         player.addListener(new Player.EventListener() { | ||||
|             @Override | ||||
|             public void onPlaybackStateChanged(final int state) { | ||||
|                 switch (state) { | ||||
|                     case Player.STATE_BUFFERING: | ||||
|                     case STATE_IDLE: | ||||
|                     case STATE_ENDED: | ||||
|                         handler.removeCallbacks(positionChecker); | ||||
|                         return; | ||||
|                     case STATE_READY: | ||||
|                         setupTimeline(); | ||||
|                         handler.postDelayed(positionChecker, initialDelay); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason) { | ||||
|                 updatePlayPauseDrawable(playWhenReady); | ||||
|             } | ||||
|         }); | ||||
|         player.addAudioListener(new AudioListener() { | ||||
|             @Override | ||||
|             public void onVolumeChanged(final float volume) { | ||||
|                 updateMuteIcon(volume); | ||||
|             } | ||||
|         }); | ||||
|         controlsBinding.timeline.addOnChangeListener((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); | ||||
|         }); | ||||
|         controlsBinding.timeline.setLabelFormatter(value -> TextUtils.millisToTimeString((long) value)); | ||||
|         controlsBinding.playPause.setOnClickListener(v -> player.setPlayWhenReady(!player.getPlayWhenReady())); | ||||
|         controlsBinding.mute.setOnClickListener(v -> toggleMute()); | ||||
|         controlsBinding.rewWithAmount.setOnClickListener(v -> { | ||||
|             final long positionMs = player.getCurrentPosition() - 5000; | ||||
|             player.seekTo(positionMs < 0 ? 0 : positionMs); | ||||
|         }); | ||||
|         controlsBinding.ffWithAmount.setOnClickListener(v -> { | ||||
|             long positionMs = player.getCurrentPosition() + 5000; | ||||
|             long duration = player.getDuration(); | ||||
|             if (duration == TIME_UNSET) { | ||||
|                 duration = 0; | ||||
|             } | ||||
|             player.seekTo(Math.min(positionMs, duration)); | ||||
|         }); | ||||
|         controlsBinding.speed.setOnClickListener(this::showMenu); | ||||
|         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() { | ||||
| @ -242,12 +242,18 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
| 
 | ||||
|     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) { | ||||
| @ -302,10 +308,10 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
| 
 | ||||
|     private void updateMuteIcon(final float volume) { | ||||
|         if (volume == 0) { | ||||
|             controlsBinding.mute.setIconResource(R.drawable.ic_volume_off_24); | ||||
|             controlsBinding.mute.setIconResource(R.drawable.ic_volume_off_24_states); | ||||
|             return; | ||||
|         } | ||||
|         controlsBinding.mute.setIconResource(R.drawable.ic_volume_up_24); | ||||
|         controlsBinding.mute.setIconResource(R.drawable.ic_volume_up_24_states); | ||||
|     } | ||||
| 
 | ||||
|     private void updatePlayPauseDrawable(final boolean playWhenReady) { | ||||
| @ -313,7 +319,7 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|             controlsBinding.playPause.setIconResource(R.drawable.ic_pause_24); | ||||
|             return; | ||||
|         } | ||||
|         controlsBinding.playPause.setIconResource(R.drawable.ic_play_arrow_24); | ||||
|         controlsBinding.playPause.setIconResource(R.drawable.ic_play_states); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @ -338,23 +344,88 @@ public class VideoPlayerViewHelper implements Player.EventListener { | ||||
|         return 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 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 (player == null) return; | ||||
|         player.release(); | ||||
|         player = null; | ||||
|         if (positionUpdateHandler != null && positionChecker != null) { | ||||
|             positionUpdateHandler.removeCallbacks(positionChecker); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public void pause() { | ||||
|         if (player == null) return; | ||||
|         player.pause(); | ||||
|         if (positionUpdateHandler != null && 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() { | ||||
|             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 { | ||||
|  | ||||
| @ -113,6 +113,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|     private int sliderPosition = -1; | ||||
|     private DialogInterface.OnShowListener onShowListener; | ||||
|     private boolean isLoggedIn; | ||||
|     private boolean hasBeenToggled = false; | ||||
| 
 | ||||
|     private final VerticalDragHelper.OnVerticalDragListener onVerticalDragListener = new VerticalDragHelper.OnVerticalDragListener() { | ||||
| 
 | ||||
| @ -303,8 +304,8 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|     public void onDestroyView() { | ||||
|         super.onDestroyView(); | ||||
|         switch (feedModel.getItemType()) { | ||||
|             case MEDIA_TYPE_VIDEO: | ||||
|                 if (videoPlayerViewHelper != null) { | ||||
| @ -870,6 +871,20 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|         if (!wasPaused && sharedMainPostElement != null) { | ||||
|             addSharedElement(sharedMainPostElement, binding.sliderParent); | ||||
|         } | ||||
|         final boolean hasVideo = feedModel.getSliderItems() | ||||
|                                           .stream() | ||||
|                                           .anyMatch(postChild -> postChild.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO); | ||||
|         if (hasVideo) { | ||||
|             final View child = binding.sliderParent.getChildAt(0); | ||||
|             if (child instanceof RecyclerView) { | ||||
|                 ((RecyclerView) child).setItemViewCacheSize(feedModel.getSliderItems().size()); | ||||
|                 ((RecyclerView) child).addRecyclerListener(holder -> { | ||||
|                     if (holder instanceof SliderVideoViewHolder) { | ||||
|                         ((SliderVideoViewHolder) holder).releasePlayer(); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         sliderItemsAdapter = new SliderItemsAdapter(onVerticalDragListener, binding.playerControls, true, new SliderCallbackAdapter() { | ||||
|             @Override | ||||
|             public void onThumbnailLoaded(final int position) { | ||||
| @ -879,19 +894,17 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
| 
 | ||||
|             @Override | ||||
|             public void onItemClicked(final int position) { | ||||
|                 toggleDetails(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onPlayerPlay(final int position) { | ||||
|                 if (!detailsVisible) return; | ||||
|                 toggleDetails(); | ||||
|                 if (!detailsVisible || hasBeenToggled) return; | ||||
|                 showPlayerControls(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onPlayerPause(final int position) { | ||||
|                 if (detailsVisible) return; | ||||
|                 if (detailsVisible || hasBeenToggled) return; | ||||
|                 toggleDetails(); | ||||
|             } | ||||
|         }); | ||||
| @ -924,7 +937,22 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|                 final String text = (position + 1) + "/" + size; | ||||
|                 binding.mediaCounter.setText(text); | ||||
|                 final PostChild postChild = feedModel.getSliderItems().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 (postChild.getItemType() == 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); | ||||
|                     return; | ||||
|                 } | ||||
| @ -1052,6 +1080,9 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|         hideCaption(); | ||||
|         // previously invisible view | ||||
|         View view = binding.playerControls.getRoot(); | ||||
|         if (view != null && view.getVisibility() == View.VISIBLE) { | ||||
|             return; | ||||
|         } | ||||
|         if (!ViewCompat.isAttachedToWindow(view)) { | ||||
|             view.setVisibility(View.VISIBLE); | ||||
|             return; | ||||
| @ -1076,6 +1107,9 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|     private void hidePlayerControls() { | ||||
|         // previously visible view | ||||
|         final View view = binding.playerControls.getRoot(); | ||||
|         if (view != null && view.getVisibility() == View.GONE) { | ||||
|             return; | ||||
|         } | ||||
|         if (!ViewCompat.isAttachedToWindow(view)) { | ||||
|             view.setVisibility(View.GONE); | ||||
|             return; | ||||
| @ -1106,6 +1140,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment { | ||||
|     } | ||||
| 
 | ||||
|     private void toggleDetails() { | ||||
|         hasBeenToggled = true; | ||||
|         binding.getRoot().post(() -> { | ||||
|             TransitionManager.beginDelayedTransition(binding.getRoot()); | ||||
|             if (detailsVisible) { | ||||
|  | ||||
							
								
								
									
										15
									
								
								app/src/main/res/drawable/ic_forward_5_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/src/main/res/drawable/ic_forward_5_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="?attr/colorControlNormal" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillAlpha="0.5" | ||||
|         android:fillColor="@android:color/white" | ||||
|         android:pathData="M18,13c0,3.31 -2.69,6 -6,6s-6,-2.69 -6,-6s2.69,-6 6,-6v4l5,-5l-5,-5v4c-4.42,0 -8,3.58 -8,8c0,4.42 3.58,8 8,8c4.42,0 8,-3.58 8,-8H18z" /> | ||||
|     <path | ||||
|         android:fillAlpha="0.5" | ||||
|         android:fillColor="@android:color/white" | ||||
|         android:pathData="M12.03,15.38c-0.44,0 -0.58,-0.31 -0.6,-0.56h-0.84c0.03,0.85 0.79,1.25 1.44,1.25c0.93,0 1.44,-0.63 1.44,-1.43c0,-1.33 -0.97,-1.44 -1.3,-1.44c-0.2,0 -0.43,0.05 -0.64,0.16l0.11,-0.92h1.7v-0.71h-2.39l-0.25,2.17l0.67,0.17c0.13,-0.13 0.28,-0.23 0.57,-0.23c0.4,0 0.69,0.23 0.69,0.75C12.62,14.64 12.65,15.38 12.03,15.38z" /> | ||||
| </vector> | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_forward_5_24_states.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_forward_5_24_states.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:drawable="@drawable/ic_forward_5_24_a50" android:state_enabled="false" /> | ||||
|     <item android:drawable="@drawable/ic_forward_5_24" android:state_enabled="true" /> | ||||
| </selector> | ||||
							
								
								
									
										11
									
								
								app/src/main/res/drawable/ic_play_arrow_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/src/main/res/drawable/ic_play_arrow_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24" | ||||
|     android:tint="?attr/colorControlNormal"> | ||||
|   <path | ||||
|       android:fillColor="@android:color/white" | ||||
|       android:fillAlpha="0.5" | ||||
|       android:pathData="M8,5v14l11,-7z"/> | ||||
| </vector> | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_play_states.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_play_states.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:drawable="@drawable/ic_play_arrow_24_a50" android:state_enabled="false" /> | ||||
|     <item android:drawable="@drawable/ic_play_arrow_24" android:state_enabled="true" /> | ||||
| </selector> | ||||
							
								
								
									
										15
									
								
								app/src/main/res/drawable/ic_replay_5_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/src/main/res/drawable/ic_replay_5_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="?attr/colorControlNormal" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillAlpha="0.5" | ||||
|         android:fillColor="@android:color/white" | ||||
|         android:pathData="M12,5V1L7,6l5,5V7c3.31,0 6,2.69 6,6s-2.69,6 -6,6s-6,-2.69 -6,-6H4c0,4.42 3.58,8 8,8s8,-3.58 8,-8S16.42,5 12,5z" /> | ||||
|     <path | ||||
|         android:fillAlpha="0.5" | ||||
|         android:fillColor="@android:color/white" | ||||
|         android:pathData="M10.69,13.9l0.25,-2.17h2.39v0.71h-1.7l-0.11,0.92c0.03,-0.02 0.07,-0.03 0.11,-0.05s0.09,-0.04 0.15,-0.05s0.12,-0.03 0.18,-0.04s0.13,-0.02 0.2,-0.02c0.21,0 0.39,0.03 0.55,0.1s0.3,0.16 0.41,0.28s0.2,0.27 0.25,0.45s0.09,0.38 0.09,0.6c0,0.19 -0.03,0.37 -0.09,0.54s-0.15,0.32 -0.27,0.45s-0.27,0.24 -0.45,0.31s-0.39,0.12 -0.64,0.12c-0.18,0 -0.36,-0.03 -0.53,-0.08s-0.32,-0.14 -0.46,-0.24s-0.24,-0.24 -0.32,-0.39s-0.13,-0.33 -0.13,-0.53h0.84c0.02,0.18 0.08,0.32 0.19,0.41s0.25,0.15 0.42,0.15c0.11,0 0.2,-0.02 0.27,-0.06s0.14,-0.1 0.18,-0.17s0.08,-0.15 0.11,-0.25s0.03,-0.2 0.03,-0.31s-0.01,-0.21 -0.04,-0.31s-0.07,-0.17 -0.13,-0.24s-0.13,-0.12 -0.21,-0.15s-0.19,-0.05 -0.3,-0.05c-0.08,0 -0.15,0.01 -0.2,0.02s-0.11,0.03 -0.15,0.05s-0.08,0.05 -0.12,0.07s-0.07,0.06 -0.1,0.09L10.69,13.9z" /> | ||||
| </vector> | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_replay_5_24_states.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_replay_5_24_states.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:drawable="@drawable/ic_replay_5_24_a50" android:state_enabled="false" /> | ||||
|     <item android:drawable="@drawable/ic_replay_5_24" android:state_enabled="true" /> | ||||
| </selector> | ||||
							
								
								
									
										11
									
								
								app/src/main/res/drawable/ic_volume_off_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/src/main/res/drawable/ic_volume_off_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="?attr/colorControlNormal" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillAlpha="0.5" | ||||
|         android:fillColor="@android:color/white" | ||||
|         android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z" /> | ||||
| </vector> | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_volume_off_24_states.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_volume_off_24_states.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:drawable="@drawable/ic_volume_off_24_a50" android:state_enabled="false" /> | ||||
|     <item android:drawable="@drawable/ic_volume_off_24" android:state_enabled="true" /> | ||||
| </selector> | ||||
							
								
								
									
										11
									
								
								app/src/main/res/drawable/ic_volume_up_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/src/main/res/drawable/ic_volume_up_24_a50.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="?attr/colorControlNormal" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillAlpha="0.5" | ||||
|         android:fillColor="@android:color/white" | ||||
|         android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z" /> | ||||
| </vector> | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_volume_up_24_states.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_volume_up_24_states.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:drawable="@drawable/ic_volume_up_24_a50" android:state_enabled="false" /> | ||||
|     <item android:drawable="@drawable/ic_volume_up_24" android:state_enabled="true" /> | ||||
| </selector> | ||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/speed_text_color_states.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/speed_text_color_states.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:color="@color/white_a50" android:state_enabled="false" /> | ||||
|     <item android:color="@color/white" android:state_enabled="true" /> | ||||
| </selector> | ||||
| @ -53,13 +53,14 @@ | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:visibility="visible" | ||||
|         app:icon="@drawable/ic_replay_5_24" | ||||
|         app:icon="@drawable/ic_replay_5_24_states" | ||||
|         app:iconSize="24dp" | ||||
|         app:iconTint="@color/white" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@id/play_pause" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@id/timeline" | ||||
|         tools:enabled="false" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
|     <com.google.android.material.button.MaterialButton | ||||
| @ -67,13 +68,14 @@ | ||||
|         style="@style/Widget.App.MaterialButton.IconOnly.BorderlessRipple" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:icon="@drawable/ic_play_arrow_24" | ||||
|         app:icon="@drawable/ic_play_states" | ||||
|         app:iconSize="24dp" | ||||
|         app:iconTint="@color/white" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@id/ff_with_amount" | ||||
|         app:layout_constraintStart_toEndOf="@id/rew_with_amount" | ||||
|         app:layout_constraintTop_toBottomOf="@id/timeline" | ||||
|         tools:enabled="false" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
|     <com.google.android.material.button.MaterialButton | ||||
| @ -81,13 +83,14 @@ | ||||
|         style="@style/Widget.App.MaterialButton.IconOnly.BorderlessRipple" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:icon="@drawable/ic_forward_5_24" | ||||
|         app:icon="@drawable/ic_forward_5_24_states" | ||||
|         app:iconSize="24dp" | ||||
|         app:iconTint="@color/white" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@id/mute" | ||||
|         app:layout_constraintStart_toEndOf="@id/play_pause" | ||||
|         app:layout_constraintTop_toBottomOf="@id/timeline" | ||||
|         tools:enabled="false" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
|     <com.google.android.material.button.MaterialButton | ||||
| @ -95,13 +98,14 @@ | ||||
|         style="@style/Widget.App.MaterialButton.IconOnly.BorderlessRipple" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:icon="@drawable/ic_volume_off_24" | ||||
|         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" | ||||
|         tools:enabled="false" | ||||
|         tools:visibility="visible" /> | ||||
| 
 | ||||
|     <com.google.android.material.button.MaterialButton | ||||
| @ -111,10 +115,11 @@ | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/one_x" | ||||
|         android:textAllCaps="false" | ||||
|         android:textColor="@color/white" | ||||
|         android:textColor="@drawable/speed_text_color_states" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@id/mute" | ||||
|         app:layout_constraintTop_toBottomOf="@id/timeline" | ||||
|         tools:enabled="false" | ||||
|         tools:visibility="visible" /> | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| @ -33,6 +33,7 @@ | ||||
|     <color name="comment_selected">#888888</color> | ||||
| 
 | ||||
|     <color name="white">#FFFFFF</color> | ||||
|     <color name="white_a50">#80FFFFFF</color> | ||||
| 
 | ||||
|     <color name="black">#000000</color> | ||||
|     <color name="black_800">#121212</color> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user