Separate out individual DM message types to their respective views

This commit is contained in:
Ammar Githam 2020-08-20 22:05:23 +09:00
parent 376f3e5d5a
commit 51138f9db0
33 changed files with 1326 additions and 816 deletions

2
.gitignore vendored
View File

@ -15,3 +15,5 @@
.externalNativeBuild .externalNativeBuild
.cxx .cxx
app/release app/release
.idea/git_toolbox_prj.xml

View File

@ -0,0 +1,146 @@
package awais.instagrabber.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import java.util.List;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageActionLogViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageAnimatedMediaViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageItemViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageLinkViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageMediaShareViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageMediaViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessagePlaceholderViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageProfileViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageRavenMediaViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageReelShareViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageStoryShareViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageTextViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageVideoCallEventViewHolder;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageVoiceMediaViewHolder;
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmLinkBinding;
import awais.instagrabber.databinding.LayoutDmMediaBinding;
import awais.instagrabber.databinding.LayoutDmMediaShareBinding;
import awais.instagrabber.databinding.LayoutDmProfileBinding;
import awais.instagrabber.databinding.LayoutDmRavenMediaBinding;
import awais.instagrabber.databinding.LayoutDmStoryShareBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.enums.DirectItemType;
public final class DirectMessageItemsAdapter extends ListAdapter<DirectItemModel, DirectMessageItemViewHolder> {
private final List<ProfileModel> users;
private final List<ProfileModel> leftUsers;
private final View.OnClickListener onClickListener;
private final MentionClickListener mentionClickListener;
private static final DiffUtil.ItemCallback<DirectItemModel> diffCallback = new DiffUtil.ItemCallback<DirectItemModel>() {
@Override
public boolean areItemsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
return oldItem.getItemId().equals(newItem.getItemId());
}
@Override
public boolean areContentsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
return oldItem.getItemId().equals(newItem.getItemId());
}
};
public DirectMessageItemsAdapter(final List<ProfileModel> users,
final List<ProfileModel> leftUsers,
final View.OnClickListener onClickListener,
final MentionClickListener mentionClickListener) {
super(diffCallback);
this.users = users;
this.leftUsers = leftUsers;
this.onClickListener = onClickListener;
this.mentionClickListener = mentionClickListener;
}
@NonNull
@Override
public DirectMessageItemViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
final DirectItemType directItemType = DirectItemType.valueOf(type);
final LayoutDmBaseBinding baseBinding = LayoutDmBaseBinding.inflate(layoutInflater, parent, false);
final ViewGroup itemViewParent = baseBinding.messageCard;
switch (directItemType) {
default:
case LIKE:
case TEXT: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageTextViewHolder(baseBinding, binding, onClickListener, mentionClickListener);
}
case PLACEHOLDER: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessagePlaceholderViewHolder(baseBinding, binding, onClickListener);
}
case ACTION_LOG: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageActionLogViewHolder(baseBinding, binding, onClickListener);
}
case LINK: {
final LayoutDmLinkBinding binding = LayoutDmLinkBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageLinkViewHolder(baseBinding, binding, onClickListener);
}
case MEDIA: {
final LayoutDmMediaBinding binding = LayoutDmMediaBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageMediaViewHolder(baseBinding, binding, onClickListener);
}
case PROFILE: {
final LayoutDmProfileBinding binding = LayoutDmProfileBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageProfileViewHolder(baseBinding, binding, onClickListener);
}
case REEL_SHARE: {
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageReelShareViewHolder(baseBinding, binding, onClickListener);
}
case MEDIA_SHARE: {
final LayoutDmMediaShareBinding binding = LayoutDmMediaShareBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageMediaShareViewHolder(baseBinding, binding, onClickListener);
}
case RAVEN_MEDIA: {
final LayoutDmRavenMediaBinding binding = LayoutDmRavenMediaBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageRavenMediaViewHolder(baseBinding, binding, onClickListener);
}
case STORY_SHARE: {
final LayoutDmStoryShareBinding binding = LayoutDmStoryShareBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageStoryShareViewHolder(baseBinding, binding, onClickListener);
}
case VOICE_MEDIA: {
final LayoutDmVoiceMediaBinding binding = LayoutDmVoiceMediaBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageVoiceMediaViewHolder(baseBinding, binding, onClickListener);
}
case ANIMATED_MEDIA: {
final LayoutDmAnimatedMediaBinding binding = LayoutDmAnimatedMediaBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageAnimatedMediaViewHolder(baseBinding, binding, onClickListener);
}
case VIDEO_CALL_EVENT: {
final LayoutDmTextBinding binding = LayoutDmTextBinding.inflate(layoutInflater, itemViewParent, false);
return new DirectMessageVideoCallEventViewHolder(baseBinding, binding, onClickListener);
}
}
}
@Override
public void onBindViewHolder(@NonNull final DirectMessageItemViewHolder holder, final int position) {
final DirectItemModel directItemModel = getItem(position);
holder.bind(directItemModel, users, leftUsers);
}
@Override
public int getItemViewType(final int position) {
return getItem(position).getItemType().getId();
}
}

View File

@ -1,66 +0,0 @@
package awais.instagrabber.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import java.util.List;
import awais.instagrabber.adapters.viewholder.directmessages.DirectMessageViewHolder;
import awais.instagrabber.databinding.ItemMessageItemBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
public final class MessageItemsAdapter extends ListAdapter<DirectItemModel, DirectMessageViewHolder> {
private final List<ProfileModel> users;
private final List<ProfileModel> leftUsers;
private final View.OnClickListener onClickListener;
private final MentionClickListener mentionClickListener;
private static final DiffUtil.ItemCallback<DirectItemModel> diffCallback = new DiffUtil.ItemCallback<DirectItemModel>() {
@Override
public boolean areItemsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
return oldItem.getItemId().equals(newItem.getItemId());
}
@Override
public boolean areContentsTheSame(@NonNull final DirectItemModel oldItem, @NonNull final DirectItemModel newItem) {
return oldItem.getItemId().equals(newItem.getItemId());
}
};
public MessageItemsAdapter(final List<ProfileModel> users,
final List<ProfileModel> leftUsers,
final View.OnClickListener onClickListener,
final MentionClickListener mentionClickListener) {
super(diffCallback);
this.users = users;
this.leftUsers = leftUsers;
this.onClickListener = onClickListener;
this.mentionClickListener = mentionClickListener;
}
@NonNull
@Override
public DirectMessageViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int type) {
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
final ItemMessageItemBinding binding = ItemMessageItemBinding.inflate(layoutInflater, parent, false);
return new DirectMessageViewHolder(binding, users, leftUsers, onClickListener, mentionClickListener);
}
@Override
public void onBindViewHolder(@NonNull final DirectMessageViewHolder holder, final int position) {
final DirectItemModel directItemModel = getItem(position);
holder.bind(directItemModel);
}
@Override
public int getItemViewType(final int position) {
return getItem(position).getItemType().ordinal();
}
}

View File

@ -0,0 +1,33 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT;
public class DirectMessageActionLogViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmTextBinding binding;
public DirectMessageActionLogViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmTextBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final String text = directItemModel.getActionLogModel().getDescription();
binding.tvMessage.setText(HtmlCompat.fromHtml("<small>" + text + "</small>", FROM_HTML_MODE_COMPACT));
binding.tvMessage.setVisibility(View.VISIBLE);
}
}

