342 lines
16 KiB
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];
|
|
}
|
|
}
|
|
}
|