Support opening media, hashtag, location, mentions in direct thread

This commit is contained in:
Ammar Githam 2021-01-10 18:19:27 +09:00
parent 8937918064
commit ba10f8b410
29 changed files with 465 additions and 274 deletions

View File

@ -686,7 +686,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
R.array.com_google_android_gms_fonts_certs);
final EmojiCompat.Config config = new FontRequestEmojiCompatConfig(getApplicationContext(), fontRequest);
config.setReplaceAll(true)
.setUseEmojiAsDefaultStyle(true)
// .setUseEmojiAsDefaultStyle(true)
.registerInitCallback(new EmojiCompat.InitCallback() {
@Override
public void onInitialized() {

View File

@ -47,6 +47,7 @@ import awais.instagrabber.databinding.LayoutDmStoryShareBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
import awais.instagrabber.models.enums.DirectItemType;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
@ -57,6 +58,7 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
private final User currentUser;
private DirectThread thread;
private final DirectItemCallback callback;
private final AsyncListDiffer<DirectItemOrHeader> differ;
private List<DirectItem> items;
@ -99,9 +101,11 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
};
public DirectItemsAdapter(@NonNull final User currentUser,
@NonNull final DirectThread thread) {
@NonNull final DirectThread thread,
@NonNull final DirectItemCallback callback) {
this.currentUser = currentUser;
this.thread = thread;
this.callback = callback;
differ = new AsyncListDiffer<>(new AdapterListUpdateCallback(this),
new AsyncDifferConfig.Builder<>(diffCallback).build());
// this.onClickListener = onClickListener;
@ -128,66 +132,66 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
switch (directItemType) {
case TEXT: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemTextViewHolder(baseBinding, binding, currentUser, thread, null);
return new DirectItemTextViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case LIKE: {
final LayoutDmLikeBinding binding = LayoutDmLikeBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemLikeViewHolder(baseBinding, binding, currentUser, thread, null);
return new DirectItemLikeViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case LINK: {
final LayoutDmLinkBinding binding = LayoutDmLinkBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemLinkViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemLinkViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case ACTION_LOG: {
final LayoutDmActionLogBinding binding = LayoutDmActionLogBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemActionLogViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemActionLogViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case VIDEO_CALL_EVENT: {
final LayoutDmActionLogBinding binding = LayoutDmActionLogBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemVideoCallEventViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemVideoCallEventViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case PLACEHOLDER: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemPlaceholderViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemPlaceholderViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case ANIMATED_MEDIA: {
final LayoutDmAnimatedMediaBinding binding = LayoutDmAnimatedMediaBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemAnimatedMediaViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemAnimatedMediaViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case VOICE_MEDIA: {
final LayoutDmVoiceMediaBinding binding = LayoutDmVoiceMediaBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemVoiceMediaViewHolder(baseBinding, binding, currentUser, thread, null);
return new DirectItemVoiceMediaViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case LOCATION:
case PROFILE: {
final LayoutDmProfileBinding binding = LayoutDmProfileBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemProfileViewHolder(baseBinding, binding, currentUser, thread, null);
return new DirectItemProfileViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case MEDIA: {
final LayoutDmMediaBinding binding = LayoutDmMediaBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemMediaViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemMediaViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case CLIP:
case FELIX_SHARE:
case MEDIA_SHARE: {
final LayoutDmMediaShareBinding binding = LayoutDmMediaShareBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemMediaShareViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemMediaShareViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case STORY_SHARE: {
final LayoutDmStoryShareBinding binding = LayoutDmStoryShareBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemStoryShareViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemStoryShareViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case REEL_SHARE: {
final LayoutDmReelShareBinding binding = LayoutDmReelShareBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemReelShareViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemReelShareViewHolder(baseBinding, binding, currentUser, thread, callback);
}
case RAVEN_MEDIA: {
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemRavenMediaViewHolder(baseBinding, binding, currentUser, thread, null);
return new DirectItemRavenMediaViewHolder(baseBinding, binding, currentUser, thread, callback);
}
default: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, baseBinding.message, false);
return new DirectItemDefaultViewHolder(baseBinding, binding, currentUser, thread, null, null);
return new DirectItemDefaultViewHolder(baseBinding, binding, currentUser, thread, callback);
}
}
}
@ -352,4 +356,18 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
binding.header.setText(DateFormat.getDateFormat(itemView.getContext()).format(date));
}
}
public interface DirectItemCallback {
void onHashtagClick(String hashtag);
void onMentionClick(String mention);
void onLocationClick(long locationId);
void onURLClick(String url);
void onEmailClick(String email);
void onMediaClick(Media media);
}
}

View File

@ -3,6 +3,7 @@ package awais.instagrabber.adapters.viewholder.directmessages;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
@ -13,9 +14,9 @@ import androidx.annotation.NonNull;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmActionLogBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemActionLog;
@ -23,6 +24,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.TextUtils;
public class DirectItemActionLogViewHolder extends DirectItemViewHolder {
private static final String TAG = DirectItemActionLogViewHolder.class.getSimpleName();
private final LayoutDmActionLogBinding binding;
@ -30,11 +32,11 @@ public class DirectItemActionLogViewHolder extends DirectItemViewHolder {
final LayoutDmActionLogBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
binding.tvMessage.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
@ -60,7 +62,7 @@ public class DirectItemActionLogViewHolder extends DirectItemViewHolder {
final ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull final View widget) {
handleDeepLink(textAttribute.getIntent());
}
};
sb.setSpan(clickableSpan, textAttribute.getStart(), textAttribute.getEnd(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

View File

@ -8,9 +8,9 @@ import androidx.core.util.Pair;
import com.facebook.drawee.backends.pipeline.Fresco;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.repositories.responses.AnimatedMediaFixedHeight;
import awais.instagrabber.repositories.responses.AnimatedMediaImages;
import awais.instagrabber.repositories.responses.User;
@ -27,9 +27,8 @@ public class DirectItemAnimatedMediaViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmAnimatedMediaBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
}

View File

@ -1,14 +1,13 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
@ -21,11 +20,9 @@ public class DirectItemDefaultViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmTextBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
// setItemView(binding.getRoot());
}
@Override

View File

@ -1,9 +1,8 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmLikeBinding;
import awais.instagrabber.repositories.responses.User;
@ -16,8 +15,8 @@ public class DirectItemLikeViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmLikeBinding binding,
final User currentUser,
final DirectThread thread,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
setItemView(binding.getRoot());
}

View File

@ -5,9 +5,9 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmLinkBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemLink;
@ -23,9 +23,8 @@ public class DirectItemLinkViewHolder extends DirectItemViewHolder {
final LayoutDmLinkBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
final int width = windowWidth - margin - dmRadiusSmall;
final ViewGroup.LayoutParams layoutParams = binding.preview.getLayoutParams();
@ -35,8 +34,8 @@ public class DirectItemLinkViewHolder extends DirectItemViewHolder {
}
@Override
public void bindItem(final DirectItem directItemModel, final MessageDirection messageDirection) {
final DirectItemLink link = directItemModel.getLink();
public void bindItem(final DirectItem item, final MessageDirection messageDirection) {
final DirectItemLink link = item.getLink();
final DirectItemLinkContext linkContext = link.getLinkContext();
final String linkImageUrl = linkContext.getLinkImageUrl();
if (TextUtils.isEmpty(linkImageUrl)) {
@ -64,6 +63,16 @@ public class DirectItemLinkViewHolder extends DirectItemViewHolder {
binding.url.setText(linkContext.getLinkUrl());
}
binding.text.setText(link.getText());
setupListeners(linkContext);
}
private void setupListeners(final DirectItemLinkContext linkContext) {
setupRamboTextListeners(binding.text);
final View.OnClickListener onClickListener = v -> openURL(linkContext.getLinkUrl());
binding.preview.setOnClickListener(onClickListener);
binding.title.setOnClickListener(onClickListener);
binding.summary.setOnClickListener(onClickListener);
binding.url.setOnClickListener(onClickListener);
}
@Override

View File

@ -13,9 +13,9 @@ import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmMediaShareBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.enums.DirectItemType;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.Caption;
@ -38,9 +38,8 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmMediaShareBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
incomingRoundingParams = RoundingParams.fromCornersRadii(dmRadiusSmall, dmRadius, dmRadius, dmRadius);
outgoingRoundingParams = RoundingParams.fromCornersRadii(dmRadius, dmRadiusSmall, dmRadius, dmRadius);
@ -59,36 +58,36 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
: R.drawable.bg_media_share_top_outgoing);
Media media = getMedia(item);
if (media == null) return;
final User user = media.getUser();
if (user != null) {
binding.username.setVisibility(View.VISIBLE);
binding.profilePic.setVisibility(View.VISIBLE);
binding.username.setText(user.getUsername());
binding.profilePic.setImageURI(user.getProfilePicUrl());
itemView.post(() -> {
setupUser(media);
setupTitle(media);
setupCaption(media);
});
itemView.post(() -> {
final MediaItemType mediaType = media.getMediaType();
setupTypeIndicator(mediaType);
if (mediaType == MediaItemType.MEDIA_TYPE_SLIDER) {
setupPreview(media.getCarouselMedia().get(0));
return;
}
setupPreview(media);
});
itemView.setOnClickListener(v -> openMedia(media));
}
private void setupTypeIndicator(final MediaItemType mediaType) {
final boolean showTypeIcon = mediaType == MediaItemType.MEDIA_TYPE_VIDEO || mediaType == MediaItemType.MEDIA_TYPE_SLIDER;
if (!showTypeIcon) {
binding.typeIcon.setVisibility(View.GONE);
} else {
binding.username.setVisibility(View.GONE);
binding.profilePic.setVisibility(View.GONE);
}
final String title = media.getTitle();
if (!TextUtils.isEmpty(title)) {
binding.title.setVisibility(View.VISIBLE);
binding.title.setText(title);
} else {
binding.title.setVisibility(View.GONE);
}
final Caption caption = media.getCaption();
if (caption != null) {
binding.caption.setVisibility(View.VISIBLE);
binding.caption.setText(caption.getText());
binding.caption.setEllipsize(TextUtils.TruncateAt.END);
binding.caption.setMaxLines(2);
} else {
binding.caption.setVisibility(View.GONE);
}
final MediaItemType mediaType = media.getMediaType();
if (mediaType == MediaItemType.MEDIA_TYPE_SLIDER) {
media = media.getCarouselMedia().get(0);
binding.typeIcon.setVisibility(View.VISIBLE);
binding.typeIcon.setImageResource(mediaType == MediaItemType.MEDIA_TYPE_VIDEO
? R.drawable.ic_video_24
: R.drawable.ic_checkbox_multiple_blank_stroke);
}
}
private void setupPreview(@NonNull final Media media) {
final Pair<Integer, Integer> widthHeight = NumberUtils.calculateWidthHeight(
media.getOriginalHeight(),
media.getOriginalWidth(),
@ -101,15 +100,41 @@ public class DirectItemMediaShareViewHolder extends DirectItemViewHolder {
binding.mediaPreview.requestLayout();
final String url = ResponseBodyUtils.getThumbUrl(media.getImageVersions2());
binding.mediaPreview.setImageURI(url);
final boolean showTypeIcon = mediaType == MediaItemType.MEDIA_TYPE_VIDEO || mediaType == MediaItemType.MEDIA_TYPE_SLIDER;
if (!showTypeIcon) {
binding.typeIcon.setVisibility(View.GONE);
return;
}
private void setupCaption(@NonNull final Media media) {
final Caption caption = media.getCaption();
if (caption != null) {
binding.caption.setVisibility(View.VISIBLE);
binding.caption.setText(caption.getText());
binding.caption.setEllipsize(TextUtils.TruncateAt.END);
binding.caption.setMaxLines(2);
} else {
binding.caption.setVisibility(View.GONE);
}
}
private void setupTitle(@NonNull final Media media) {
final String title = media.getTitle();
if (!TextUtils.isEmpty(title)) {
binding.title.setVisibility(View.VISIBLE);
binding.title.setText(title);
} else {
binding.title.setVisibility(View.GONE);
}
}
private void setupUser(@NonNull final Media media) {
final User user = media.getUser();
if (user != null) {
binding.username.setVisibility(View.VISIBLE);
binding.profilePic.setVisibility(View.VISIBLE);
binding.username.setText(user.getUsername());
binding.profilePic.setImageURI(user.getProfilePicUrl());
} else {
binding.username.setVisibility(View.GONE);
binding.profilePic.setVisibility(View.GONE);
}
binding.typeIcon.setVisibility(View.VISIBLE);
binding.typeIcon.setImageResource(mediaType == MediaItemType.MEDIA_TYPE_VIDEO
? R.drawable.ic_video_24
: R.drawable.ic_checkbox_multiple_blank_stroke);
}
@Nullable

View File

@ -10,9 +10,9 @@ import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmMediaBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.ImageVersions2;
import awais.instagrabber.repositories.responses.Media;
@ -32,9 +32,8 @@ public class DirectItemMediaViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmMediaBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
incomingRoundingParams = RoundingParams.fromCornersRadii(dmRadiusSmall, dmRadius, dmRadius, dmRadius);
outgoingRoundingParams = RoundingParams.fromCornersRadii(dmRadius, dmRadiusSmall, dmRadius, dmRadius);
@ -49,6 +48,7 @@ public class DirectItemMediaViewHolder extends DirectItemViewHolder {
.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
.build());
final Media media = directItemModel.getMedia();
itemView.setOnClickListener(v -> openMedia(media));
final MediaItemType modelMediaType = media.getMediaType();
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO || modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER
? View.VISIBLE
@ -71,4 +71,5 @@ public class DirectItemMediaViewHolder extends DirectItemViewHolder {
final String thumbUrl = ResponseBodyUtils.getThumbUrl(imageVersions2);
binding.mediaPreview.setImageURI(thumbUrl);
}
}

View File

@ -1,12 +1,10 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
@ -19,9 +17,8 @@ public class DirectItemPlaceholderViewHolder extends DirectItemViewHolder {
final LayoutDmTextBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
}

View File

@ -13,6 +13,7 @@ import com.google.common.collect.ImmutableList;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmProfileBinding;
import awais.instagrabber.models.enums.DirectItemType;
@ -34,8 +35,8 @@ public class DirectItemProfileViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmProfileBinding binding,
final User currentUser,
final DirectThread thread,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
previewViews = ImmutableList.of(
@ -98,6 +99,7 @@ public class DirectItemProfileViewHolder extends DirectItemViewHolder {
binding.username.setText(profile.getUsername());
binding.fullName.setText(profile.getFullName());
binding.isVerified.setVisibility(profile.isVerified() ? View.VISIBLE : View.GONE);
itemView.setOnClickListener(v -> openProfile(profile.getUsername()));
}
private void setLocation(@NonNull final DirectItem item) {
@ -113,5 +115,6 @@ public class DirectItemProfileViewHolder extends DirectItemViewHolder {
binding.fullName.setVisibility(View.GONE);
}
binding.isVerified.setVisibility(View.GONE);
itemView.setOnClickListener(v -> openLocation(location.getPk()));
}
}

View File

@ -10,6 +10,7 @@ import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmRavenMediaBinding;
import awais.instagrabber.models.enums.MediaItemType;
@ -32,8 +33,8 @@ public class DirectItemRavenMediaViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmRavenMediaBinding binding,
final User currentUser,
final DirectThread thread,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
maxWidth = windowWidth - margin - dmRadiusSmall;
setItemView(binding.getRoot());
@ -46,6 +47,9 @@ public class DirectItemRavenMediaViewHolder extends DirectItemViewHolder {
if (media == null) return;
setExpiryInfo(visualMedia);
setPreview(visualMedia, messageDirection);
final boolean expired = media.getPk() == null;
if (expired) return;
itemView.setOnClickListener(v -> openMedia(media));
/*final boolean isExpired = visualMedia == null || (mediaModel = visualMedia.getMedia()) == null ||
TextUtils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;

View File

@ -10,9 +10,9 @@ import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmReelShareBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.ImageVersions2;
import awais.instagrabber.repositories.responses.Media;
@ -31,9 +31,8 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmReelShareBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
}
@ -72,6 +71,7 @@ public class DirectItemReelShareViewHolder extends DirectItemViewHolder {
}
if (!expired) {
setPreview(media);
itemView.setOnClickListener(v -> openMedia(media));
}
}

View File

@ -10,9 +10,9 @@ import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.RoundingParams;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmStoryShareBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.responses.ImageVersions2;
import awais.instagrabber.repositories.responses.Media;
@ -27,17 +27,14 @@ import awais.instagrabber.utils.TextUtils;
public class DirectItemStoryShareViewHolder extends DirectItemViewHolder {
private final LayoutDmStoryShareBinding binding;
// private final int maxWidth;
public DirectItemStoryShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmStoryShareBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
// maxWidth = windowWidth - margin - dmRadiusSmall;
setItemView(binding.getRoot());
}
@ -58,13 +55,13 @@ public class DirectItemStoryShareViewHolder extends DirectItemViewHolder {
binding.ivMediaPreview.setController(null);
final DirectItemStoryShare storyShare = item.getStoryShare();
if (storyShare == null) return;
final String text = storyShare.getText();
if (!TextUtils.isEmpty(text)) {
binding.text.setText(text);
binding.text.setVisibility(View.VISIBLE);
return;
}
final Media storyShareMedia = storyShare.getMedia();
setText(storyShare);
final Media media = storyShare.getMedia();
setupPreview(messageDirection, media);
itemView.setOnClickListener(v -> openMedia(media));
}
private void setupPreview(final MessageDirection messageDirection, final Media storyShareMedia) {
final MediaItemType mediaType = storyShareMedia.getMediaType();
binding.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ? View.VISIBLE : View.GONE);
final RoundingParams roundingParams = messageDirection == MessageDirection.INCOMING
@ -90,6 +87,16 @@ public class DirectItemStoryShareViewHolder extends DirectItemViewHolder {
binding.ivMediaPreview.setImageURI(thumbUrl);
}
private void setText(final DirectItemStoryShare storyShare) {
final String text = storyShare.getText();
if (!TextUtils.isEmpty(text)) {
binding.text.setText(text);
binding.text.setVisibility(View.VISIBLE);
return;
}
binding.text.setVisibility(View.GONE);
}
private void setExpiredStoryInfo(final DirectItem item) {
binding.shareInfo.setText(item.getStoryShare().getTitle());
binding.text.setVisibility(View.VISIBLE);

View File

@ -1,9 +1,8 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.repositories.responses.User;
@ -18,8 +17,8 @@ public class DirectItemTextViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmTextBinding binding,
final User currentUser,
final DirectThread thread,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
@NonNull final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
}
@ -29,29 +28,11 @@ public class DirectItemTextViewHolder extends DirectItemViewHolder {
final String text = directItemModel.getText();
if (text == null) return;
binding.tvMessage.setText(text);
// setupListeners();
setupRamboTextListeners(binding.tvMessage);
}
@Override
protected boolean showBackground() {
return true;
}
// private void setupListeners() {
// binding.tvMessage.addOnHashtagListener(autoLinkItem -> {
// final String hashtag = autoLinkItem.getOriginalText().trim();
// });
// binding.tvMessage.addOnMentionClickListener(autoLinkItem -> {
// final String mention = autoLinkItem.getOriginalText().trim();
// });
// binding.tvMessage.addOnEmailClickListener(autoLinkItem -> {
// final String email = autoLinkItem.getOriginalText().trim();
// });
// binding.tvMessage.addOnURLClickListener(autoLinkItem -> {
// final String url = autoLinkItem.getOriginalText().trim();
// });
// binding.tvMessage.setOnLongClickListener(v -> {
// return true;
// });
// }
}

View File

@ -11,9 +11,9 @@ import androidx.annotation.NonNull;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmActionLogBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemActionLog;
@ -29,9 +29,8 @@ public class DirectItemVideoCallEventViewHolder extends DirectItemViewHolder {
final LayoutDmActionLogBinding binding,
final User currentUser,
final DirectThread thread,
final MentionClickListener mentionClickListener,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
setItemView(binding.getRoot());
}

View File

@ -19,6 +19,8 @@ import java.util.Locale;
import java.util.stream.Collectors;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.customviews.RamboTextViewV2;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.models.enums.DirectItemType;
import awais.instagrabber.models.enums.MediaItemType;
@ -28,6 +30,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemEmojiReaction;
import awais.instagrabber.repositories.responses.directmessages.DirectItemReactions;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
import awais.instagrabber.utils.DeepLinkParser;
import awais.instagrabber.utils.ResponseBodyUtils;
public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
@ -36,12 +39,14 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
private final LayoutDmBaseBinding binding;
private final User currentUser;
private final DirectThread thread;
private final int groupMessageWidth;
private final List<Long> userIds;
private final DirectItemCallback callback;
protected final int margin;
protected final int dmRadius;
protected final int dmRadiusSmall;
protected final int messageInfoPaddingSmall;
private final int groupMessageWidth;
private final List<Long> userIds;
protected final int mediaImageMaxHeight;
protected final int windowWidth;
protected final int mediaImageMaxWidth;
@ -49,18 +54,18 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
public DirectItemViewHolder(@NonNull final LayoutDmBaseBinding binding,
@NonNull final User currentUser,
@NonNull final DirectThread thread,
@NonNull final View.OnClickListener onClickListener) {
@NonNull final DirectItemCallback callback) {
super(binding.getRoot());
this.binding = binding;
this.currentUser = currentUser;
this.thread = thread;
this.callback = callback;
userIds = thread.getUsers()
.stream()
.map(User::getPk)
.collect(Collectors.toList());
binding.ivProfilePic.setVisibility(thread.isGroup() ? View.VISIBLE : View.GONE);
binding.ivProfilePic.setOnClickListener(thread.isGroup() ? onClickListener : null);
// binding.messageCard.setOnClickListener(onClickListener);
binding.ivProfilePic.setOnClickListener(null);
final Resources resources = itemView.getResources();
margin = resources.getDimensionPixelSize(R.dimen.dm_message_item_margin);
final int avatarSize = resources.getDimensionPixelSize(R.dimen.dm_message_item_avatar_size);
@ -366,6 +371,40 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
public void cleanup() {}
protected void setupRamboTextListeners(@NonNull final RamboTextViewV2 textView) {
textView.addOnHashtagListener(autoLinkItem -> callback.onHashtagClick(autoLinkItem.getOriginalText().trim()));
textView.addOnMentionClickListener(autoLinkItem -> openProfile(autoLinkItem.getOriginalText().trim()));
textView.addOnEmailClickListener(autoLinkItem -> callback.onEmailClick(autoLinkItem.getOriginalText().trim()));
textView.addOnURLClickListener(autoLinkItem -> openURL(autoLinkItem.getOriginalText().trim()));
}
protected void openProfile(final String username) {
callback.onMentionClick(username);
}
protected void openLocation(final long locationId) {
callback.onLocationClick(locationId);
}
protected void openURL(final String url) {
callback.onURLClick(url);
}
protected void openMedia(final Media media) {
callback.onMediaClick(media);
}
protected void handleDeepLink(final String deepLinkText) {
if (deepLinkText == null) return;
final DeepLinkParser.DeepLink deepLink = DeepLinkParser.parse(deepLinkText);
if (deepLink == null) return;
switch (deepLink.getType()) {
case USER:
callback.onMentionClick(deepLink.getValue());
break;
}
}
public enum MessageDirection {
INCOMING,
OUTGOING

View File

@ -17,6 +17,7 @@ import com.google.common.primitives.Floats;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
import awais.instagrabber.repositories.responses.Audio;
@ -43,8 +44,8 @@ public class DirectItemVoiceMediaViewHolder extends DirectItemViewHolder {
@NonNull final LayoutDmVoiceMediaBinding binding,
final User currentUser,
final DirectThread thread,
final View.OnClickListener onClickListener) {
super(baseBinding, currentUser, thread, onClickListener);
final DirectItemCallback callback) {
super(baseBinding, currentUser, thread, callback);
this.binding = binding;
this.dataSourceFactory = new DefaultDataSourceFactory(binding.getRoot().getContext(), "instagram");
setItemView(binding.getRoot());

View File

@ -93,7 +93,7 @@ public class ChatMessageLayout extends FrameLayout {
widthSize += viewPartMainWidth;
heightSize += viewPartMainHeight;
} else if (firstChildId == R.id.raven_media_container || firstChildId == R.id.profile_container || firstChildId == R.id.voice_media
|| firstChildId == R.id.story_container || firstChildId == R.id.media_share_container) {
|| firstChildId == R.id.story_container || firstChildId == R.id.media_share_container || firstChildId == R.id.link_container) {
widthSize += viewPartMainWidth;
heightSize += viewPartMainHeight + viewPartInfoHeight;
} else {

View File

@ -442,12 +442,16 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
setProfilePicSharedElement();
setupCaptionBottomSheet();
setupCommonActions();
setupShare();
setObservers();
}
private void setObservers() {
viewModel.getUser().observe(getViewLifecycleOwner(), user -> {
if (user == null) {
binding.userDetailsGroup.setVisibility(View.GONE);
return;
}
binding.userDetailsGroup.setVisibility(View.VISIBLE);
binding.getRoot().post(() -> setupProfilePic(user));
binding.getRoot().post(() -> setupTitles(user));
});
@ -461,15 +465,27 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
binding.date.setVisibility(View.VISIBLE);
binding.date.setText(date);
}));
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
if (viewModel.getMedia().isCommentLikesEnabled()) {
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
final long safeCount = getSafeCount(count);
final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount);
binding.likesCount.setText(likesString);
});
viewModel.getCommentCount().observe(getViewLifecycleOwner(), count -> {
final long safeCount = getSafeCount(count);
final String likesString = getResources().getQuantityString(R.plurals.comments_count, (int) safeCount, safeCount);
binding.likesCount.setText(likesString);
});
}
viewModel.getViewCount().observe(getViewLifecycleOwner(), count -> {
if (count == null) {
binding.viewsCount.setVisibility(View.GONE);
return;
}
binding.viewsCount.setVisibility(View.VISIBLE);
final long safeCount = getSafeCount(count);
final String likesString = getResources().getQuantityString(R.plurals.likes_count, (int) safeCount, safeCount);
binding.likesCount.setText(likesString);
});
viewModel.getCommentCount().observe(getViewLifecycleOwner(), count -> {
final long safeCount = getSafeCount(count);
final String likesString = getResources().getQuantityString(R.plurals.comments_count, (int) safeCount, safeCount);
binding.likesCount.setText(likesString);
final String viewString = getResources().getQuantityString(R.plurals.views_count, (int) safeCount, safeCount);
binding.viewsCount.setText(viewString);
});
viewModel.getType().observe(getViewLifecycleOwner(), this::setupPostTypeLayout);
viewModel.getLiked().observe(getViewLifecycleOwner(), this::setLikedResources);
@ -518,9 +534,16 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
setupSave();
setupDownload();
setupComment();
setupShare();
}
private void setupComment() {
if (!viewModel.hasPk() || !viewModel.getMedia().isCommentLikesEnabled()) {
binding.comment.setVisibility(View.GONE);
binding.commentsCount.setVisibility(View.GONE);
return;
}
binding.comment.setVisibility(View.VISIBLE);
binding.comment.setOnClickListener(v -> {
final Media media = viewModel.getMedia();
final User user = media.getUser();
@ -554,6 +577,12 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
}
private void setupLike() {
final boolean likableMedia = viewModel.hasPk() && viewModel.getMedia().isCommentLikesEnabled();
if (!likableMedia) {
binding.like.setVisibility(View.GONE);
binding.likesCount.setVisibility(View.GONE);
return;
}
if (!viewModel.isLoggedIn()) {
binding.like.setVisibility(View.GONE);
return;
@ -626,7 +655,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
}
private void setupSave() {
if (!viewModel.isLoggedIn()) {
if (!viewModel.isLoggedIn() || !viewModel.hasPk() || !viewModel.getMedia().canViewerSave()) {
binding.save.setVisibility(View.GONE);
return;
}
@ -854,6 +883,11 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
}
private void setupShare() {
if (!viewModel.hasPk()) {
binding.share.setVisibility(View.GONE);
return;
}
binding.share.setVisibility(View.VISIBLE);
binding.share.setOnLongClickListener(v -> {
Utils.displayToastAboveView(context, v, getString(R.string.share));
return true;
@ -1017,7 +1051,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
sliderPosition = position;
final String text = (position + 1) + "/" + size;
binding.mediaCounter.setText(text);
final Media postChild = media.getCarouselMedia().get(position);
final Media childMedia = media.getCarouselMedia().get(position);
final View view = binding.sliderParent.getChildAt(0);
if (prevPosition != -1) {
if (view instanceof RecyclerView) {
@ -1027,7 +1061,7 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
}
}
}
if (postChild.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO) {
if (childMedia.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO) {
if (view instanceof RecyclerView) {
final RecyclerView.ViewHolder viewHolder = ((RecyclerView) view).findViewHolderForAdapterPosition(position);
if (viewHolder instanceof SliderVideoViewHolder) {
@ -1035,8 +1069,10 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
}
}
enablePlayerControls(true);
viewModel.setViewCount(childMedia.getViewCount());
return;
}
viewModel.setViewCount(null);
enablePlayerControls(false);
}
@ -1325,10 +1361,12 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
TransitionManager.beginDelayedTransition(binding.getRoot());
if (detailsVisible) {
detailsVisible = false;
binding.profilePic.setVisibility(View.GONE);
binding.title.setVisibility(View.GONE);
binding.subtitle.setVisibility(View.GONE);
binding.topBg.setVisibility(View.GONE);
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);
}
@ -1355,10 +1393,12 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment im
}
return;
}
binding.profilePic.setVisibility(View.VISIBLE);
binding.title.setVisibility(View.VISIBLE);
binding.subtitle.setVisibility(View.VISIBLE);
binding.topBg.setVisibility(View.VISIBLE);
if (media.getUser() != null) {
binding.profilePic.setVisibility(View.VISIBLE);
binding.title.setVisibility(View.VISIBLE);
binding.subtitle.setVisibility(View.VISIBLE);
binding.topBg.setVisibility(View.VISIBLE);
}
if (media.getLocation() != null) {
binding.location.setVisibility(View.VISIBLE);
}

View File

@ -68,7 +68,9 @@ import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge;
import awais.instagrabber.customviews.helpers.TextWatcherAdapter;
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
import awais.instagrabber.dialogs.MediaPickerBottomDialogFragment;
import awais.instagrabber.fragments.PostViewV2Fragment;
import awais.instagrabber.models.Resource;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
@ -96,11 +98,9 @@ public class DirectMessageThreadFragment extends Fragment {
private DirectItemsAdapter itemsAdapter;
private MainActivity fragmentActivity;
private DirectThreadViewModel viewModel;
public static boolean hasSentSomething;
private ConstraintLayout root;
private boolean shouldRefresh = true;
private List<DirectItemOrHeader> itemOrHeaders;
private MenuItem markAsSeenMenuItem;
private FragmentDirectMessagesThreadBinding binding;
private Tooltip tooltip;
private float initialSendX;
@ -116,75 +116,6 @@ public class DirectMessageThreadFragment extends Fragment {
private boolean wasKbShowing;
private int keyboardHeight = Utils.convertDpToPx(250);
// private final View.OnClickListener clickListener = v -> {
// if (v == binding.commentSend) {
// final String text = binding.commentText.getText().toString();
// if (TextUtils.isEmpty(text)) {
// final Context context = getContext();
// if (context == null) return;
// Toast.makeText(context, R.string.comment_send_empty_comment, Toast.LENGTH_SHORT).show();
// return;
// }
// sendText(text, null, false);
// return;
// }
// if (v == binding.image) {
// final Intent intent = new Intent();
// intent.setType("image/*");
// intent.setAction(Intent.ACTION_GET_CONTENT);
// startActivityForResult(Intent.createChooser(intent, getString(R.string.select_picture)), PICK_IMAGE);
// }
// };
// private final FetchListener<InboxThreadModel> fetchListener = new FetchListener<InboxThreadModel>() {
// @Override
// public void doBefore() {
// setTitle(true);g
// }
//
// @Override
// public void onResult(final InboxThreadModel result) {
// if (result == null && ("MINCURSOR".equals(cursor) || "MAXCURSOR".equals(cursor) || TextUtils.isEmpty(cursor))) {
// final Context context = getContext();
// if (context == null) return;
// Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
// }
//
// if (result != null) {
// cursor = result.getOldestCursor();
// hasOlder = result.hasOlder();
// if ("MINCURSOR".equals(cursor) || "MAXCURSOR".equals(cursor)) {
// cursor = null;
// }
// users.clear();
// users.addAll(result.getUsers());
// leftUsers.clear();
// leftUsers.addAll(result.getLeftUsers());
//
// List<DirectItemModel> list = listViewModel.getList().getValue();
// final List<DirectItemModel> newList = result.getItems();
// list = list != null ? new LinkedList<>(list) : new LinkedList<>();
// if (hasSentSomething || hasDeletedSomething) {
// list = newList;
// final Handler handler = new Handler();
// if (hasSentSomething) handler.postDelayed(() -> {
// binding.messageList.smoothScrollToPosition(0);
// }, 200);
// hasSentSomething = false;
// hasDeletedSomething = false;
// } else {
// list.addAll(newList);
// }
// listViewModel.getList().postValue(list);
// lastMessage = result.getNewestCursor();
//
// // if (Utils.settingsHelper.getBoolean(Constants.DM_MARK_AS_SEEN)) new ThreadAction().execute("seen", lastMessage);
// }
// setTitle(false);
// }
// };
// private DirectItemMediaModel downloadMediaItem;
// private int prevSizeChangeHeight;
// private ArrayAdapter<String> dialogAdapter;
private final AppExecutors appExecutors = AppExecutors.getInstance();
private final Animatable2Compat.AnimationCallback micToSendAnimationCallback = new Animatable2Compat.AnimationCallback() {
@Override
@ -200,7 +131,46 @@ public class DirectMessageThreadFragment extends Fragment {
setMicToSendIcon();
}
};
private final DirectItemsAdapter.DirectItemCallback directItemCallback = new DirectItemsAdapter.DirectItemCallback() {
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = DirectMessageThreadFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
}
@Override
public void onMentionClick(final String mention) {
final Bundle bundle = new Bundle();
bundle.putString("username", "@" + mention);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(R.id.action_global_profileFragment, bundle);
}
@Override
public void onLocationClick(final long locationId) {
final NavDirections action = DirectMessageThreadFragmentDirections.actionGlobalLocationFragment(locationId);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
}
@Override
public void onURLClick(final String url) {
final Context context = getContext();
if (context == null) return;
Utils.openURL(context, url);
}
@Override
public void onEmailClick(final String email) {
final Context context = getContext();
if (context == null) return;
Utils.openEmailAddress(context, email);
}
@Override
public void onMediaClick(final Media media) {
final PostViewV2Fragment.Builder builder = PostViewV2Fragment.builder(media);
builder.build().show(getChildFragmentManager(), "post_view");
}
};
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
@ -243,7 +213,7 @@ public class DirectMessageThreadFragment extends Fragment {
@Override
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
inflater.inflate(R.menu.dm_thread_menu, menu);
markAsSeenMenuItem = menu.findItem(R.id.mark_as_seen);
final MenuItem markAsSeenMenuItem = menu.findItem(R.id.mark_as_seen);
if (markAsSeenMenuItem != null) {
markAsSeenMenuItem.setVisible(false);
}
@ -253,7 +223,8 @@ public class DirectMessageThreadFragment extends Fragment {
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
final int itemId = item.getItemId();
if (itemId == R.id.info) {
final NavDirections action = DirectMessageThreadFragmentDirections.actionDMThreadFragmentToDMSettingsFragment(viewModel.getThreadId(), null);
final NavDirections action = DirectMessageThreadFragmentDirections
.actionDMThreadFragmentToDMSettingsFragment(viewModel.getThreadId(), null);
NavHostFragment.findNavController(this).navigate(action);
return true;
}
@ -379,7 +350,6 @@ public class DirectMessageThreadFragment extends Fragment {
.findFirst()
: Optional.empty();
if (first.isPresent()) {
// setTitle(UPDATING_TITLE);
final DirectThread thread = first.get();
viewModel.setThread(thread);
return;
@ -590,7 +560,7 @@ public class DirectMessageThreadFragment extends Fragment {
itemsAdapter.setThread(thread);
return;
}
itemsAdapter = new DirectItemsAdapter(currentUser, thread);
itemsAdapter = new DirectItemsAdapter(currentUser, thread, directItemCallback);
itemsAdapter.setHasStableIds(true);
itemsAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
binding.chats.setAdapter(itemsAdapter);

View File

@ -169,8 +169,7 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
final View profilePicView,
final View mainPostImage,
final int position) {
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(feedModel);
final PostViewV2Fragment.Builder builder = PostViewV2Fragment.builder(feedModel);
if (position >= 0) {
builder.setPosition(position);
}

View File

@ -1,5 +1,7 @@
package awais.instagrabber.repositories.responses;
import androidx.annotation.Nullable;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@ -123,6 +125,7 @@ public class Media implements Serializable {
return takenAt;
}
@Nullable
public User getUser() {
return user;
}
@ -231,7 +234,11 @@ public class Media implements Serializable {
return injected != null;
}
@Nullable
public String getDate() {
if (takenAt <= 0) {
return null;
}
if (dateString == null) {
dateString = Utils.datetimeParser.format(new Date(takenAt * 1000L));
}

View File

@ -0,0 +1,67 @@
package awais.instagrabber.utils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.regex.Pattern;
public final class DeepLinkParser {
private static final Map<DeepLink.Type, DeepLinkPattern> TYPE_PATTERN_MAP = ImmutableMap
.<DeepLink.Type, DeepLinkPattern>builder()
.put(DeepLink.Type.USER, new DeepLinkPattern("instagram://user?username="))
.build();
@Nullable
public static DeepLink parse(@NonNull final String text) {
for (final Map.Entry<DeepLink.Type, DeepLinkPattern> entry : TYPE_PATTERN_MAP.entrySet()) {
if (text.startsWith(entry.getValue().getPatternText())) {
final String value = entry.getValue().getPattern().matcher(text).replaceAll("");
return new DeepLink(entry.getKey(), value);
}
}
return null;
}
public static class DeepLinkPattern {
private final String patternText;
private final Pattern pattern;
public DeepLinkPattern(final String patternText) {
this.patternText = patternText;
pattern = Pattern.compile(patternText, Pattern.LITERAL);
}
public String getPatternText() {
return patternText;
}
public Pattern getPattern() {
return pattern;
}
}
public static class DeepLink {
private final Type type;
private final String value;
public DeepLink(final Type type, final String value) {
this.type = type;
this.value = value;
}
public Type getType() {
return type;
}
public String getValue() {
return value;
}
public enum Type {
USER,
}
}
}

View File

@ -36,6 +36,7 @@ public class PostViewV2ViewModel extends ViewModel {
private final MutableLiveData<String> date = new MutableLiveData<>();
private final MutableLiveData<Long> likeCount = new MutableLiveData<>(0L);
private final MutableLiveData<Long> commentCount = new MutableLiveData<>(0L);
private final MutableLiveData<Long> viewCount = new MutableLiveData<>(0L);
private final MutableLiveData<MediaItemType> type = new MutableLiveData<>();
private final MutableLiveData<Boolean> liked = new MutableLiveData<>(false);
private final MutableLiveData<Boolean> saved = new MutableLiveData<>(false);
@ -63,6 +64,7 @@ public class PostViewV2ViewModel extends ViewModel {
date.postValue(media.getDate());
likeCount.postValue(media.getLikeCount());
commentCount.postValue(media.getCommentCount());
viewCount.postValue(media.getMediaType() == MediaItemType.MEDIA_TYPE_VIDEO ? media.getViewCount() : null);
type.postValue(media.getMediaType());
liked.postValue(media.hasLiked());
saved.postValue(media.hasViewerSaved());
@ -71,7 +73,7 @@ public class PostViewV2ViewModel extends ViewModel {
private void initOptions() {
final ImmutableList.Builder<Integer> builder = ImmutableList.builder();
if (isLoggedIn && media.getUser().getPk() == viewerId) {
if (isLoggedIn && media.getUser() != null && media.getUser().getPk() == viewerId) {
builder.add(R.id.edit_caption);
}
options.postValue(builder.build());
@ -109,6 +111,10 @@ public class PostViewV2ViewModel extends ViewModel {
return commentCount;
}
public LiveData<Long> getViewCount() {
return viewCount;
}
public LiveData<MediaItemType> getType() {
return type;
}
@ -270,4 +276,12 @@ public class PostViewV2ViewModel extends ViewModel {
});
return data;
}
public boolean hasPk() {
return media.getPk() != null;
}
public void setViewCount(final Long viewCount) {
this.viewCount.postValue(viewCount);
}
}

View File

@ -73,18 +73,6 @@
app:layout_constraintTop_toTopOf="@id/profile_pic"
tools:text="Username Username Username" />
<!--<androidx.appcompat.widget.AppCompatImageView-->
<!-- android:id="@+id/isVerified"-->
<!-- android:layout_width="20dp"-->
<!-- android:layout_height="0dp"-->
<!-- android:scaleType="fitCenter"-->
<!-- android:visibility="gone"-->
<!-- app:layout_constraintBottom_toBottomOf="@id/title"-->
<!-- app:layout_constraintStart_toEndOf="@id/title"-->
<!-- app:layout_constraintTop_toTopOf="@id/title"-->
<!-- app:srcCompat="@drawable/verified"-->
<!-- tools:visibility="visible" />-->
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/subtitle"
android:layout_width="0dp"
@ -110,6 +98,14 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/top_bg"
app:srcCompat="@drawable/ic_more_vert_24"
app:tint="@color/white"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Group
android:id="@+id/user_details_group"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="top_bg, profile_pic,title,subtitle,options"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
@ -278,10 +274,11 @@
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bottom_bg_barrier"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="top"
app:constraint_referenced_ids="bottom_bg,likes_count,comments_count" />
app:constraint_referenced_ids="likes_count,comments_count,views_count" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/likes_count"
@ -289,13 +286,13 @@
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toTopOf="@id/date"
app:layout_constraintBottom_toTopOf="@id/counts_barrier"
app:layout_constraintEnd_toStartOf="@id/comments_count"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/bottom_bg_barrier"
app:layout_constraintTop_toBottomOf="@id/bottom_bg_barrier"
tools:text="9999999999 likes"
tools:visibility="visible" />
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/comments_count"
@ -303,13 +300,13 @@
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toTopOf="@id/date"
app:layout_constraintBottom_toTopOf="@id/counts_barrier"
app:layout_constraintEnd_toStartOf="@id/views_count"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/likes_count"
app:layout_constraintTop_toTopOf="@id/bottom_bg_barrier"
app:layout_constraintTop_toBottomOf="@id/bottom_bg_barrier"
tools:text="9999999 comments"
tools:visibility="visible" />
tools:visibility="gone" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/views_count"
@ -317,12 +314,20 @@
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toTopOf="@id/date"
app:layout_constraintBottom_toTopOf="@id/counts_barrier"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/comments_count"
app:layout_constraintTop_toTopOf="@id/bottom_bg_barrier"
app:layout_constraintTop_toBottomOf="@id/bottom_bg_barrier"
tools:text="9999999999 views"
tools:visibility="visible" />
tools:visibility="gone" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/counts_barrier"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="top"
app:constraint_referenced_ids="date" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/date"
@ -331,15 +336,17 @@
android:padding="8dp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@id/buttons_barrier"
app:layout_constraintTop_toBottomOf="@id/likes_count"
tools:text="2020-11-07 11:18:55" />
app:layout_constraintTop_toBottomOf="@id/counts_barrier"
tools:text="2020-11-07 11:18:55"
tools:visibility="visible" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/buttons_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="bottom"
app:constraint_referenced_ids="likes_count,comments_count,views_count" />
app:constraint_referenced_ids="date" />
<com.google.android.material.button.MaterialButton
android:id="@+id/caption_toggle"

View File

@ -57,7 +57,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:background="@android:color/transparent"
android:hint="Message"
android:hint="@string/message"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:textColor="@color/white"

View File

@ -143,7 +143,8 @@
<argument
android:name="title"
app:argType="string" />
app:argType="string"
app:nullable="true" />
<action
android:id="@+id/action_settings_to_inbox"

View File

@ -373,6 +373,10 @@
<item quantity="one">%d comment</item>
<item quantity="other">%d comments</item>
</plurals>
<plurals name="views_count">
<item quantity="one">%d view</item>
<item quantity="other">%d views</item>
</plurals>
<plurals name="stories_count">
<item quantity="one">%s story</item>
<item quantity="other">%s stories</item>
@ -391,4 +395,5 @@
<string name="dms_action_make_admin">Make Admin</string>
<string name="dms_action_remove_admin">Remove as Admin</string>
<string name="edit_unsuccessful">Edit was unsuccessful</string>
<string name="message">Message</string>
</resources>