View File

@ -0,0 +1,29 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.databinding.LayoutDmAnimatedMediaBinding;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
public class DirectMessageAnimatedMediaViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmAnimatedMediaBinding binding;
public DirectMessageAnimatedMediaViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmAnimatedMediaBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
getGlideRequestManager().asGif().load(directItemModel.getAnimatedMediaModel().getGifUrl())
.into(binding.ivAnimatedMessage);
binding.ivAnimatedMessage.setVisibility(View.VISIBLE);
}
}

View File

@ -0,0 +1,100 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
public abstract class DirectMessageItemViewHolder extends RecyclerView.ViewHolder {
private static final int MESSAGE_INCOMING = 69;
private static final int MESSAGE_OUTGOING = 420;
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel(Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)));
private final LayoutDmBaseBinding binding;
private final String strDmYou;
private final int itemMargin;
private final RequestManager glideRequestManager;
public DirectMessageItemViewHolder(@NonNull final LayoutDmBaseBinding binding, @NonNull final View.OnClickListener onClickListener) {
super(binding.getRoot());
this.binding = binding;
binding.ivProfilePic.setOnClickListener(onClickListener);
binding.messageCard.setOnClickListener(onClickListener);
strDmYou = binding.getRoot().getContext().getString(R.string.direct_messages_you);
itemMargin = Utils.displayMetrics.widthPixels / 5;
glideRequestManager = Glide.with(itemView);
}
public void bind(final DirectItemModel directItemModel, final List<ProfileModel> users, final List<ProfileModel> leftUsers) {
final ProfileModel user = getUser(directItemModel.getUserId(), users, leftUsers);
final int type = user == myProfileHolder ? MESSAGE_OUTGOING : MESSAGE_INCOMING;
final RecyclerView.LayoutParams itemViewLayoutParams = (RecyclerView.LayoutParams) itemView.getLayoutParams();
itemViewLayoutParams.setMargins(type == MESSAGE_OUTGOING ? itemMargin : 0, 0,
type == MESSAGE_INCOMING ? itemMargin : 0, 0);
final ViewGroup messageCardParent = (ViewGroup) binding.messageCard.getParent();
binding.contentContainer.setGravity(type == MESSAGE_INCOMING ? Gravity.START : Gravity.END);
CharSequence text = "?";
if (user != null && user != myProfileHolder) {
text = user.getUsername();
} else if (user == myProfileHolder) text = "";
text = (Utils.isEmpty(text) ? "" : text + " - ") + directItemModel.getDateTime();
binding.tvUsername.setText(text);
binding.tvUsername.setGravity(type == MESSAGE_INCOMING ? Gravity.START : Gravity.END);
binding.ivProfilePic.setVisibility(type == MESSAGE_INCOMING ? View.VISIBLE : View.GONE);
binding.ivProfilePic.setTag(user);
binding.likedContainer.setVisibility(directItemModel.isLiked() ? View.VISIBLE : View.GONE);
messageCardParent.setTag(directItemModel);
binding.messageCard.setTag(directItemModel);
if (type == MESSAGE_INCOMING && user != null) {
glideRequestManager.load(user.getSdProfilePic()).into(binding.ivProfilePic);
}
bindItem(directItemModel);
}
public void setItemView(final View view) {
this.binding.messageCard.addView(view);
}
public RequestManager getGlideRequestManager() {
return glideRequestManager;
}
public abstract void bindItem(final DirectItemModel directItemModel);
@Nullable
private ProfileModel getUser(final long userId, final List<ProfileModel> users, final List<ProfileModel> leftUsers) {
if (users != null) {
ProfileModel result = myProfileHolder;
for (final ProfileModel user : users) {
if (Long.toString(userId).equals(user.getId())) result = user;
}
if (leftUsers != null)
for (final ProfileModel leftUser : leftUsers) {
if (Long.toString(userId).equals(leftUser.getId())) result = leftUser;
}
return result;
}
return null;
}
}

View File

@ -0,0 +1,46 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmLinkBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.utils.Utils;
public class DirectMessageLinkViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmLinkBinding binding;
public DirectMessageLinkViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmLinkBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final DirectItemModel.DirectItemLinkModel link = directItemModel.getLinkModel();
final DirectItemModel.DirectItemLinkContext linkContext = link.getLinkContext();
final String linkImageUrl = linkContext.getLinkImageUrl();
if (Utils.isEmpty(linkImageUrl)) {
binding.ivLinkPreview.setVisibility(View.GONE);
} else {
getGlideRequestManager().load(linkImageUrl).into(binding.ivLinkPreview);
}
if (Utils.isEmpty(linkContext.getLinkTitle())) {
binding.tvLinkTitle.setVisibility(View.GONE);
} else {
binding.tvLinkTitle.setText(linkContext.getLinkTitle());
}
if (Utils.isEmpty(linkContext.getLinkSummary())) {
binding.tvLinkSummary.setVisibility(View.GONE);
} else {
binding.tvLinkSummary.setText(linkContext.getLinkSummary());
}
binding.tvMessage.setText(Utils.getSpannableUrl(link.getText()));
}
}

View File

@ -0,0 +1,44 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import awais.instagrabber.R;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmMediaShareBinding;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.direct_messages.DirectItemModel.DirectItemMediaModel;
import awais.instagrabber.models.enums.MediaItemType;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT;
public class DirectMessageMediaShareViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmMediaShareBinding binding;
public DirectMessageMediaShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmMediaShareBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final Context context = itemView.getContext();
final DirectItemMediaModel mediaModel = directItemModel.getMediaModel();
final ProfileModel modelUser = mediaModel.getUser();
if (modelUser != null) {
binding.tvMessage.setText(HtmlCompat.fromHtml("<small>" + context.getString(R.string.dms_inbox_media_shared_from, modelUser.getUsername()) + "</small>", FROM_HTML_MODE_COMPACT));
}
getGlideRequestManager().load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
final MediaItemType modelMediaType = mediaModel.getMediaType();
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO
|| modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
}
}

View File

@ -0,0 +1,32 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmMediaBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.enums.MediaItemType;
public class DirectMessageMediaViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmMediaBinding binding;
public DirectMessageMediaViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmMediaBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final DirectItemModel.DirectItemMediaModel mediaModel = directItemModel.getMediaModel();
getGlideRequestManager().load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
final MediaItemType modelMediaType = mediaModel.getMediaType();
binding.typeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO
|| modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
}
}

View File

@ -0,0 +1,31 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT;
public class DirectMessagePlaceholderViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmTextBinding binding;
public DirectMessagePlaceholderViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmTextBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
binding.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), FROM_HTML_MODE_COMPACT));
}
}

View File

@ -0,0 +1,38 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmProfileBinding;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
public class DirectMessageProfileViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmProfileBinding binding;
public DirectMessageProfileViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmProfileBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
binding.btnOpenProfile.setOnClickListener(onClickListener);
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final ProfileModel profileModel = directItemModel.getProfileModel();
Glide.with(binding.profileInfo)
.load(profileModel.getSdProfilePic())
.into(binding.profileInfo);
binding.btnOpenProfile.setTag(profileModel);
binding.tvFullName.setText(profileModel.getName());
binding.profileInfoText.setText(profileModel.getUsername());
binding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE);
}
}

View File

