barinsta/app/src/main/java/awais/instagrabber/adapters/viewholder/feed/FeedSliderViewHolder.java

342 lines
16 KiB
Java

package awais.instagrabber.adapters.viewholder.feed;
import android.content.Context;
import android.net.Uri;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ViewSwitcher;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
import awais.instagrabber.R;
import awais.instagrabber.databinding.ItemFeedSliderBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.FeedModel;
import awais.instagrabber.models.ViewerPostModel;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
import static awais.instagrabber.utils.Utils.settingsHelper;
public class FeedSliderViewHolder extends FeedItemViewHolder {
private static final String TAG = "FeedSliderViewHolder";
private static final boolean shouldAutoPlay = settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS);
private final ItemFeedSliderBinding binding;
private final DefaultDataSourceFactory dataSourceFactory;
private final PlayerChangeListener playerChangeListener = (position, player) -> {
pagerPlayer = player;
playerPosition = position;
};
private CacheDataSourceFactory cacheDataSourceFactory;
private SimpleExoPlayer pagerPlayer;
private int playerPosition = 0;
public FeedSliderViewHolder(@NonNull final ItemFeedSliderBinding binding,
final MentionClickListener mentionClickListener,
final View.OnClickListener clickListener,
final View.OnLongClickListener longClickListener) {
super(binding.getRoot(), binding.itemFeedTop, binding.itemFeedBottom, mentionClickListener, clickListener, longClickListener);
this.binding = binding;
binding.itemFeedBottom.videoViewsContainer.setVisibility(View.GONE);
binding.itemFeedBottom.btnMute.setVisibility(View.GONE);
final ViewGroup.LayoutParams layoutParams = binding.mediaList.getLayoutParams();
layoutParams.height = Utils.displayMetrics.widthPixels + 1;
binding.mediaList.setLayoutParams(layoutParams);
final Context context = binding.getRoot().getContext();
dataSourceFactory = new DefaultDataSourceFactory(context, "instagram");
final SimpleCache simpleCache = Utils.getSimpleCacheInstance(context);
if (simpleCache != null) {
cacheDataSourceFactory = new CacheDataSourceFactory(simpleCache, dataSourceFactory);
}
}
@Override
public void bindItem(final FeedModel feedModel) {
final ViewerPostModel[] sliderItems = feedModel.getSliderItems();
final int sliderItemLen = sliderItems != null ? sliderItems.length : 0;
if (sliderItemLen <= 0) {
return;
}
final String text = "1/" + sliderItemLen;
binding.mediaCounter.setText(text);
binding.mediaList.setOffscreenPageLimit(Math.min(5, sliderItemLen));
final PagerAdapter adapter = binding.mediaList.getAdapter();
if (adapter != null) {
final int count = adapter.getCount();
for (int i = 0; i < count; i++) {
adapter.destroyItem(binding.mediaList, i, binding.mediaList.getChildAt(i));
}
}
final ChildMediaItemsAdapter itemsAdapter = new ChildMediaItemsAdapter(sliderItems,
cacheDataSourceFactory != null
? cacheDataSourceFactory
: dataSourceFactory,
playerChangeListener);
binding.mediaList.setAdapter(itemsAdapter);
//noinspection deprecation
binding.mediaList.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
private int prevPos = 0;
@Override
public void onPageSelected(final int position) {
ViewerPostModel sliderItem = sliderItems[prevPos];
if (sliderItem != null) {
sliderItem.setSelected(false);
if (sliderItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) {
// stop playing prev video
final ViewSwitcher prevChild = (ViewSwitcher) binding.mediaList.getChildAt(prevPos);
if (prevChild == null || prevChild.getTag() == null || !(prevChild.getTag() instanceof SimpleExoPlayer)) {
return;
}
((SimpleExoPlayer) prevChild.getTag()).setPlayWhenReady(false);
}
}
sliderItem = sliderItems[position];
if (sliderItem == null) return;
sliderItem.setSelected(true);
final String text = (position + 1) + "/" + sliderItemLen;
binding.mediaCounter.setText(text);
prevPos = position;
if (sliderItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) {
binding.itemFeedBottom.btnMute.setVisibility(View.VISIBLE);
if (shouldAutoPlay) {
autoPlay(position);
}
} else binding.itemFeedBottom.btnMute.setVisibility(View.GONE);
}
});
final View.OnClickListener muteClickListener = v -> {
final int currentItem = binding.mediaList.getCurrentItem();
if (currentItem < 0 || currentItem >= binding.mediaList.getChildCount()) {
return;
}
final ViewerPostModel sliderItem = sliderItems[currentItem];
if (sliderItem.getItemType() != MediaItemType.MEDIA_TYPE_VIDEO) {
return;
}
final View currentView = binding.mediaList.getChildAt(currentItem);
if (!(currentView instanceof ViewSwitcher)) {
return;
}
final ViewSwitcher viewSwitcher = (ViewSwitcher) currentView;
final Object tag = viewSwitcher.getTag();
if (!(tag instanceof SimpleExoPlayer)) {
return;
}
final SimpleExoPlayer player = (SimpleExoPlayer) tag;
final float intVol = player.getVolume() == 0f ? 1f : 0f;
player.setVolume(intVol);
binding.itemFeedBottom.btnMute.setImageResource(intVol == 0f ? R.drawable.ic_volume_up_24 : R.drawable.ic_volume_off_24);
Utils.sessionVolumeFull = intVol == 1f;
};
final ViewerPostModel firstItem = sliderItems[0];
if (firstItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) {
binding.itemFeedBottom.btnMute.setVisibility(View.VISIBLE);
}
binding.itemFeedBottom.btnMute.setImageResource(Utils.sessionVolumeFull ? R.drawable.ic_volume_off_24 : R.drawable.ic_volume_up_24);
binding.itemFeedBottom.btnMute.setOnClickListener(muteClickListener);
}
private void autoPlay(final int position) {
if (!shouldAutoPlay) {
return;
}
final ChildMediaItemsAdapter adapter = (ChildMediaItemsAdapter) binding.mediaList.getAdapter();
if (adapter == null) {
return;
}
final ViewerPostModel sliderItem = adapter.getItemAtPosition(position);
if (sliderItem.getItemType() != MediaItemType.MEDIA_TYPE_VIDEO) {
return;
}
final ViewSwitcher viewSwitcher = (ViewSwitcher) binding.mediaList.getChildAt(position);
loadPlayer(binding.getRoot().getContext(),
position, sliderItem.getDisplayUrl(),
viewSwitcher,
cacheDataSourceFactory != null ? cacheDataSourceFactory : dataSourceFactory,
playerChangeListener);
}
public void startPlayingVideo() {
autoPlay(playerPosition);
}
public void stopPlayingVideo() {
if (pagerPlayer == null) {
return;
}
pagerPlayer.setPlayWhenReady(false);
}
private interface PlayerChangeListener {
void playerChanged(final int position, final SimpleExoPlayer player);
}
private static void loadPlayer(final Context context,
final int position, final String displayUrl,
final ViewSwitcher viewSwitcher,
final DataSource.Factory factory,
final PlayerChangeListener playerChangeListener) {
if (viewSwitcher == null) {
return;
}
SimpleExoPlayer player = (SimpleExoPlayer) viewSwitcher.getTag();
if (player != null) {
player.setPlayWhenReady(true);
return;
}
player = new SimpleExoPlayer.Builder(context).build();
final PlayerView playerView = (PlayerView) viewSwitcher.getChildAt(1);
playerView.setPlayer(player);
if (viewSwitcher.getDisplayedChild() == 0) {
viewSwitcher.showNext();
}
playerView.setControllerShowTimeoutMs(1000);
float vol = settingsHelper.getBoolean(Constants.MUTED_VIDEOS) ? 0f : 1f;
if (vol == 0f && Utils.sessionVolumeFull) vol = 1f;
player.setVolume(vol);
player.setPlayWhenReady(Utils.settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));
final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(displayUrl));
player.setRepeatMode(Player.REPEAT_MODE_ALL);
player.prepare(mediaSource);
player.setVolume(vol);
playerChangeListener.playerChanged(position, player);
viewSwitcher.setTag(player);
}
private static final class ChildMediaItemsAdapter extends PagerAdapter {
// private static final String TAG = "ChildMediaItemsAdapter";
private final ViewerPostModel[] sliderItems;
private final DataSource.Factory factory;
private final PlayerChangeListener playerChangeListener;
private final ViewGroup.LayoutParams layoutParams;
private ChildMediaItemsAdapter(final ViewerPostModel[] sliderItems,
final DataSource.Factory factory,
final PlayerChangeListener playerChangeListener) {
this.sliderItems = sliderItems;
this.factory = factory;
this.playerChangeListener = playerChangeListener;
layoutParams = new ViewGroup.LayoutParams(Utils.displayMetrics.widthPixels, Utils.displayMetrics.widthPixels + 1);
}
@NonNull
@Override
public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
final Context context = container.getContext();
final ViewerPostModel sliderItem = sliderItems[position];
final String displayUrl = sliderItem.getDisplayUrl();
if (sliderItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) {
final ViewSwitcher viewSwitcher = createViewSwitcher(context, position, sliderItem.getSliderDisplayUrl(), displayUrl);
container.addView(viewSwitcher);
return viewSwitcher;
}
final GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder.newInstance(container.getResources())
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.build();
final SimpleDraweeView photoView = new SimpleDraweeView(context, hierarchy);
photoView.setLayoutParams(layoutParams);
final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(displayUrl))
.setLocalThumbnailPreviewsEnabled(true)
.setProgressiveRenderingEnabled(true)
.build();
photoView.setImageRequest(imageRequest);
container.addView(photoView);
return photoView;
}
@NonNull
private ViewSwitcher createViewSwitcher(final Context context, final int position, final String sliderDisplayUrl, final String displayUrl) {
final ViewSwitcher viewSwitcher = new ViewSwitcher(context);
viewSwitcher.setLayoutParams(layoutParams);
final FrameLayout frameLayout = new FrameLayout(context);
frameLayout.setLayoutParams(layoutParams);
final GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(context.getResources())
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.build();
final SimpleDraweeView simpleDraweeView = new SimpleDraweeView(context, hierarchy);
simpleDraweeView.setLayoutParams(layoutParams);
simpleDraweeView.setImageURI(sliderDisplayUrl);
frameLayout.addView(simpleDraweeView);
final AppCompatImageView imageView = new AppCompatImageView(context);
final int px = Utils.convertDpToPx(50);
final FrameLayout.LayoutParams playButtonLayoutParams = new FrameLayout.LayoutParams(px, px);
playButtonLayoutParams.gravity = Gravity.CENTER;
imageView.setLayoutParams(playButtonLayoutParams);
imageView.setImageResource(R.drawable.exo_icon_play);
frameLayout.addView(imageView);
viewSwitcher.addView(frameLayout);
final PlayerView playerView = new PlayerView(context);
viewSwitcher.addView(playerView);
if (shouldAutoPlay && position == 0) {
loadPlayer(context, position, displayUrl, viewSwitcher, factory, playerChangeListener);
} else
frameLayout.setOnClickListener(v -> loadPlayer(context, position, displayUrl, viewSwitcher, factory, playerChangeListener));
return viewSwitcher;
}
@Override
public void destroyItem(@NonNull final ViewGroup container, final int position, @NonNull final Object object) {
final View view = container.getChildAt(position);
// Log.d(TAG, "destroy position: " + position + ", view: " + view);
if (view instanceof ViewSwitcher) {
final Object tag = view.getTag();
if (tag instanceof SimpleExoPlayer) {
final SimpleExoPlayer player = (SimpleExoPlayer) tag;
player.release();
}
}
container.removeView((View) object);
}
@Override
public int getCount() {
return sliderItems != null ? sliderItems.length : 0;
}
@Override
public boolean isViewFromObject(@NonNull final View view, @NonNull final Object object) {
return view.equals(object);
}
public ViewerPostModel getItemAtPosition(final int position) {
return sliderItems[0];
}
}
}