mirror of https://github.com/KokaKiwi/BarInsta
486 lines
23 KiB
Java
Executable File
486 lines
23 KiB
Java
Executable File
package awais.instagrabber.adapters;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.graphics.Typeface;
|
|
import android.net.Uri;
|
|
import android.text.SpannableStringBuilder;
|
|
import android.text.Spanned;
|
|
import android.text.style.StyleSpan;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.appcompat.app.AlertDialog;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
import androidx.viewpager.widget.PagerAdapter;
|
|
import androidx.viewpager.widget.ViewPager;
|
|
|
|
import com.bumptech.glide.Glide;
|
|
import com.bumptech.glide.RequestManager;
|
|
import com.github.chrisbanes.photoview.PhotoView;
|
|
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.DefaultDataSourceFactory;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
|
|
import awais.instagrabber.BuildConfig;
|
|
import awais.instagrabber.R;
|
|
import awais.instagrabber.activities.CommentsViewer;
|
|
import awais.instagrabber.activities.PostViewer;
|
|
import awais.instagrabber.adapters.viewholder.FeedItemViewHolder;
|
|
import awais.instagrabber.customviews.CommentMentionClickSpan;
|
|
import awais.instagrabber.customviews.RamboTextView;
|
|
import awais.instagrabber.interfaces.MentionClickListener;
|
|
import awais.instagrabber.models.BasePostModel;
|
|
import awais.instagrabber.models.FeedModel;
|
|
import awais.instagrabber.models.PostModel;
|
|
import awais.instagrabber.models.ProfileModel;
|
|
import awais.instagrabber.models.ViewerPostModel;
|
|
import awais.instagrabber.models.enums.DownloadMethod;
|
|
import awais.instagrabber.models.enums.ItemGetType;
|
|
import awais.instagrabber.models.enums.MediaItemType;
|
|
import awais.instagrabber.utils.Constants;
|
|
import awais.instagrabber.utils.Utils;
|
|
|
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
|
|
|
public final class FeedAdapter extends RecyclerView.Adapter<FeedItemViewHolder> {
|
|
private final static String ellipsize = "… more";
|
|
private final Activity activity;
|
|
private final LayoutInflater layoutInflater;
|
|
private final ArrayList<FeedModel> feedModels;
|
|
private final MentionClickListener mentionClickListener;
|
|
private final View.OnClickListener clickListener = new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(@NonNull final View v) {
|
|
final Object tag = v.getTag();
|
|
|
|
if (tag instanceof FeedModel) {
|
|
final FeedModel feedModel = (FeedModel) tag;
|
|
|
|
if (v instanceof RamboTextView) {
|
|
if (feedModel.isMentionClicked())
|
|
feedModel.toggleCaption();
|
|
feedModel.setMentionClicked(false);
|
|
if (!expandCollapseTextView((RamboTextView) v, feedModel))
|
|
feedModel.toggleCaption();
|
|
|
|
} else {
|
|
final int id = v.getId();
|
|
switch (id) {
|
|
case R.id.btnComments:
|
|
activity.startActivityForResult(new Intent(activity, CommentsViewer.class)
|
|
.putExtra(Constants.EXTRAS_SHORTCODE, feedModel.getShortCode()), 6969);
|
|
break;
|
|
|
|
case R.id.viewStoryPost:
|
|
activity.startActivity(new Intent(activity, PostViewer.class)
|
|
.putExtra(Constants.EXTRAS_INDEX, feedModel.getPosition())
|
|
.putExtra(Constants.EXTRAS_POST, new PostModel(feedModel.getShortCode()))
|
|
.putExtra(Constants.EXTRAS_TYPE, ItemGetType.FEED_ITEMS));
|
|
break;
|
|
|
|
case R.id.btnDownload:
|
|
final Context context = v.getContext();
|
|
ProfileModel profileModel = feedModel.getProfileModel();
|
|
final String username = profileModel != null ? profileModel.getUsername() : null;
|
|
|
|
final ViewerPostModel[] sliderItems = feedModel.getSliderItems();
|
|
|
|
if (feedModel.getItemType() != MediaItemType.MEDIA_TYPE_SLIDER || sliderItems == null || sliderItems.length == 1)
|
|
Utils.batchDownload(context, username, DownloadMethod.DOWNLOAD_FEED, Collections.singletonList(feedModel));
|
|
else {
|
|
final ArrayList<BasePostModel> postModels = new ArrayList<>();
|
|
final DialogInterface.OnClickListener clickListener = (dialog, which) -> {
|
|
postModels.clear();
|
|
|
|
final boolean breakWhenFoundSelected = which == DialogInterface.BUTTON_POSITIVE;
|
|
|
|
for (final ViewerPostModel sliderItem : sliderItems) {
|
|
if (sliderItem != null) {
|
|
if (!breakWhenFoundSelected) postModels.add(sliderItem);
|
|
else if (sliderItem.isSelected()) {
|
|
postModels.add(sliderItem);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// shows 0 items on first item of viewpager cause onPageSelected hasn't been called yet
|
|
if (breakWhenFoundSelected && postModels.size() == 0)
|
|
postModels.add(sliderItems[0]);
|
|
|
|
if (postModels.size() > 0)
|
|
Utils.batchDownload(context, username, DownloadMethod.DOWNLOAD_FEED, postModels);
|
|
};
|
|
|
|
new AlertDialog.Builder(context).setTitle(R.string.post_viewer_download_dialog_title)
|
|
.setPositiveButton(R.string.post_viewer_download_current, clickListener)
|
|
.setNegativeButton(R.string.post_viewer_download_album, clickListener).show();
|
|
}
|
|
break;
|
|
|
|
case R.id.ivProfilePic:
|
|
if (mentionClickListener != null) {
|
|
profileModel = feedModel.getProfileModel();
|
|
if (profileModel != null)
|
|
mentionClickListener.onClick(null, profileModel.getUsername(), false);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
private final View.OnLongClickListener longClickListener = v -> {
|
|
final Object tag;
|
|
if (v instanceof RamboTextView && (tag = v.getTag()) instanceof FeedModel)
|
|
Utils.copyText(v.getContext(), ((FeedModel) tag).getPostCaption());
|
|
return true;
|
|
};
|
|
public SimpleExoPlayer pagerPlayer;
|
|
private final PlayerChangeListener playerChangeListener = (childPos, player) -> {
|
|
// todo
|
|
pagerPlayer = player;
|
|
};
|
|
|
|
public FeedAdapter(final Activity activity, final ArrayList<FeedModel> FeedModels, final MentionClickListener mentionClickListener) {
|
|
this.activity = activity;
|
|
this.feedModels = FeedModels;
|
|
this.mentionClickListener = mentionClickListener;
|
|
this.layoutInflater = LayoutInflater.from(activity);
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public FeedItemViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
|
final View view;
|
|
if (viewType == MediaItemType.MEDIA_TYPE_VIDEO.ordinal())
|
|
view = layoutInflater.inflate(R.layout.item_feed_video, parent, false);
|
|
else if (viewType == MediaItemType.MEDIA_TYPE_SLIDER.ordinal())
|
|
view = layoutInflater.inflate(R.layout.item_feed_slider, parent, false);
|
|
else
|
|
view = layoutInflater.inflate(R.layout.item_feed, parent, false);
|
|
return new FeedItemViewHolder(view);
|
|
}
|
|
|
|
@SuppressLint("SetTextI18n")
|
|
@Override
|
|
public void onBindViewHolder(@NonNull final FeedItemViewHolder viewHolder, final int position) {
|
|
final FeedModel feedModel = feedModels.get(position);
|
|
if (feedModel != null) {
|
|
final RequestManager glideRequestManager = Glide.with(viewHolder.itemView);
|
|
|
|
feedModel.setPosition(position);
|
|
|
|
viewHolder.viewPost.setTag(feedModel);
|
|
viewHolder.profilePic.setTag(feedModel);
|
|
viewHolder.btnDownload.setTag(feedModel);
|
|
viewHolder.viewerCaption.setTag(feedModel);
|
|
|
|
final ProfileModel profileModel = feedModel.getProfileModel();
|
|
if (profileModel != null) {
|
|
glideRequestManager.load(profileModel.getSdProfilePic()).into(viewHolder.profilePic);
|
|
viewHolder.username.setText(profileModel.getUsername());
|
|
}
|
|
|
|
viewHolder.viewPost.setOnClickListener(clickListener);
|
|
viewHolder.profilePic.setOnClickListener(clickListener);
|
|
viewHolder.btnDownload.setOnClickListener(clickListener);
|
|
|
|
viewHolder.tvPostDate.setText(feedModel.getPostDate());
|
|
|
|
final long commentsCount = feedModel.getCommentsCount();
|
|
viewHolder.commentsCount.setText(String.valueOf(commentsCount));
|
|
|
|
if (commentsCount <= 0) {
|
|
viewHolder.btnComments.setTag(null);
|
|
viewHolder.btnComments.setOnClickListener(null);
|
|
viewHolder.btnComments.setEnabled(false);
|
|
} else {
|
|
viewHolder.btnComments.setTag(feedModel);
|
|
viewHolder.btnComments.setOnClickListener(clickListener);
|
|
viewHolder.btnComments.setEnabled(true);
|
|
}
|
|
|
|
final String thumbnailUrl = feedModel.getThumbnailUrl();
|
|
final String displayUrl = feedModel.getDisplayUrl();
|
|
CharSequence postCaption = feedModel.getPostCaption();
|
|
|
|
final boolean captionEmpty = Utils.isEmpty(postCaption);
|
|
|
|
viewHolder.viewerCaption.setOnClickListener(clickListener);
|
|
viewHolder.viewerCaption.setOnLongClickListener(longClickListener);
|
|
viewHolder.viewerCaption.setVisibility(captionEmpty ? View.GONE : View.VISIBLE);
|
|
|
|
if (!captionEmpty && Utils.hasMentions(postCaption)) {
|
|
postCaption = Utils.getMentionText(postCaption);
|
|
feedModel.setPostCaption(postCaption);
|
|
viewHolder.viewerCaption.setText(postCaption, TextView.BufferType.SPANNABLE);
|
|
viewHolder.viewerCaption.setMentionClickListener(mentionClickListener);
|
|
} else {
|
|
viewHolder.viewerCaption.setText(postCaption);
|
|
}
|
|
|
|
expandCollapseTextView(viewHolder.viewerCaption, feedModel);
|
|
|
|
final MediaItemType itemType = feedModel.getItemType();
|
|
final View viewToChangeHeight;
|
|
|
|
if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) {
|
|
viewToChangeHeight = viewHolder.playerView;
|
|
|
|
viewHolder.videoViewsParent.setVisibility(View.VISIBLE);
|
|
viewHolder.videoViews.setText(String.valueOf(feedModel.getViewCount()));
|
|
} else {
|
|
viewHolder.videoViewsParent.setVisibility(View.GONE);
|
|
viewHolder.btnMute.setVisibility(View.GONE);
|
|
|
|
if (itemType == MediaItemType.MEDIA_TYPE_SLIDER) {
|
|
viewToChangeHeight = viewHolder.mediaList;
|
|
|
|
final ViewerPostModel[] sliderItems = feedModel.getSliderItems();
|
|
final int sliderItemLen = sliderItems != null ? sliderItems.length : 0;
|
|
|
|
if (sliderItemLen > 0) {
|
|
viewHolder.mediaCounter.setText("1/" + sliderItemLen);
|
|
viewHolder.mediaList.setOffscreenPageLimit(Math.min(5, sliderItemLen));
|
|
|
|
final ViewPager.SimpleOnPageChangeListener simpleOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
|
|
private int prevPos = 0;
|
|
|
|
@Override
|
|
public void onPageSelected(final int position) {
|
|
ViewerPostModel sliderItem = sliderItems[prevPos];
|
|
if (sliderItem != null) sliderItem.setSelected(false);
|
|
sliderItem = sliderItems[position];
|
|
if (sliderItem != null) sliderItem.setSelected(true);
|
|
|
|
View childAt = viewHolder.mediaList.getChildAt(prevPos);
|
|
if (childAt instanceof PlayerView) {
|
|
pagerPlayer = (SimpleExoPlayer) ((PlayerView) childAt).getPlayer();
|
|
if (pagerPlayer != null) pagerPlayer.setPlayWhenReady(false);
|
|
}
|
|
childAt = viewHolder.mediaList.getChildAt(position);
|
|
if (childAt instanceof PlayerView) {
|
|
pagerPlayer = (SimpleExoPlayer) ((PlayerView) childAt).getPlayer();
|
|
if (pagerPlayer != null) pagerPlayer.setPlayWhenReady(true);
|
|
}
|
|
prevPos = position;
|
|
viewHolder.mediaCounter.setText((position + 1) + "/" + sliderItemLen);
|
|
}
|
|
};
|
|
|
|
//noinspection deprecation
|
|
viewHolder.mediaList.setOnPageChangeListener(simpleOnPageChangeListener); // cause add listeners might add to recycled holders
|
|
|
|
final View.OnClickListener muteClickListener = v -> {
|
|
Player player = null;
|
|
if (v instanceof PlayerView) player = ((PlayerView) v).getPlayer();
|
|
else if (v instanceof ImageView || v == viewHolder.btnMute) {
|
|
final int currentItem = viewHolder.mediaList.getCurrentItem();
|
|
if (currentItem < viewHolder.mediaList.getChildCount()) {
|
|
final View childAt = viewHolder.mediaList.getChildAt(currentItem);
|
|
if (childAt instanceof PlayerView) player = ((PlayerView) childAt).getPlayer();
|
|
}
|
|
|
|
} else {
|
|
final Object tag = v.getTag();
|
|
if (tag instanceof Player) player = (Player) tag;
|
|
}
|
|
|
|
if (player instanceof SimpleExoPlayer) {
|
|
final SimpleExoPlayer exoPlayer = (SimpleExoPlayer) player;
|
|
final float intVol = exoPlayer.getVolume() == 0f ? 1f : 0f;
|
|
exoPlayer.setVolume(intVol);
|
|
viewHolder.btnMute.setImageResource(intVol == 0f ? R.drawable.vol : R.drawable.mute);
|
|
Utils.sessionVolumeFull = intVol == 1f;
|
|
}
|
|
};
|
|
|
|
viewHolder.btnMute.setOnClickListener(muteClickListener);
|
|
viewHolder.mediaList.setAdapter(new ChildMediaItemsAdapter(sliderItems, viewHolder.btnMute, muteClickListener, playerChangeListener));
|
|
}
|
|
} else {
|
|
viewToChangeHeight = viewHolder.imageView;
|
|
String url = displayUrl;
|
|
if (Utils.isEmpty(url)) url = thumbnailUrl;
|
|
glideRequestManager.load(url).into(viewHolder.imageView);
|
|
}
|
|
}
|
|
|
|
if (viewToChangeHeight != null) {
|
|
final ViewGroup.LayoutParams layoutParams = viewToChangeHeight.getLayoutParams();
|
|
layoutParams.height = Utils.displayMetrics.widthPixels + 1;
|
|
viewToChangeHeight.setLayoutParams(layoutParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getItemCount() {
|
|
return feedModels == null ? 0 : feedModels.size();
|
|
}
|
|
|
|
@Override
|
|
public int getItemViewType(final int position) {
|
|
if (feedModels != null) return feedModels.get(position).getItemType().ordinal();
|
|
return MediaItemType.MEDIA_TYPE_IMAGE.ordinal();
|
|
}
|
|
|
|
/**
|
|
* expands or collapses {@link RamboTextView} [stg idek why i wrote this documentation]
|
|
*
|
|
* @param textView the {@link RamboTextView} view, to expand and collapse
|
|
* @param feedModel the {@link FeedModel} model to check wether model is collapsed to expanded
|
|
*
|
|
* @return true if expanded/collapsed, false if empty or text size is <= 255 chars
|
|
*/
|
|
public static boolean expandCollapseTextView(@NonNull final RamboTextView textView, @NonNull final FeedModel feedModel) {
|
|
final CharSequence caption = feedModel.getPostCaption();
|
|
if (Utils.isEmpty(caption)) return false;
|
|
|
|
final TextView.BufferType bufferType = caption instanceof Spanned ? TextView.BufferType.SPANNABLE : TextView.BufferType.NORMAL;
|
|
|
|
if (!feedModel.isCaptionExpanded()) {
|
|
int i = Utils.indexOfChar(caption, '\r', 0);
|
|
if (i == -1) i = Utils.indexOfChar(caption, '\n', 0);
|
|
if (i == -1) i = 255;
|
|
|
|
final int captionLen = caption.length();
|
|
final int minTrim = Math.min(255, i);
|
|
if (captionLen <= minTrim) return false;
|
|
|
|
final CharSequence mentionText = caption.subSequence(0, Math.min(captionLen, minTrim));
|
|
final SpannableStringBuilder stringBuilder = new SpannableStringBuilder(mentionText).append(ellipsize);
|
|
final int spanLen = stringBuilder.length();
|
|
|
|
// fixed @mention...more merging into one span
|
|
final CommentMentionClickSpan[] spans = stringBuilder.getSpans(0, mentionText.length(), CommentMentionClickSpan.class);
|
|
if (spans != null) {
|
|
for (final CommentMentionClickSpan span : spans) {
|
|
final int spanStart = stringBuilder.getSpanStart(span);
|
|
stringBuilder.removeSpan(span);
|
|
stringBuilder.setSpan(span, spanStart, mentionText.length(), 0);
|
|
}
|
|
}
|
|
|
|
stringBuilder.setSpan(new StyleSpan(Typeface.BOLD), spanLen - ellipsize.length(), spanLen, 0);
|
|
|
|
textView.setText(stringBuilder, bufferType);
|
|
textView.setCaptionIsExpandable(true);
|
|
textView.setCaptionIsExpanded(true);
|
|
} else {
|
|
textView.setText(caption, bufferType);
|
|
textView.setCaptionIsExpanded(false);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private interface PlayerChangeListener {
|
|
void playerChanged(final int childPos, final SimpleExoPlayer player);
|
|
}
|
|
|
|
private static final class ChildMediaItemsAdapter extends PagerAdapter {
|
|
private final PlayerChangeListener playerChangeListener;
|
|
private final View.OnClickListener muteClickListener;
|
|
private final ViewerPostModel[] sliderItems;
|
|
private final View btnMute;
|
|
private SimpleExoPlayer player;
|
|
|
|
private ChildMediaItemsAdapter(final ViewerPostModel[] sliderItems, final View btnMute, final View.OnClickListener muteClickListener,
|
|
final PlayerChangeListener playerChangeListener) {
|
|
this.muteClickListener = muteClickListener;
|
|
this.sliderItems = sliderItems;
|
|
this.btnMute = btnMute;
|
|
if (BuildConfig.DEBUG) this.playerChangeListener = playerChangeListener;
|
|
else this.playerChangeListener = null;
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
|
|
if (BuildConfig.DEBUG) container.setBackgroundColor(0xFF_0a_c0_09); // todo remove
|
|
|
|
final Context context = container.getContext();
|
|
final ViewerPostModel sliderItem = sliderItems[position];
|
|
|
|
if (sliderItem.getItemType() == MediaItemType.MEDIA_TYPE_VIDEO) {
|
|
if (btnMute != null) btnMute.setVisibility(View.VISIBLE);
|
|
final PlayerView playerView = new PlayerView(context);
|
|
|
|
player = new SimpleExoPlayer.Builder(context).build();
|
|
playerView.setPlayer(player);
|
|
|
|
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(new DefaultDataSourceFactory(context, "instagram"))
|
|
.createMediaSource(Uri.parse(sliderItem.getDisplayUrl()));
|
|
|
|
player.setRepeatMode(Player.REPEAT_MODE_ALL);
|
|
player.prepare(mediaSource);
|
|
player.setVolume(vol);
|
|
|
|
playerView.setTag(player);
|
|
playerView.setOnClickListener(muteClickListener);
|
|
|
|
if (playerChangeListener != null) {
|
|
//todo
|
|
// playerChangeListener.playerChanged(position, player);
|
|
Log.d("AWAISKING_APP", "playerChangeListener: " + playerChangeListener);
|
|
}
|
|
|
|
container.addView(playerView);
|
|
return playerView;
|
|
} else {
|
|
if (btnMute != null) btnMute.setVisibility(View.GONE);
|
|
|
|
final PhotoView photoView = new PhotoView(context);
|
|
photoView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
Glide.with(context).load(sliderItem.getDisplayUrl()).into(photoView);
|
|
container.addView(photoView);
|
|
return photoView;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void destroyItem(@NonNull final ViewGroup container, final int position, @NonNull final Object object) {
|
|
final Player player = object instanceof PlayerView ? ((PlayerView) object).getPlayer() : this.player;
|
|
|
|
if (player == this.player && this.player != null) {
|
|
this.player.stop(true);
|
|
this.player.release();
|
|
} else if (player != null) {
|
|
player.stop(true);
|
|
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 == object;
|
|
}
|
|
}
|
|
} |