@ -0,0 +1,85 @@
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.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmRavenMediaBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.models.enums.RavenExpiringMediaType;
import awais.instagrabber.models.enums.RavenMediaViewType;
import awais.instagrabber.utils.Utils;
public class DirectMessageRavenMediaViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmRavenMediaBinding binding;
public DirectMessageRavenMediaViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmRavenMediaBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
binding.tvMessage.setVisibility(View.GONE);
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final Context context = itemView.getContext();
final DirectItemModel.DirectItemRavenMediaModel ravenMediaModel = directItemModel.getRavenMediaModel();
DirectItemModel.DirectItemMediaModel mediaModel = directItemModel.getMediaModel();
final boolean isExpired = ravenMediaModel == null || (mediaModel = ravenMediaModel.getMedia()) == null ||
Utils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;
DirectItemModel.RavenExpiringMediaActionSummaryModel mediaActionSummary = null;
if (ravenMediaModel != null) {
mediaActionSummary = ravenMediaModel.getExpiringMediaActionSummary();
}
binding.mediaExpiredIcon.setVisibility(isExpired ? View.VISIBLE : View.GONE);
int textRes = R.string.dms_inbox_raven_media_unknown;
if (isExpired) textRes = R.string.dms_inbox_raven_media_expired;
if (!isExpired) {
if (mediaActionSummary != null) {
final RavenExpiringMediaType expiringMediaType = mediaActionSummary.getType();
if (expiringMediaType == RavenExpiringMediaType.RAVEN_DELIVERED)
textRes = R.string.dms_inbox_raven_media_delivered;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENT)
textRes = R.string.dms_inbox_raven_media_sent;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_OPENED)
textRes = R.string.dms_inbox_raven_media_opened;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_REPLAYED)
textRes = R.string.dms_inbox_raven_media_replayed;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENDING)
textRes = R.string.dms_inbox_raven_media_sending;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_BLOCKED)
textRes = R.string.dms_inbox_raven_media_blocked;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SUGGESTED)
textRes = R.string.dms_inbox_raven_media_suggested;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SCREENSHOT)
textRes = R.string.dms_inbox_raven_media_screenshot;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_CANNOT_DELIVER)
textRes = R.string.dms_inbox_raven_media_cant_deliver;
}
final RavenMediaViewType ravenMediaViewType = ravenMediaModel.getViewType();
if (ravenMediaViewType == RavenMediaViewType.PERMANENT || ravenMediaViewType == RavenMediaViewType.REPLAYABLE) {
final MediaItemType mediaType = mediaModel.getMediaType();
textRes = -1;
binding.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
getGlideRequestManager().load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
}
}
if (textRes != -1) {
binding.tvMessage.setText(context.getText(textRes));
binding.tvMessage.setVisibility(View.VISIBLE);
}
}
}

View File

@ -0,0 +1,46 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmRavenMediaBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.utils.Utils;
public class DirectMessageReelShareViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmRavenMediaBinding binding;
public DirectMessageReelShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmRavenMediaBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
binding.tvMessage.setVisibility(View.GONE);
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final DirectItemModel.DirectItemReelShareModel reelShare = directItemModel.getReelShare();
final String text = reelShare.getText();
if (!Utils.isEmpty(text)) {
binding.tvMessage.setText(text);
binding.tvMessage.setVisibility(View.VISIBLE);
}
final DirectItemModel.DirectItemMediaModel reelShareMedia = reelShare.getMedia();
final MediaItemType mediaType = reelShareMedia.getMediaType();
if (mediaType == null)
binding.mediaExpiredIcon.setVisibility(View.VISIBLE);
else {
binding.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
getGlideRequestManager().load(reelShareMedia.getThumbUrl()).into(binding.ivMediaPreview);
}
}
}

View File

@ -0,0 +1,48 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmStoryShareBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.utils.Utils;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT;
public class DirectMessageStoryShareViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmStoryShareBinding binding;
public DirectMessageStoryShareViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmStoryShareBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
binding.tvMessage.setVisibility(View.GONE);
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final DirectItemModel.DirectItemReelShareModel reelShare = directItemModel.getReelShare();
if (reelShare == null) {
binding.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), FROM_HTML_MODE_COMPACT));
binding.tvMessage.setVisibility(View.VISIBLE);
} else {
final String text = reelShare.getText();
if (!Utils.isEmpty(text)) {
binding.tvMessage.setText(text);
binding.tvMessage.setVisibility(View.VISIBLE);
}
final DirectItemModel.DirectItemMediaModel reelShareMedia = reelShare.getMedia();
final MediaItemType mediaType = reelShareMedia.getMediaType();
binding.typeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
getGlideRequestManager().load(reelShareMedia.getThumbUrl()).into(binding.ivMediaPreview);
}
}
}

View File

@ -0,0 +1,43 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.content.Context;
import android.text.Spanned;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import awais.instagrabber.R;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.utils.Utils;
public class DirectMessageTextViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmTextBinding binding;
public DirectMessageTextViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmTextBinding binding,
final View.OnClickListener onClickListener,
final MentionClickListener mentionClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
this.binding.tvMessage.setMentionClickListener(mentionClickListener);
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final Context context = itemView.getContext();
CharSequence text = directItemModel.getText();
text = Utils.getSpannableUrl(text.toString()); // for urls
if (Utils.hasMentions(text)) text = Utils.getMentionText(text); // for mentions
if (text instanceof Spanned)
binding.tvMessage.setText(text, TextView.BufferType.SPANNABLE);
else if (text == "") {
binding.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
} else binding.tvMessage.setText(text);
}
}

View File

@ -0,0 +1,29 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import androidx.annotation.NonNull;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmTextBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
public class DirectMessageVideoCallEventViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmTextBinding binding;
public DirectMessageVideoCallEventViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmTextBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
// todo add call event info
binding.tvMessage.setVisibility(View.VISIBLE);
binding.tvMessage.setBackgroundColor(0xFF_1F90E6);
}
}

View File

@ -1,390 +0,0 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.content.Context;
import android.text.Spanned;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.databinding.ItemMessageItemBinding;
import awais.instagrabber.interfaces.MentionClickListener;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.models.enums.DirectItemType;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.models.enums.RavenExpiringMediaType;
import awais.instagrabber.models.enums.RavenMediaViewType;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_COMPACT;
public final class DirectMessageViewHolder extends RecyclerView.ViewHolder {
private static final String TAG = "DirectMessageViewHolder";
private static final int MESSAGE_INCOMING = 69;
private static final int MESSAGE_OUTGOING = 420;
private final ProfileModel myProfileHolder = ProfileModel.getDefaultProfileModel(Utils.getUserIdFromCookie(Utils.settingsHelper.getString(Constants.COOKIE)));
private final ItemMessageItemBinding binding;
private final List<ProfileModel> users;
private final List<ProfileModel> leftUsers;
private final int itemMargin;
private final String strDmYou;
private DirectItemModel.DirectItemVoiceMediaModel prevVoiceModel;
private ImageView prevPlayIcon;
private View.OnClickListener onClickListener;
private MentionClickListener mentionClickListener;
private final View.OnClickListener voicePlayClickListener = v -> {
final Object tag = v.getTag();
if (v instanceof ViewGroup && tag instanceof DirectItemModel.DirectItemVoiceMediaModel) {
final ImageView playIcon = (ImageView) ((ViewGroup) v).getChildAt(0);
final DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = (DirectItemModel.DirectItemVoiceMediaModel) tag;
final boolean voicePlaying = voiceMediaModel.isPlaying();
voiceMediaModel.setPlaying(!voicePlaying);
if (voiceMediaModel == prevVoiceModel) {
// todo pause / resume
} else {
// todo release prev audio, start new voice
if (prevVoiceModel != null) prevVoiceModel.setPlaying(false);
if (prevPlayIcon != null)
prevPlayIcon.setImageResource(android.R.drawable.ic_media_play);
}
if (voicePlaying) {
playIcon.setImageResource(android.R.drawable.ic_media_play);
} else {
playIcon.setImageResource(android.R.drawable.ic_media_pause);
}
prevVoiceModel = voiceMediaModel;
prevPlayIcon = playIcon;
}
};
public DirectMessageViewHolder(final ItemMessageItemBinding binding,
final List<ProfileModel> users,
final List<ProfileModel> leftUsers,
final View.OnClickListener onClickListener,
final MentionClickListener mentionClickListener) {
super(binding.getRoot());
this.binding = binding;
this.users = users;
this.leftUsers = leftUsers;
this.itemMargin = Utils.displayMetrics.widthPixels / 5;
this.onClickListener = onClickListener;
this.mentionClickListener = mentionClickListener;
strDmYou = binding.getRoot().getContext().getString(R.string.direct_messages_you);
}
public void bind(final DirectItemModel directItemModel) {
if (directItemModel == null) {
return;
}
final Context context = itemView.getContext();
//itemView.setTag(directItemModel);
final DirectItemType itemType = directItemModel.getItemType();
final ProfileModel user = getUser(directItemModel.getUserId());
final int type = user == myProfileHolder ? MESSAGE_OUTGOING : MESSAGE_INCOMING;
final RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) itemView.getLayoutParams();
layoutParams.setMargins(type == MESSAGE_OUTGOING ? itemMargin : 0, 0,
type == MESSAGE_INCOMING ? itemMargin : 0, 0);
binding.tvMessage.setVisibility(View.GONE);
final View voiceMessageContainer = (View) binding.waveformSeekBar.getParent();
final View linkMessageContainer = (View) binding.ivLinkPreview.getParent();
final View mediaMessageContainer = (View) binding.ivMediaPreview.getParent();
final View mediaTypeIcon = binding.typeIcon;
final View profileMessageContainer = (View) binding.profileInfo.getParent();
voiceMessageContainer.setVisibility(View.GONE);
binding.ivAnimatedMessage.setVisibility(View.GONE);
linkMessageContainer.setVisibility(View.GONE);
mediaMessageContainer.setVisibility(View.GONE);
mediaTypeIcon.setVisibility(View.GONE);
binding.mediaExpiredIcon.setVisibility(View.GONE);
profileMessageContainer.setVisibility(View.GONE);
binding.isVerified.setVisibility(View.GONE);
final FrameLayout btnOpenProfile = binding.btnInfo;
btnOpenProfile.setVisibility(View.GONE);
btnOpenProfile.setOnClickListener(null);
btnOpenProfile.setTag(null);
CharSequence text = "?";
if (user != null && user != myProfileHolder) text = user.getUsername();
else if (user == myProfileHolder) text = strDmYou;
text = text + " - " + directItemModel.getDateTime();
binding.tvUsername.setText(text);
binding.ivProfilePic.setVisibility(type == MESSAGE_INCOMING ? View.VISIBLE : View.GONE);
binding.ivProfilePic.setTag(user);
binding.ivProfilePic.setOnClickListener(onClickListener);
binding.tvMessage.setMentionClickListener(mentionClickListener);
binding.messageCard.setTag(directItemModel);
LinearLayout parent = (LinearLayout) binding.messageCard.getParent();
parent.setTag(directItemModel);
binding.messageCard.setOnClickListener(onClickListener);
binding.liked.setVisibility(directItemModel.isLiked() ? View.VISIBLE : View.GONE);
final RequestManager glideRequestManager = Glide.with(itemView);
if (type == MESSAGE_INCOMING && user != null)
glideRequestManager.load(user.getSdProfilePic()).into(binding.ivProfilePic);
DirectItemModel.DirectItemMediaModel mediaModel = directItemModel.getMediaModel();
switch (itemType) {
case PLACEHOLDER:
binding.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), FROM_HTML_MODE_COMPACT));
binding.tvMessage.setVisibility(View.VISIBLE);
break;
case TEXT:
case LIKE:
text = directItemModel.getText();
text = Utils.getSpannableUrl(text.toString()); // for urls
if (Utils.hasMentions(text)) text = Utils.getMentionText(text); // for mentions
if (text instanceof Spanned)
binding.tvMessage.setText(text, TextView.BufferType.SPANNABLE);
else if (text == "") {
binding.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
} else binding.tvMessage.setText(text);
binding.tvMessage.setVisibility(View.VISIBLE);
break;
case LINK: {
final DirectItemModel.DirectItemLinkModel link = directItemModel.getLinkModel();
final DirectItemModel.DirectItemLinkContext linkContext = link.getLinkContext();
final String linkImageUrl = linkContext.getLinkImageUrl();
if (!Utils.isEmpty(linkImageUrl)) {
glideRequestManager.load(linkImageUrl).into(binding.ivLinkPreview);
binding.tvLinkTitle.setText(linkContext.getLinkTitle());
binding.tvLinkSummary.setText(linkContext.getLinkSummary());
binding.ivLinkPreview.setVisibility(View.VISIBLE);
linkMessageContainer.setVisibility(View.VISIBLE);
}
binding.tvMessage.setText(Utils.getSpannableUrl(link.getText()));
binding.tvMessage.setVisibility(View.VISIBLE);
}
break;
case MEDIA_SHARE: {
final ProfileModel modelUser = mediaModel.getUser();
if (modelUser != null) {
binding.tvMessage.setText(HtmlCompat.fromHtml("<small>" + context.getString(R.string.dms_inbox_media_shared_from, modelUser.getUsername()) + "</small>", FROM_HTML_MODE_COMPACT));
binding.tvMessage.setVisibility(View.VISIBLE);
}
}
case MEDIA: {
glideRequestManager.load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
final MediaItemType modelMediaType = mediaModel.getMediaType();
mediaTypeIcon.setVisibility(modelMediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
modelMediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
mediaMessageContainer.setVisibility(View.VISIBLE);
}
break;
case RAVEN_MEDIA: {
final DirectItemModel.DirectItemRavenMediaModel ravenMediaModel = directItemModel.getRavenMediaModel();
final boolean isExpired = ravenMediaModel == null || (mediaModel = ravenMediaModel.getMedia()) == null ||
Utils.isEmpty(mediaModel.getThumbUrl()) && mediaModel.getPk() < 1;
DirectItemModel.RavenExpiringMediaActionSummaryModel mediaActionSummary = null;
if (ravenMediaModel != null) {
mediaActionSummary = ravenMediaModel.getExpiringMediaActionSummary();
}
binding.mediaExpiredIcon.setVisibility(isExpired ? View.VISIBLE : View.GONE);
int textRes = R.string.dms_inbox_raven_media_unknown;
if (isExpired) textRes = R.string.dms_inbox_raven_media_expired;
if (!isExpired) {
if (mediaActionSummary != null) {
final RavenExpiringMediaType expiringMediaType = mediaActionSummary.getType();
if (expiringMediaType == RavenExpiringMediaType.RAVEN_DELIVERED)
textRes = R.string.dms_inbox_raven_media_delivered;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENT)
textRes = R.string.dms_inbox_raven_media_sent;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_OPENED)
textRes = R.string.dms_inbox_raven_media_opened;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_REPLAYED)
textRes = R.string.dms_inbox_raven_media_replayed;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SENDING)
textRes = R.string.dms_inbox_raven_media_sending;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_BLOCKED)
textRes = R.string.dms_inbox_raven_media_blocked;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SUGGESTED)
textRes = R.string.dms_inbox_raven_media_suggested;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_SCREENSHOT)
textRes = R.string.dms_inbox_raven_media_screenshot;
else if (expiringMediaType == RavenExpiringMediaType.RAVEN_CANNOT_DELIVER)
textRes = R.string.dms_inbox_raven_media_cant_deliver;
}
final RavenMediaViewType ravenMediaViewType = ravenMediaModel.getViewType();
if (ravenMediaViewType == RavenMediaViewType.PERMANENT || ravenMediaViewType == RavenMediaViewType.REPLAYABLE) {
final MediaItemType mediaType = mediaModel.getMediaType();
textRes = -1;
mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
glideRequestManager.load(mediaModel.getThumbUrl()).into(binding.ivMediaPreview);
mediaMessageContainer.setVisibility(View.VISIBLE);
}
}
if (textRes != -1) {
binding.tvMessage.setText(context.getText(textRes));
binding.tvMessage.setVisibility(View.VISIBLE);
}
}
break;
case REEL_SHARE: {
final DirectItemModel.DirectItemReelShareModel reelShare = directItemModel.getReelShare();
if (!Utils.isEmpty(text = reelShare.getText())) {
binding.tvMessage.setText(text);
binding.tvMessage.setVisibility(View.VISIBLE);
}
final DirectItemModel.DirectItemMediaModel reelShareMedia = reelShare.getMedia();
final MediaItemType mediaType = reelShareMedia.getMediaType();
if (mediaType == null)
binding.mediaExpiredIcon.setVisibility(View.VISIBLE);
else {
mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
glideRequestManager.load(reelShareMedia.getThumbUrl()).into(binding.ivMediaPreview);
mediaMessageContainer.setVisibility(View.VISIBLE);
}
}
break;
case STORY_SHARE: {
final DirectItemModel.DirectItemReelShareModel reelShare = directItemModel.getReelShare();
if (reelShare == null) {
binding.tvMessage.setText(HtmlCompat.fromHtml(directItemModel.getText().toString(), FROM_HTML_MODE_COMPACT));
binding.tvMessage.setVisibility(View.VISIBLE);
} else {
if (!Utils.isEmpty(text = reelShare.getText())) {
binding.tvMessage.setText(text);
binding.tvMessage.setVisibility(View.VISIBLE);
}
final DirectItemModel.DirectItemMediaModel reelShareMedia = reelShare.getMedia();
final MediaItemType mediaType = reelShareMedia.getMediaType();
mediaTypeIcon.setVisibility(mediaType == MediaItemType.MEDIA_TYPE_VIDEO ||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER ? View.VISIBLE : View.GONE);
glideRequestManager.load(reelShareMedia.getThumbUrl()).into(binding.ivMediaPreview);
mediaMessageContainer.setVisibility(View.VISIBLE);
}
}
break;
case VOICE_MEDIA: {
final DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = directItemModel.getVoiceMediaModel();
if (voiceMediaModel != null) {
final int[] waveformData = voiceMediaModel.getWaveformData();
if (waveformData != null) binding.waveformSeekBar.setSample(waveformData);
final long durationMs = voiceMediaModel.getDurationMs();
binding.tvVoiceDuration.setText(Utils.millisToString(durationMs));
binding.waveformSeekBar.setProgress(voiceMediaModel.getProgress());
binding.waveformSeekBar.setProgressChangeListener((waveformSeekBar, progress, fromUser) -> {
// todo progress audio player
voiceMediaModel.setProgress(progress);
if (fromUser)
binding.tvVoiceDuration.setText(Utils.millisToString(durationMs * progress / 100));
});
binding.btnPlayVoice.setTag(voiceMediaModel);
binding.btnPlayVoice.setOnClickListener(voicePlayClickListener);
} else {
binding.waveformSeekBar.setProgress(0);
}
voiceMessageContainer.setVisibility(View.VISIBLE);
}
break;
case ANIMATED_MEDIA: {
glideRequestManager.asGif().load(directItemModel.getAnimatedMediaModel().getGifUrl())
.into(binding.ivAnimatedMessage);
binding.ivAnimatedMessage.setVisibility(View.VISIBLE);
}
break;
case PROFILE: {
final ProfileModel profileModel = directItemModel.getProfileModel();
Glide.with(binding.profileInfo).load(profileModel.getSdProfilePic())
.into(binding.profileInfo);
btnOpenProfile.setTag(profileModel);
btnOpenProfile.setOnClickListener(onClickListener);
binding.tvFullName.setText(profileModel.getName());
binding.profileInfoText.setText(profileModel.getUsername());
binding.isVerified.setVisibility(profileModel.isVerified() ? View.VISIBLE : View.GONE);
btnOpenProfile.setVisibility(View.VISIBLE);
profileMessageContainer.setVisibility(View.VISIBLE);
}
break;
case VIDEO_CALL_EVENT: {
// todo add call event info
binding.tvMessage.setVisibility(View.VISIBLE);
binding.profileInfoText.setBackgroundColor(0xFF_1F90E6);
}
break;
case ACTION_LOG: {
text = directItemModel.getActionLogModel().getDescription();
binding.tvMessage.setText(HtmlCompat.fromHtml("<small>" + text + "</small>", FROM_HTML_MODE_COMPACT));
binding.tvMessage.setVisibility(View.VISIBLE);
}
break;
}
}
@Nullable
private ProfileModel getUser(final long userId) {
if (users != null) {
ProfileModel result = myProfileHolder;
for (final ProfileModel user : users) {
if (Long.toString(userId).equals(user.getId())) result = user;
}
if (leftUsers != null)
for (final ProfileModel leftUser : leftUsers) {
if (Long.toString(userId).equals(leftUser.getId())) result = leftUser;
}
return result;
}
return null;
}
}

View File

@ -0,0 +1,77 @@
package awais.instagrabber.adapters.viewholder.directmessages;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import awais.instagrabber.databinding.LayoutDmBaseBinding;
import awais.instagrabber.databinding.LayoutDmVoiceMediaBinding;
import awais.instagrabber.models.direct_messages.DirectItemModel;
import awais.instagrabber.utils.Utils;
public class DirectMessageVoiceMediaViewHolder extends DirectMessageItemViewHolder {
private final LayoutDmVoiceMediaBinding binding;
private DirectItemModel.DirectItemVoiceMediaModel prevVoiceModel;
private ImageView prevPlayIcon;
public DirectMessageVoiceMediaViewHolder(@NonNull final LayoutDmBaseBinding baseBinding,
@NonNull final LayoutDmVoiceMediaBinding binding,
final View.OnClickListener onClickListener) {
super(baseBinding, onClickListener);
this.binding = binding;
// todo pause / resume
// todo release prev audio, start new voice
binding.btnPlayVoice.setOnClickListener(v -> {
final Object tag = v.getTag();
final ImageView playIcon = (ImageView) ((ViewGroup) v).getChildAt(0);
final DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = (DirectItemModel.DirectItemVoiceMediaModel) tag;
final boolean voicePlaying = voiceMediaModel.isPlaying();
voiceMediaModel.setPlaying(!voicePlaying);
if (voiceMediaModel == prevVoiceModel) {
// todo pause / resume
} else {
// todo release prev audio, start new voice
if (prevVoiceModel != null) prevVoiceModel.setPlaying(false);
if (prevPlayIcon != null)
prevPlayIcon.setImageResource(android.R.drawable.ic_media_play);
}
if (voicePlaying) {
playIcon.setImageResource(android.R.drawable.ic_media_play);
} else {
playIcon.setImageResource(android.R.drawable.ic_media_pause);
}
prevVoiceModel = voiceMediaModel;
prevPlayIcon = playIcon;
});
setItemView(binding.getRoot());
}
@Override
public void bindItem(final DirectItemModel directItemModel) {
final DirectItemModel.DirectItemVoiceMediaModel voiceMediaModel = directItemModel.getVoiceMediaModel();
if (voiceMediaModel != null) {
final int[] waveformData = voiceMediaModel.getWaveformData();
if (waveformData != null) binding.waveformSeekBar.setSample(waveformData);
final long durationMs = voiceMediaModel.getDurationMs();
binding.tvVoiceDuration.setText(Utils.millisToString(durationMs));
binding.waveformSeekBar.setProgress(voiceMediaModel.getProgress());
binding.waveformSeekBar.setProgressChangeListener((waveformSeekBar, progress, fromUser) -> {
// todo progress audio player
voiceMediaModel.setProgress(progress);
if (fromUser)
binding.tvVoiceDuration.setText(Utils.millisToString(durationMs * progress / 100));
});
binding.btnPlayVoice.setTag(voiceMediaModel);
} else {
binding.waveformSeekBar.setProgress(0);
}
}
}

View File

@ -31,8 +31,6 @@ import androidx.recyclerview.widget.RecyclerView;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
@ -47,7 +45,7 @@ import awais.instagrabber.R;
import awais.instagrabber.activities.PostViewer; import awais.instagrabber.activities.PostViewer;
import awais.instagrabber.activities.ProfileViewer; import awais.instagrabber.activities.ProfileViewer;
import awais.instagrabber.activities.StoryViewer; import awais.instagrabber.activities.StoryViewer;
import awais.instagrabber.adapters.MessageItemsAdapter; import awais.instagrabber.adapters.DirectMessageItemsAdapter;
import awais.instagrabber.asyncs.ImageUploader; import awais.instagrabber.asyncs.ImageUploader;
import awais.instagrabber.asyncs.direct_messages.DirectMessageInboxThreadFetcher; import awais.instagrabber.asyncs.direct_messages.DirectMessageInboxThreadFetcher;
import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster; import awais.instagrabber.asyncs.direct_messages.DirectThreadBroadcaster;
@ -187,8 +185,9 @@ public class DirectMessageThreadFragment extends Fragment {
new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, cursor, fetchListener).execute(); // serial because we don't want messages to be randomly ordered new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, cursor, fetchListener).execute(); // serial because we don't want messages to be randomly ordered
})); }));
final DialogInterface.OnClickListener onDialogListener = (d,w) -> { final DialogInterface.OnClickListener onDialogListener = (dialogInterface, which) -> {
if (w == 0) { switch (which) {
case 0:
final DirectItemType itemType = directItemModel.getItemType(); final DirectItemType itemType = directItemModel.getItemType();
switch (itemType) { switch (itemType) {
case MEDIA_SHARE: case MEDIA_SHARE:
@ -239,23 +238,22 @@ public class DirectMessageThreadFragment extends Fragment {
default: default:
Log.d("austin_debug", "unsupported type " + itemType); Log.d("austin_debug", "unsupported type " + itemType);
} }
} break;
else if (w == 1) { case 1:
sendText(null, directItemModel.getItemId(), directItemModel.isLiked()); sendText(null, directItemModel.getItemId(), directItemModel.isLiked());
} break;
else if (w == 2) { case 2:
if (String.valueOf(directItemModel.getUserId()).equals(myId)) { if (String.valueOf(directItemModel.getUserId()).equals(myId)) {
// unsend: https://www.instagram.com/direct_v2/web/threads/340282366841710300949128288687654467119/items/29473546990090204551245070881259520/delete/ // unsend: https://www.instagram.com/direct_v2/web/threads/340282366841710300949128288687654467119/items/29473546990090204551245070881259520/delete/
} } else searchUsername(getUser(directItemModel.getUserId()).getUsername());
else searchUsername(getUser(directItemModel.getUserId()).getUsername()); break;
} }
}; };
final View.OnClickListener onClickListener = v -> { final View.OnClickListener onClickListener = v -> {
Object tag = v.getTag(); Object tag = v.getTag();
if (tag instanceof ProfileModel) { if (tag instanceof ProfileModel) {
searchUsername(((ProfileModel) tag).getUsername()); searchUsername(((ProfileModel) tag).getUsername());
} } else if (tag instanceof DirectItemModel) {
else if (tag instanceof DirectItemModel) {
directItemModel = (DirectItemModel) tag; directItemModel = (DirectItemModel) tag;
final DirectItemType itemType = directItemModel.getItemType(); final DirectItemType itemType = directItemModel.getItemType();
int firstOption = R.string.dms_inbox_raven_message_unknown; int firstOption = R.string.dms_inbox_raven_message_unknown;
@ -300,12 +298,12 @@ public class DirectMessageThreadFragment extends Fragment {
new AlertDialog.Builder(requireContext()) new AlertDialog.Builder(requireContext())
//.setTitle(title) //.setTitle(title)
.setAdapter(dialogAdapter, onDialogListener) .setAdapter(dialogAdapter, onDialogListener)
.setNeutralButton(R.string.cancel, null) // .setNeutralButton(R.string.cancel, null)
.show(); .show();
} }
}; };
final MentionClickListener mentionClickListener = (view, text, isHashtag) -> searchUsername(text); final MentionClickListener mentionClickListener = (view, text, isHashtag) -> searchUsername(text);
final MessageItemsAdapter adapter = new MessageItemsAdapter(users, leftUsers, onClickListener, mentionClickListener); final DirectMessageItemsAdapter adapter = new DirectMessageItemsAdapter(users, leftUsers, onClickListener, mentionClickListener);
messageList.setAdapter(adapter); messageList.setAdapter(adapter);
listViewModel = new ViewModelProvider(fragmentActivity).get(DirectItemModelListViewModel.class); listViewModel = new ViewModelProvider(fragmentActivity).get(DirectItemModelListViewModel.class);
listViewModel.getList().observe(fragmentActivity, adapter::submitList); listViewModel.getList().observe(fragmentActivity, adapter::submitList);
@ -342,8 +340,7 @@ public class DirectMessageThreadFragment extends Fragment {
Log.e(TAG, "Error", e); Log.e(TAG, "Error", e);
return; return;
} }
} } else {
else {
reactionOptions = new DirectThreadBroadcaster.ReactionBroadcastOptions(itemId, delete); reactionOptions = new DirectThreadBroadcaster.ReactionBroadcastOptions(itemId, delete);
} }
broadcast(text != null ? textOptions : reactionOptions, result -> { broadcast(text != null ? textOptions : reactionOptions, result -> {
@ -353,10 +350,11 @@ public class DirectMessageThreadFragment extends Fragment {
} }
if (text != null) { if (text != null) {
binding.commentText.setText(""); binding.commentText.setText("");
} else {
final LinearLayout dim = (LinearLayout) binding.messageList.findViewWithTag(directItemModel).getParent();
if (dim.findViewById(R.id.liked_container) != null) {
dim.findViewById(R.id.liked_container).setVisibility(delete ? View.GONE : View.VISIBLE);
} }
else {
LinearLayout dim = (LinearLayout) binding.messageList.findViewWithTag(directItemModel);
if (dim.findViewById(R.id.liked) != null) dim.findViewById(R.id.liked).setVisibility(delete ? View.GONE : View.VISIBLE);
directItemModel.setLiked(); directItemModel.setLiked();
} }
hasSentSomething = true; hasSentSomething = true;
@ -384,15 +382,14 @@ public class DirectMessageThreadFragment extends Fragment {
// Broadcast // Broadcast
final DirectThreadBroadcaster.ImageBroadcastOptions options = new DirectThreadBroadcaster.ImageBroadcastOptions(true, uploadId); final DirectThreadBroadcaster.ImageBroadcastOptions options = new DirectThreadBroadcaster.ImageBroadcastOptions(true, uploadId);
hasSentSomething = true; hasSentSomething = true;
broadcast(options, onBroadcastCompleteListener -> new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)); broadcast(options, broadcastResponse -> new DirectMessageInboxThreadFetcher(threadId, UserInboxDirection.OLDER, null, fetchListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR));
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, "Error parsing json response", e); Log.e(TAG, "Error parsing json response", e);
} }
}); });
final ImageUploadOptions options = ImageUploadOptions.builder(bitmap).build(); final ImageUploadOptions options = ImageUploadOptions.builder(bitmap).build();
imageUploader.execute(options); imageUploader.execute(options);
} } catch (IOException e) {
catch (IOException e) {
Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Error opening file", e); Log.e(TAG, "Error opening file", e);
} }

View File

@ -3,7 +3,6 @@ package awais.instagrabber.models.direct_messages;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.io.Serializable; import java.io.Serializable;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import awais.instagrabber.models.ProfileModel; import awais.instagrabber.models.ProfileModel;
@ -13,8 +12,6 @@ import awais.instagrabber.models.enums.RavenExpiringMediaType;
import awais.instagrabber.models.enums.RavenMediaViewType; import awais.instagrabber.models.enums.RavenMediaViewType;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import static awais.instagrabber.utils.Constants.COOKIE;
public final class DirectItemModel implements Serializable, Comparable<DirectItemModel> { public final class DirectItemModel implements Serializable, Comparable<DirectItemModel> {
private final long userId, timestamp; private final long userId, timestamp;
private final DirectItemType itemType; private final DirectItemType itemType;
@ -31,8 +28,9 @@ public final class DirectItemModel implements Serializable, Comparable<DirectIte
private final DirectItemRavenMediaModel ravenMediaModel; private final DirectItemRavenMediaModel ravenMediaModel;
private final DirectItemAnimatedMediaModel animatedMediaModel; private final DirectItemAnimatedMediaModel animatedMediaModel;
private final DirectItemVideoCallEventModel videoCallEventModel; private final DirectItemVideoCallEventModel videoCallEventModel;
private final Date date;
private final String myId = Utils.getUserIdFromCookie(Utils.settingsHelper.getString(COOKIE)); // private final String myId = Utils.getUserIdFromCookie(Utils.settingsHelper.getString(COOKIE));
public DirectItemModel(final long userId, final long timestamp, final String itemId, final String[] likes, public DirectItemModel(final long userId, final long timestamp, final String itemId, final String[] likes,
final DirectItemType itemType, final CharSequence text, final DirectItemLinkModel linkModel, final DirectItemType itemType, final CharSequence text, final DirectItemLinkModel linkModel,
@ -45,7 +43,7 @@ public final class DirectItemModel implements Serializable, Comparable<DirectIte
this.itemType = itemType; this.itemType = itemType;
this.itemId = itemId; this.itemId = itemId;
this.likes = likes; this.likes = likes;
this.liked = likes != null ? Arrays.asList(likes).contains(myId) : false; this.liked = likes != null && likes.length != 0;
this.text = text; this.text = text;
this.linkModel = linkModel; this.linkModel = linkModel;
this.profileModel = profileModel; this.profileModel = profileModel;
@ -56,6 +54,7 @@ public final class DirectItemModel implements Serializable, Comparable<DirectIte
this.ravenMediaModel = ravenMediaModel; this.ravenMediaModel = ravenMediaModel;
this.videoCallEventModel = videoCallEventModel; this.videoCallEventModel = videoCallEventModel;
this.animatedMediaModel = animatedMediaModel; this.animatedMediaModel = animatedMediaModel;
date = new Date(timestamp / 1000L);
} }
public DirectItemType getItemType() { public DirectItemType getItemType() {
@ -88,7 +87,7 @@ public final class DirectItemModel implements Serializable, Comparable<DirectIte
@NonNull @NonNull
public String getDateTime() { public String getDateTime() {
return Utils.datetimeParser.format(new Date(timestamp / 1000L)); return Utils.datetimeParser.format(date);
} }
public ProfileModel getProfileModel() { public ProfileModel getProfileModel() {

View File

@ -1,20 +1,43 @@
package awais.instagrabber.models.enums; package awais.instagrabber.models.enums;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public enum DirectItemType implements Serializable { public enum DirectItemType implements Serializable {
TEXT, TEXT(1),
LIKE, LIKE(2),
LINK, LINK(3),
MEDIA, MEDIA(4),
RAVEN_MEDIA, RAVEN_MEDIA(5),
PROFILE, PROFILE(6),
VIDEO_CALL_EVENT, VIDEO_CALL_EVENT(7),
ANIMATED_MEDIA, ANIMATED_MEDIA(8),
VOICE_MEDIA, VOICE_MEDIA(9),
MEDIA_SHARE, MEDIA_SHARE(10),
REEL_SHARE, REEL_SHARE(11),
ACTION_LOG, ACTION_LOG(12),
PLACEHOLDER, PLACEHOLDER(13),
STORY_SHARE, STORY_SHARE(14);
private final int id;
private static Map<Integer, DirectItemType> map = new HashMap<>();
static {
for (DirectItemType type : DirectItemType.values()) {
map.put(type.id, type);
}
}
DirectItemType(final int id) {
this.id = id;
}
public int getId() {
return id;
}
public static DirectItemType valueOf(final int id) {
return map.get(id);
}
} }

View File

@ -1,263 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<awais.instagrabber.customviews.CircularImageView
android:id="@+id/ivProfilePic"
android:layout_width="@dimen/message_item_profile_size"
android:layout_height="@dimen/message_item_profile_size"
android:layout_gravity="top|start"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/app_name"
android:textColor="?android:textColorPrimary" />
<androidx.cardview.widget.CardView
android:id="@+id/messageCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground"
app:cardElevation="2dp"
app:cardPreventCornerOverlap="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- profile message -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<awais.instagrabber.customviews.CircularImageView
android:id="@+id/profileInfo"
android:layout_width="@dimen/profile_picture_size"
android:layout_height="@dimen/profile_picture_size" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/isVerified"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="top|start"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:srcCompat="@drawable/verified" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/profileInfoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textSize="16sp" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvFullName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
<!-- expired media message icon -->
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mediaExpiredIcon"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:padding="8dp"
android:src="@drawable/expired"
android:visibility="gone" />
<!-- voice message -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/message_item_size"
android:orientation="horizontal"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingEnd="4dp"
android:paddingRight="4dp"
android:visibility="gone">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/btnPlayVoice"
style="@style/PlayButtonCard"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginStart="2dp"
android:layout_marginLeft="2dp"
android:layout_marginEnd="2dp"
android:layout_marginRight="2dp"
android:foreground="?android:selectableItemBackground"
app:cardCornerRadius="36dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_gravity="center"
app:srcCompat="@android:drawable/ic_media_play" />
</androidx.cardview.widget.CardView>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvVoiceDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:textColorPrimary" />
</LinearLayout>
<awais.instagrabber.customviews.masoudss_waveform.WaveformSeekBar
android:id="@+id/waveformSeekBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp" />
</LinearLayout>
<!-- media message (show above message) -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivMediaPreview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/typeIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|top"
android:layout_margin="8dp"
app:srcCompat="@drawable/video" />
</FrameLayout>
<!-- text message / description -->
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary"
android:visibility="gone" />
<!-- link message (show below message) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivLinkPreview"
android:layout_width="@dimen/profile_picture_size"
android:layout_height="@dimen/profile_picture_size" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/profile_picture_size"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvLinkTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingEnd="4dp"
android:paddingRight="4dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvLinkSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="4dp" />
</LinearLayout>
</LinearLayout>
<!-- animated media message -->
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivAnimatedMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<FrameLayout
android:id="@+id/btnInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dm_profile_button_color"
android:foreground="?android:selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:gravity="center"
android:padding="4dp"
android:singleLine="true"
android:text="@string/open_profile"
android:textSize="16sp" />
</FrameLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/liked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
app:srcCompat="@drawable/ic_like"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ivAnimatedMessage"
android:layout_width="wrap_content"
android:maxHeight="@dimen/dm_media_img_max_height"
android:layout_height="wrap_content" />

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<awais.instagrabber.customviews.CircularImageView
android:id="@+id/ivProfilePic"
android:layout_width="@dimen/message_item_profile_size"
android:layout_height="@dimen/message_item_profile_size"
android:layout_gravity="top|start"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp" />
<LinearLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:gravity="end"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/app_name"
android:textColor="?android:textColorPrimary" />
<androidx.cardview.widget.CardView
android:id="@+id/messageCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foreground="?android:selectableItemBackground"
app:cardCornerRadius="@dimen/dm_message_card_radius"
app:cardElevation="2dp"
app:cardUseCompatPadding="true" />
<androidx.cardview.widget.CardView
android:id="@+id/liked_container"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="-25dp"
android:layout_marginEnd="-10dp"
android:layout_marginRight="-10dp"
app:cardCornerRadius="25dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/liked"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
app:srcCompat="@drawable/ic_like"
app:tint="@color/btn_red_background" />
</androidx.cardview.widget.CardView>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivLinkPreview"
android:layout_width="match_parent"
android:layout_height="@dimen/dm_link_image_size"
android:scaleType="centerCrop"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvLinkTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingEnd="4dp"
android:paddingRight="4dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvLinkSummary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:maxLines="2"
android:ellipsize="end"
android:padding="4dp" />
</LinearLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivMediaPreview"
android:layout_width="wrap_content"
android:maxHeight="@dimen/dm_media_img_max_height"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/typeIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|top"
android:layout_margin="8dp"
app:srcCompat="@drawable/video" />
</FrameLayout>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivMediaPreview"
android:layout_width="wrap_content"
android:maxHeight="@dimen/dm_media_img_max_height"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/typeIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|top"
android:layout_margin="8dp"
app:srcCompat="@drawable/video" />
</FrameLayout>
</LinearLayout>

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<awais.instagrabber.customviews.CircularImageView
android:id="@+id/profileInfo"
android:layout_width="@dimen/profile_picture_size"
android:layout_height="@dimen/profile_picture_size" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/isVerified"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="top|start"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:srcCompat="@drawable/verified" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/profileInfoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textSize="16sp" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvFullName"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:ellipsize="marquee"
android:singleLine="true"
android:textSize="16sp" />
<FrameLayout
android:id="@+id/btnOpenProfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dm_profile_button_color"
android:foreground="?android:selectableItemBackground">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:gravity="center"
android:padding="4dp"
android:singleLine="true"
android:text="@string/open_profile"
android:textSize="16sp" />
</FrameLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mediaExpiredIcon"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:padding="8dp"
android:src="@drawable/expired" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivMediaPreview"
android:layout_width="wrap_content"
android:maxHeight="@dimen/dm_media_img_max_height"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/typeIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|top"
android:layout_margin="8dp"
app:srcCompat="@drawable/video" />
</FrameLayout>
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />
</LinearLayout>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivMediaPreview"
android:layout_width="wrap_content"
android:maxHeight="@dimen/dm_media_img_max_height"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/typeIcon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|top"
android:layout_margin="8dp"
app:srcCompat="@drawable/video" />
</FrameLayout>
<awais.instagrabber.customviews.RamboTextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />
</LinearLayout>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<awais.instagrabber.customviews.RamboTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|fill_horizontal"
android:padding="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" />

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/message_item_size"
android:orientation="horizontal"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingEnd="4dp"
android:paddingRight="4dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:id="@+id/btnPlayVoice"
style="@style/PlayButtonCard"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginStart="2dp"
android:layout_marginLeft="2dp"
android:layout_marginEnd="2dp"
android:layout_marginRight="2dp"
android:foreground="?android:selectableItemBackground"
app:cardCornerRadius="36dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_gravity="center"
app:srcCompat="@android:drawable/ic_media_play" />
</androidx.cardview.widget.CardView>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvVoiceDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:textColorPrimary" />
</LinearLayout>
<awais.instagrabber.customviews.masoudss_waveform.WaveformSeekBar
android:id="@+id/waveformSeekBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp" />
</LinearLayout>

View File

@ -7,6 +7,7 @@
<dimen name="feed_profile_size">48dp</dimen> <dimen name="feed_profile_size">48dp</dimen>
<dimen name="slider_item_size">80dp</dimen> <dimen name="slider_item_size">80dp</dimen>
<dimen name="highlight_size">70dp</dimen> <dimen name="highlight_size">70dp</dimen>
<dimen name="dm_link_image_size">120dp</dimen>
<dimen name="story_item_height">80dp</dimen> <dimen name="story_item_height">80dp</dimen>
<dimen name="story_item_width">45dp</dimen> <dimen name="story_item_width">45dp</dimen>
@ -16,4 +17,6 @@
<dimen name="message_item_size">@dimen/simple_item_picture_size</dimen> <dimen name="message_item_size">@dimen/simple_item_picture_size</dimen>
<dimen name="message_item_profile_size">@dimen/feed_profile_size</dimen> <dimen name="message_item_profile_size">@dimen/feed_profile_size</dimen>
<dimen name="dm_media_img_max_height">500dp</dimen>
<dimen name="dm_message_card_radius">8dp</dimen>
</resources> </resources>