mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-10-31 03:25:34 +00:00 
			
		
		
		
	Allow removing like/reaction
This commit is contained in:
		
							parent
							
								
									255c3c84b4
								
							
						
					
					
						commit
						6a163454f4
					
				| @ -389,7 +389,9 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView. | ||||
| 
 | ||||
|         void onStoryClick(DirectItemStoryShare storyShare); | ||||
| 
 | ||||
|         void onReaction(final DirectItem item, Emoji emoji); | ||||
|         void onReaction(DirectItem item, Emoji emoji); | ||||
| 
 | ||||
|         void onReactionClick(DirectItem item, int position); | ||||
|     } | ||||
| 
 | ||||
|     public interface DirectItemInternalLongClickListener { | ||||
|  | ||||
| @ -10,7 +10,7 @@ import androidx.recyclerview.widget.ListAdapter; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.viewholder.DirectInboxItemViewHolder; | ||||
| import awais.instagrabber.adapters.viewholder.directmessages.DirectInboxItemViewHolder; | ||||
| import awais.instagrabber.databinding.LayoutDmInboxItemBinding; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectItem; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThread; | ||||
|  | ||||
| @ -0,0 +1,81 @@ | ||||
| package awais.instagrabber.adapters; | ||||
| 
 | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.ViewGroup; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.DiffUtil; | ||||
| import androidx.recyclerview.widget.ListAdapter; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.viewholder.directmessages.DirectReactionViewHolder; | ||||
| import awais.instagrabber.databinding.LayoutDmUserItemBinding; | ||||
| import awais.instagrabber.repositories.responses.User; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectItemEmojiReaction; | ||||
| 
 | ||||
| public final class DirectReactionsAdapter extends ListAdapter<DirectItemEmojiReaction, DirectReactionViewHolder> { | ||||
| 
 | ||||
|     private static final DiffUtil.ItemCallback<DirectItemEmojiReaction> DIFF_CALLBACK = new DiffUtil.ItemCallback<DirectItemEmojiReaction>() { | ||||
|         @Override | ||||
|         public boolean areItemsTheSame(@NonNull final DirectItemEmojiReaction oldItem, @NonNull final DirectItemEmojiReaction newItem) { | ||||
|             return oldItem.getSenderId() == newItem.getSenderId(); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public boolean areContentsTheSame(@NonNull final DirectItemEmojiReaction oldItem, @NonNull final DirectItemEmojiReaction newItem) { | ||||
|             return oldItem.getEmoji().equals(newItem.getEmoji()); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     private final long viewerId; | ||||
|     private final List<User> users; | ||||
|     private final String itemId; | ||||
|     private final OnReactionClickListener onReactionClickListener; | ||||
| 
 | ||||
|     public DirectReactionsAdapter(final long viewerId, | ||||
|                                   final List<User> users, | ||||
|                                   final String itemId, | ||||
|                                   final OnReactionClickListener onReactionClickListener) { | ||||
|         super(DIFF_CALLBACK); | ||||
|         this.viewerId = viewerId; | ||||
|         this.users = users; | ||||
|         this.itemId = itemId; | ||||
|         this.onReactionClickListener = onReactionClickListener; | ||||
|         setHasStableIds(true); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public DirectReactionViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { | ||||
|         final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); | ||||
|         final LayoutDmUserItemBinding binding = LayoutDmUserItemBinding.inflate(layoutInflater, parent, false); | ||||
|         return new DirectReactionViewHolder(binding, viewerId, itemId, onReactionClickListener); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onBindViewHolder(@NonNull final DirectReactionViewHolder holder, final int position) { | ||||
|         final DirectItemEmojiReaction reaction = getItem(position); | ||||
|         if (reaction == null) return; | ||||
|         holder.bind(reaction, getUser(reaction.getSenderId())); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public long getItemId(final int position) { | ||||
|         return getItem(position).getSenderId(); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     private User getUser(final long pk) { | ||||
|         return users.stream() | ||||
|                     .filter(user -> user.getPk() == pk) | ||||
|                     .findFirst() | ||||
|                     .orElse(null); | ||||
|     } | ||||
| 
 | ||||
|     public interface OnReactionClickListener { | ||||
|         void onReactionClick(String itemId, DirectItemEmojiReaction reaction); | ||||
|     } | ||||
| } | ||||
| @ -14,7 +14,7 @@ import com.google.common.collect.ImmutableList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.adapters.viewholder.DirectUserViewHolder; | ||||
| import awais.instagrabber.adapters.viewholder.directmessages.DirectUserViewHolder; | ||||
| import awais.instagrabber.databinding.ItemFavSectionHeaderBinding; | ||||
| import awais.instagrabber.databinding.LayoutDmUserItemBinding; | ||||
| import awais.instagrabber.repositories.responses.User; | ||||
|  | ||||
| @ -12,7 +12,7 @@ import java.util.List; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import awais.instagrabber.adapters.DirectUsersAdapter.OnDirectUserClickListener; | ||||
| import awais.instagrabber.adapters.viewholder.DirectUserViewHolder; | ||||
| import awais.instagrabber.adapters.viewholder.directmessages.DirectUserViewHolder; | ||||
| import awais.instagrabber.databinding.LayoutDmUserItemBinding; | ||||
| import awais.instagrabber.repositories.responses.User; | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| package awais.instagrabber.adapters.viewholder; | ||||
| package awais.instagrabber.adapters.viewholder.directmessages; | ||||
| 
 | ||||
| import android.graphics.Typeface; | ||||
| import android.view.View; | ||||
| @ -24,7 +24,6 @@ import androidx.transition.TransitionManager; | ||||
| import com.google.android.material.transition.MaterialFade; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| @ -109,7 +108,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder { | ||||
|     public void bind(final int position, final DirectItem item) { | ||||
|         this.item = item; | ||||
|         final MessageDirection messageDirection = isSelf(item) ? MessageDirection.OUTGOING : MessageDirection.INCOMING; | ||||
|         itemView.post(() -> bindBase(item, messageDirection)); | ||||
|         itemView.post(() -> bindBase(item, messageDirection, position)); | ||||
|         itemView.post(() -> bindItem(item, messageDirection)); | ||||
|         itemView.post(() -> setupLongClickListener(position)); | ||||
|         // bindBase(item, messageDirection); | ||||
| @ -117,7 +116,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder { | ||||
|         // setupLongClickListener(position); | ||||
|     } | ||||
| 
 | ||||
|     private void bindBase(final DirectItem item, final MessageDirection messageDirection) { | ||||
|     private void bindBase(final DirectItem item, final MessageDirection messageDirection, final int position) { | ||||
|         final FrameLayout.LayoutParams containerLayoutParams = (FrameLayout.LayoutParams) binding.container.getLayoutParams(); | ||||
|         final DirectItemType itemType = item.getItemType(); | ||||
|         setMessageDirectionGravity(messageDirection, containerLayoutParams); | ||||
| @ -134,7 +133,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder { | ||||
|             binding.messageInfo.setPadding(0, 0, messageInfoPaddingSmall, dmRadiusSmall); | ||||
|         } | ||||
|         setupReply(item, messageDirection); | ||||
|         setReactions(item); | ||||
|         setReactions(item, position); | ||||
|     } | ||||
| 
 | ||||
|     private void setBackground(final MessageDirection messageDirection) { | ||||
| @ -334,7 +333,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder { | ||||
|         replyInfoLayoutParams.endToStart = isIncoming ? ConstraintLayout.LayoutParams.UNSET : quoteLineId; | ||||
|     } | ||||
| 
 | ||||
|     private void setReactions(final DirectItem item) { | ||||
|     private void setReactions(final DirectItem item, final int position) { | ||||
|         binding.getRoot().post(() -> { | ||||
|             MaterialFade materialFade = new MaterialFade(); | ||||
|             materialFade.addTarget(binding.emojis); | ||||
| @ -343,17 +342,27 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder { | ||||
|             final List<DirectItemEmojiReaction> emojis = reactions != null ? reactions.getEmojis() : null; | ||||
|             if (emojis == null || emojis.isEmpty()) { | ||||
|                 binding.container.setPadding(messageInfoPaddingSmall, messageInfoPaddingSmall, messageInfoPaddingSmall, messageInfoPaddingSmall); | ||||
|                 binding.emojis.setVisibility(View.GONE); | ||||
|                 binding.reactionsWrapper.setVisibility(View.GONE); | ||||
|                 return; | ||||
|             } | ||||
|             binding.emojis.setVisibility(View.VISIBLE); | ||||
|             binding.emojis.setTranslationY(getReactionsTranslationY()); | ||||
|             binding.reactionsWrapper.setVisibility(View.VISIBLE); | ||||
|             binding.reactionsWrapper.setTranslationY(getReactionsTranslationY()); | ||||
|             binding.container.setPadding(messageInfoPaddingSmall, messageInfoPaddingSmall, messageInfoPaddingSmall, reactionAdjustMargin); | ||||
|             final String emojisJoined = emojis.stream() | ||||
|                                               .map(DirectItemEmojiReaction::getEmoji) | ||||
|                                               .collect(Collectors.joining()); | ||||
|             final String text = String.format(Locale.ENGLISH, "%s %d", emojisJoined, emojis.size()); | ||||
|             binding.emojis.setText(text); | ||||
|             binding.emojis.setEmojis(emojis.stream() | ||||
|                                            .map(DirectItemEmojiReaction::getEmoji) | ||||
|                                            .collect(Collectors.toList())); | ||||
|             // binding.emojis.setEmojis(ImmutableList.of("😣", | ||||
|             //                                           "😖", | ||||
|             //                                           "😫", | ||||
|             //                                           "😩", | ||||
|             //                                           "🥺", | ||||
|             //                                           "😢", | ||||
|             //                                           "😭", | ||||
|             //                                           "😤", | ||||
|             //                                           "😠", | ||||
|             //                                           "😡", | ||||
|             //                                           "🤬")); | ||||
|             binding.emojis.setOnClickListener(v -> callback.onReactionClick(item, position)); | ||||
|             // final List<DirectUser> reactedUsers = emojis.stream() | ||||
|             //                                             .map(DirectItemEmojiReaction::getSenderId) | ||||
|             //                                             .distinct() | ||||
|  | ||||
| @ -0,0 +1,71 @@ | ||||
| package awais.instagrabber.adapters.viewholder.directmessages; | ||||
| 
 | ||||
| import android.view.View; | ||||
| 
 | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.adapters.DirectReactionsAdapter.OnReactionClickListener; | ||||
| import awais.instagrabber.customviews.emoji.Emoji; | ||||
| import awais.instagrabber.databinding.LayoutDmUserItemBinding; | ||||
| import awais.instagrabber.repositories.responses.User; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectItemEmojiReaction; | ||||
| import awais.instagrabber.utils.emoji.EmojiParser; | ||||
| 
 | ||||
| public class DirectReactionViewHolder extends RecyclerView.ViewHolder { | ||||
|     private final LayoutDmUserItemBinding binding; | ||||
|     private final long viewerId; | ||||
|     private final String itemId; | ||||
|     private final OnReactionClickListener onReactionClickListener; | ||||
|     private final EmojiParser emojiParser; | ||||
| 
 | ||||
|     public DirectReactionViewHolder(final LayoutDmUserItemBinding binding, | ||||
|                                     final long viewerId, | ||||
|                                     final String itemId, | ||||
|                                     final OnReactionClickListener onReactionClickListener) { | ||||
|         super(binding.getRoot()); | ||||
|         this.binding = binding; | ||||
|         this.viewerId = viewerId; | ||||
|         this.itemId = itemId; | ||||
|         this.onReactionClickListener = onReactionClickListener; | ||||
|         binding.info.setVisibility(View.GONE); | ||||
|         binding.secondaryImage.setVisibility(View.VISIBLE); | ||||
|         emojiParser = EmojiParser.getInstance(); | ||||
|     } | ||||
| 
 | ||||
|     public void bind(final DirectItemEmojiReaction reaction, | ||||
|                      @Nullable final User user) { | ||||
|         itemView.setOnClickListener(v -> { | ||||
|             if (onReactionClickListener == null) return; | ||||
|             onReactionClickListener.onReactionClick(itemId, reaction); | ||||
|         }); | ||||
|         setUser(user); | ||||
|         setReaction(reaction); | ||||
|     } | ||||
| 
 | ||||
|     private void setReaction(final DirectItemEmojiReaction reaction) { | ||||
|         final Emoji emoji = emojiParser.getEmoji(reaction.getEmoji()); | ||||
|         if (emoji == null) { | ||||
|             binding.secondaryImage.setImageDrawable(null); | ||||
|             return; | ||||
|         } | ||||
|         binding.secondaryImage.setImageDrawable(emoji.getDrawable()); | ||||
|     } | ||||
| 
 | ||||
|     private void setUser(final User user) { | ||||
|         if (user == null) { | ||||
|             binding.fullName.setText(""); | ||||
|             binding.username.setText(""); | ||||
|             binding.profilePic.setImageURI((String) null); | ||||
|             return; | ||||
|         } | ||||
|         binding.fullName.setText(user.getFullName()); | ||||
|         if (user.getPk() == viewerId) { | ||||
|             binding.username.setText(R.string.tap_to_remove); | ||||
|         } else { | ||||
|             binding.username.setText(user.getUsername()); | ||||
|         } | ||||
|         binding.profilePic.setImageURI(user.getProfilePicUrl()); | ||||
|     } | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| package awais.instagrabber.adapters.viewholder; | ||||
| package awais.instagrabber.adapters.viewholder.directmessages; | ||||
| 
 | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.text.SpannableStringBuilder; | ||||
| @ -0,0 +1,82 @@ | ||||
| package awais.instagrabber.customviews; | ||||
| 
 | ||||
| import android.annotation.SuppressLint; | ||||
| import android.content.Context; | ||||
| import android.text.SpannableString; | ||||
| import android.text.SpannableStringBuilder; | ||||
| import android.text.TextUtils; | ||||
| import android.util.AttributeSet; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.emoji.widget.EmojiAppCompatTextView; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| public class ReactionEmojiTextView extends EmojiAppCompatTextView { | ||||
|     private static final String TAG = ReactionEmojiTextView.class.getSimpleName(); | ||||
| 
 | ||||
|     private final SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); | ||||
| 
 | ||||
|     private String count = ""; | ||||
|     private SpannableString ellipsisSpannable; | ||||
|     private String distinctEmojis; | ||||
| 
 | ||||
|     public ReactionEmojiTextView(final Context context) { | ||||
|         super(context); | ||||
|         init(); | ||||
|     } | ||||
| 
 | ||||
|     public ReactionEmojiTextView(final Context context, final AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|         init(); | ||||
|     } | ||||
| 
 | ||||
|     public ReactionEmojiTextView(final Context context, final AttributeSet attrs, final int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|         init(); | ||||
|     } | ||||
| 
 | ||||
|     private void init() { | ||||
|         ellipsisSpannable = new SpannableString(count); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("SetTextI18n") | ||||
|     public void setEmojis(@NonNull final List<String> emojis) { | ||||
|         count = String.valueOf(emojis.size()); | ||||
|         distinctEmojis = emojis.stream() | ||||
|                                .distinct() | ||||
|                                .collect(Collectors.joining()); | ||||
|         ellipsisSpannable = new SpannableString(count); | ||||
|         setText(distinctEmojis + (emojis.size() > 1 ? count : "")); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { | ||||
|         super.onMeasure(widthMeasureSpec, heightMeasureSpec); | ||||
|         final CharSequence text = getText(); | ||||
|         if (text == null) return; | ||||
|         final int measuredWidth = getMeasuredWidth(); | ||||
|         float availableTextWidth = measuredWidth - getCompoundPaddingLeft() - getCompoundPaddingRight(); | ||||
|         CharSequence ellipsizedText = TextUtils.ellipsize(text, getPaint(), availableTextWidth, getEllipsize()); | ||||
|         if (!ellipsizedText.toString().equals(text.toString())) { | ||||
|             // If the ellipsizedText is different than the original text, this means that it didn't fit and got indeed ellipsized. | ||||
|             // Calculate the new availableTextWidth by taking into consideration the size of the custom ellipsis, too. | ||||
|             availableTextWidth = (availableTextWidth - getPaint().measureText(count)); | ||||
|             ellipsizedText = TextUtils.ellipsize(text, getPaint(), availableTextWidth, getEllipsize()); | ||||
|             final int defaultEllipsisStart = ellipsizedText.toString().indexOf(getDefaultEllipsis()); | ||||
|             final int defaultEllipsisEnd = defaultEllipsisStart + 1; | ||||
|             spannableStringBuilder.clear(); | ||||
|             // Update the text with the ellipsized version and replace the default ellipsis with the custom one. | ||||
|             final SpannableStringBuilder replace = spannableStringBuilder.append(ellipsizedText) | ||||
|                                                                          .replace(defaultEllipsisStart, defaultEllipsisEnd, ellipsisSpannable); | ||||
|             setText(replace); | ||||
|             super.onMeasure(widthMeasureSpec, heightMeasureSpec); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private char getDefaultEllipsis() { | ||||
|         return '…'; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,121 @@ | ||||
| package awais.instagrabber.dialogs; | ||||
| 
 | ||||
| import android.app.Dialog; | ||||
| import android.content.Context; | ||||
| import android.os.Bundle; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.fragment.app.DialogFragment; | ||||
| import androidx.recyclerview.widget.LinearLayoutManager; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| import com.google.android.material.bottomsheet.BottomSheetDialog; | ||||
| import com.google.android.material.bottomsheet.BottomSheetDialogFragment; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import awais.instagrabber.R; | ||||
| import awais.instagrabber.adapters.DirectReactionsAdapter; | ||||
| import awais.instagrabber.adapters.DirectReactionsAdapter.OnReactionClickListener; | ||||
| import awais.instagrabber.repositories.responses.User; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectItemReactions; | ||||
| import awais.instagrabber.utils.TextUtils; | ||||
| 
 | ||||
| public class DirectItemReactionDialogFragment extends BottomSheetDialogFragment { | ||||
| 
 | ||||
|     private static final String ARG_VIEWER_ID = "viewerId"; | ||||
|     private static final String ARG_ITEM_ID = "itemId"; | ||||
|     private static final String ARG_USERS = "users"; | ||||
|     private static final String ARG_REACTIONS = "reactions"; | ||||
| 
 | ||||
|     private RecyclerView recyclerView; | ||||
|     private OnReactionClickListener onReactionClickListener; | ||||
| 
 | ||||
|     public static DirectItemReactionDialogFragment newInstance(final long viewerId, | ||||
|                                                                @NonNull final ArrayList<User> users, | ||||
|                                                                @NonNull final String itemId, | ||||
|                                                                @NonNull final DirectItemReactions reactions) { | ||||
|         Bundle args = new Bundle(); | ||||
|         args.putLong(ARG_VIEWER_ID, viewerId); | ||||
|         args.putSerializable(ARG_USERS, users); | ||||
|         args.putString(ARG_ITEM_ID, itemId); | ||||
|         args.putSerializable(ARG_REACTIONS, reactions); | ||||
|         DirectItemReactionDialogFragment fragment = new DirectItemReactionDialogFragment(); | ||||
|         fragment.setArguments(args); | ||||
|         return fragment; | ||||
|     } | ||||
| 
 | ||||
|     public DirectItemReactionDialogFragment() {} | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setStyle(DialogFragment.STYLE_NORMAL, R.style.ThemeOverlay_Rounded_BottomSheetDialog); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { | ||||
|         final Context context = getContext(); | ||||
|         if (context == null) { | ||||
|             return null; | ||||
|         } | ||||
|         recyclerView = new RecyclerView(context); | ||||
|         return recyclerView; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) { | ||||
|         init(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onAttach(@NonNull final Context context) { | ||||
|         super.onAttach(context); | ||||
|         try { | ||||
|             onReactionClickListener = (OnReactionClickListener) getParentFragment(); | ||||
|         } catch (ClassCastException e) { | ||||
|             throw new ClassCastException("Calling fragment must implement DirectReactionsAdapter.OnReactionClickListener interface"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onStart() { | ||||
|         super.onStart(); | ||||
|         final Dialog dialog = getDialog(); | ||||
|         if (dialog == null) return; | ||||
|         final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialog; | ||||
|         final View bottomSheetInternal = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet); | ||||
|         if (bottomSheetInternal == null) return; | ||||
|         bottomSheetInternal.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT; | ||||
|         bottomSheetInternal.requestLayout(); | ||||
|     } | ||||
| 
 | ||||
|     private void init() { | ||||
|         final Context context = getContext(); | ||||
|         if (context == null) return; | ||||
|         final Bundle arguments = getArguments(); | ||||
|         if (arguments == null) return; | ||||
|         final long viewerId = arguments.getLong(ARG_VIEWER_ID); | ||||
|         final Serializable usersSerializable = arguments.getSerializable(ARG_USERS); | ||||
|         if (!(usersSerializable instanceof ArrayList)) return; | ||||
|         //noinspection unchecked | ||||
|         final List<User> users = (ArrayList<User>) usersSerializable; | ||||
|         final Serializable reactionsSerializable = arguments.getSerializable(ARG_REACTIONS); | ||||
|         if (!(reactionsSerializable instanceof DirectItemReactions)) return; | ||||
|         final DirectItemReactions reactions = (DirectItemReactions) reactionsSerializable; | ||||
|         final String itemId = arguments.getString(ARG_ITEM_ID); | ||||
|         if (TextUtils.isEmpty(itemId)) return; | ||||
|         recyclerView.setLayoutManager(new LinearLayoutManager(context)); | ||||
|         final DirectReactionsAdapter adapter = new DirectReactionsAdapter(viewerId, users, itemId, onReactionClickListener); | ||||
|         recyclerView.setAdapter(adapter); | ||||
|         adapter.submitList(reactions.getEmojis()); | ||||
|     } | ||||
| } | ||||
| @ -50,6 +50,7 @@ import com.google.android.material.snackbar.Snackbar; | ||||
| import com.google.common.collect.ImmutableList; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| @ -60,6 +61,7 @@ import awais.instagrabber.adapters.DirectItemsAdapter; | ||||
| import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemCallback; | ||||
| import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemLongClickListener; | ||||
| import awais.instagrabber.adapters.DirectItemsAdapter.DirectItemOrHeader; | ||||
| import awais.instagrabber.adapters.DirectReactionsAdapter; | ||||
| import awais.instagrabber.adapters.viewholder.directmessages.DirectItemViewHolder; | ||||
| import awais.instagrabber.animations.CubicBezierInterpolator; | ||||
| import awais.instagrabber.customviews.RecordView; | ||||
| @ -70,6 +72,7 @@ import awais.instagrabber.customviews.helpers.HeightProvider; | ||||
| import awais.instagrabber.customviews.helpers.RecyclerLazyLoaderAtEdge; | ||||
| import awais.instagrabber.customviews.helpers.TextWatcherAdapter; | ||||
| import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding; | ||||
| import awais.instagrabber.dialogs.DirectItemReactionDialogFragment; | ||||
| import awais.instagrabber.dialogs.MediaPickerBottomDialogFragment; | ||||
| import awais.instagrabber.fragments.PostViewV2Fragment; | ||||
| import awais.instagrabber.models.Resource; | ||||
| @ -77,6 +80,7 @@ import awais.instagrabber.repositories.requests.StoryViewerOptions; | ||||
| 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.DirectItemEmojiReaction; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectItemStoryShare; | ||||
| import awais.instagrabber.repositories.responses.directmessages.DirectThread; | ||||
| import awais.instagrabber.utils.AppExecutors; | ||||
| @ -90,7 +94,7 @@ import awais.instagrabber.viewmodels.DirectThreadViewModel; | ||||
| import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; | ||||
| import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN; | ||||
| 
 | ||||
| public class DirectMessageThreadFragment extends Fragment { | ||||
| public class DirectMessageThreadFragment extends Fragment implements DirectReactionsAdapter.OnReactionClickListener { | ||||
|     private static final String TAG = DirectMessageThreadFragment.class.getSimpleName(); | ||||
|     private static final int STORAGE_PERM_REQUEST_CODE = 8020; | ||||
|     private static final int AUDIO_RECORD_PERM_REQUEST_CODE = 1000; | ||||
| @ -145,9 +149,7 @@ public class DirectMessageThreadFragment extends Fragment { | ||||
| 
 | ||||
|         @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); | ||||
|             navigateToUser(mention); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
| @ -215,10 +217,17 @@ public class DirectMessageThreadFragment extends Fragment { | ||||
|                 resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void onReactionClick(final DirectItem item, final int position) { | ||||
|             showReactionsDialog(item); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     private final DirectItemLongClickListener directItemLongClickListener = position -> { | ||||
|         // viewModel.setSelectedPosition(position); | ||||
|     }; | ||||
|     private DirectItemReactionDialogFragment reactionDialogFragment; | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(@Nullable final Bundle savedInstanceState) { | ||||
| @ -1132,6 +1141,50 @@ public class DirectMessageThreadFragment extends Fragment { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private void showReactionsDialog(final DirectItem item) { | ||||
|         final LiveData<List<User>> users = viewModel.getUsers(); | ||||
|         final LiveData<List<User>> leftUsers = viewModel.getLeftUsers(); | ||||
|         final ArrayList<User> allUsers = new ArrayList<>(); | ||||
|         allUsers.add(viewModel.getCurrentUser()); | ||||
|         if (users != null && users.getValue() != null) { | ||||
|             allUsers.addAll(users.getValue()); | ||||
|         } | ||||
|         if (leftUsers != null && leftUsers.getValue() != null) { | ||||
|             allUsers.addAll(leftUsers.getValue()); | ||||
|         } | ||||
|         reactionDialogFragment = DirectItemReactionDialogFragment | ||||
|                 .newInstance(viewModel.getViewerId(), | ||||
|                              allUsers, | ||||
|                              item.getItemId(), | ||||
|                              item.getReactions()); | ||||
|         reactionDialogFragment.show(getChildFragmentManager(), "reactions_dialog"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onReactionClick(final String itemId, final DirectItemEmojiReaction reaction) { | ||||
|         if (reactionDialogFragment != null) { | ||||
|             reactionDialogFragment.dismiss(); | ||||
|         } | ||||
|         if (reaction == null) return; | ||||
|         if (reaction.getSenderId() == viewModel.getViewerId()) { | ||||
|             final LiveData<Resource<DirectItem>> resourceLiveData = viewModel.sendDeleteReaction(itemId); | ||||
|             if (resourceLiveData != null) { | ||||
|                 resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData)); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         // navigate to user | ||||
|         final User user = viewModel.getUser(reaction.getSenderId()); | ||||
|         if (user == null) return; | ||||
|         navigateToUser(user.getUsername()); | ||||
|     } | ||||
| 
 | ||||
|     private void navigateToUser(@NonNull final String username) { | ||||
|         final Bundle bundle = new Bundle(); | ||||
|         bundle.putString("username", "@" + username); | ||||
|         NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(R.id.action_global_profileFragment, bundle); | ||||
|     } | ||||
| 
 | ||||
|     public static class ItemsAdapterDataMerger extends MediatorLiveData<Pair<User, DirectThread>> { | ||||
|         private User user; | ||||
|         private DirectThread thread; | ||||
|  | ||||
| @ -1,8 +1,9 @@ | ||||
| package awais.instagrabber.repositories.responses.directmessages; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| public class DirectItemEmojiReaction { | ||||
| public class DirectItemEmojiReaction implements Serializable { | ||||
|     private final long senderId; | ||||
|     private final long timestamp; | ||||
|     private final String emoji; | ||||
|  | ||||
| @ -2,10 +2,11 @@ package awais.instagrabber.repositories.responses.directmessages; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| public class DirectItemReactions implements Cloneable { | ||||
| public class DirectItemReactions implements Cloneable, Serializable { | ||||
|     private List<DirectItemEmojiReaction> emojis; | ||||
|     private List<DirectItemEmojiReaction> likes; | ||||
| 
 | ||||
|  | ||||
| @ -270,6 +270,13 @@ public final class EmojiParser { | ||||
|         return ALL_EMOJIS; | ||||
|     } | ||||
| 
 | ||||
|     public Emoji getEmoji(final String emoji) { | ||||
|         if (emoji == null) { | ||||
|             return null; | ||||
|         } | ||||
|         return ALL_EMOJIS.get(emoji); | ||||
|     } | ||||
| 
 | ||||
|     // public String getMinorCategory(String emoji) { | ||||
|     //     String minorCat = emojiToMinorCategory.get(emoji); | ||||
|     //     if (minorCat == null) { | ||||
|  | ||||
| @ -77,6 +77,7 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|     private final MutableLiveData<String> threadTitle = new MutableLiveData<>(""); | ||||
|     private final MutableLiveData<Boolean> fetching = new MutableLiveData<>(false); | ||||
|     private final MutableLiveData<List<User>> users = new MutableLiveData<>(new ArrayList<>()); | ||||
|     private final MutableLiveData<List<User>> leftUsers = new MutableLiveData<>(new ArrayList<>()); | ||||
| 
 | ||||
|     private final DirectMessagesService service; | ||||
|     private final ContentResolver contentResolver; | ||||
| @ -92,18 +93,19 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|     private User currentUser; | ||||
|     private Call<DirectThreadFeedResponse> chatsRequest; | ||||
|     private VoiceRecorder voiceRecorder; | ||||
|     private final long viewerId; | ||||
| 
 | ||||
|     public DirectThreadViewModel(@NonNull final Application application) { | ||||
|         super(application); | ||||
|         final String cookie = settingsHelper.getString(Constants.COOKIE); | ||||
|         final long userId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         viewerId = CookieUtils.getUserIdFromCookie(cookie); | ||||
|         final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID); | ||||
|         csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); | ||||
|         if (TextUtils.isEmpty(csrfToken) || userId <= 0 || TextUtils.isEmpty(deviceUuid)) { | ||||
|         if (TextUtils.isEmpty(csrfToken) || viewerId <= 0 || TextUtils.isEmpty(deviceUuid)) { | ||||
|             throw new IllegalArgumentException("User is not logged in!"); | ||||
|         } | ||||
|         service = DirectMessagesService.getInstance(csrfToken, userId, deviceUuid); | ||||
|         mediaService = MediaService.getInstance(deviceUuid, csrfToken, userId); | ||||
|         service = DirectMessagesService.getInstance(csrfToken, viewerId, deviceUuid); | ||||
|         mediaService = MediaService.getInstance(deviceUuid, csrfToken, viewerId); | ||||
|         contentResolver = application.getContentResolver(); | ||||
|         recordingsDir = DirectoryUtils.getOutputMediaDirectory(application, "Recordings"); | ||||
|         this.application = application; | ||||
| @ -138,6 +140,10 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|         return items; | ||||
|     } | ||||
| 
 | ||||
|     public long getViewerId() { | ||||
|         return viewerId; | ||||
|     } | ||||
| 
 | ||||
|     public void setItems(final List<DirectItem> items) { | ||||
|         this.items.postValue(items); | ||||
|     } | ||||
| @ -219,13 +225,53 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|                 "none" | ||||
|         ); | ||||
|         if (index < 0) { | ||||
|             temp.add(reaction); | ||||
|             temp.add(0, reaction); | ||||
|         } else if (shouldReplaceIfAlreadyReacted) { | ||||
|             temp.set(index, reaction); | ||||
|             temp.add(0, reaction); | ||||
|             temp.remove(index); | ||||
|         } | ||||
|         return temp; | ||||
|     } | ||||
| 
 | ||||
|     private void removeReaction(final DirectItem item) { | ||||
|         try { | ||||
|             final DirectItem itemClone = (DirectItem) item.clone(); | ||||
|             final DirectItemReactions reactions = itemClone.getReactions(); | ||||
|             final DirectItemReactions reactionsClone = (DirectItemReactions) reactions.clone(); | ||||
|             final List<DirectItemEmojiReaction> likes = reactionsClone.getLikes(); | ||||
|             if (likes != null) { | ||||
|                 final List<DirectItemEmojiReaction> updatedLikes = likes.stream() | ||||
|                                                                         .filter(like -> like.getSenderId() != viewerId) | ||||
|                                                                         .collect(Collectors.toList()); | ||||
|                 reactionsClone.setLikes(updatedLikes); | ||||
|             } | ||||
|             final List<DirectItemEmojiReaction> emojis = reactionsClone.getEmojis(); | ||||
|             if (emojis != null) { | ||||
|                 final List<DirectItemEmojiReaction> updatedEmojis = emojis.stream() | ||||
|                                                                           .filter(emoji -> emoji.getSenderId() != viewerId) | ||||
|                                                                           .collect(Collectors.toList()); | ||||
|                 reactionsClone.setEmojis(updatedEmojis); | ||||
|             } | ||||
|             itemClone.setReactions(reactionsClone); | ||||
|             List<DirectItem> list = this.items.getValue(); | ||||
|             list = list == null ? new LinkedList<>() : new LinkedList<>(list); | ||||
|             int index = -1; | ||||
|             for (int i = 0; i < list.size(); i++) { | ||||
|                 final DirectItem directItem = list.get(i); | ||||
|                 if (directItem.getItemId().equals(item.getItemId())) { | ||||
|                     index = i; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             if (index >= 0) { | ||||
|                 list.set(index, itemClone); | ||||
|             } | ||||
|             this.items.postValue(list); | ||||
|         } catch (Exception e) { | ||||
|             Log.e(TAG, "removeReaction: ", e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void updateItemSent(final String clientContext, final long timestamp) { | ||||
|         if (clientContext == null) return; | ||||
|         List<DirectItem> list = this.items.getValue(); | ||||
| @ -259,6 +305,10 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|         return users; | ||||
|     } | ||||
| 
 | ||||
|     public LiveData<List<User>> getLeftUsers() { | ||||
|         return leftUsers; | ||||
|     } | ||||
| 
 | ||||
|     public void fetchChats() { | ||||
|         final Boolean isFetching = fetching.getValue(); | ||||
|         if ((isFetching != null && isFetching) || !hasOlder) return; | ||||
| @ -319,9 +369,8 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|         threadTitle.postValue(thread.getThreadTitle()); | ||||
|         cursor = thread.getOldestCursor(); | ||||
|         hasOlder = thread.hasOlder(); | ||||
|         if (users.getValue() == null || users.getValue().isEmpty()) { | ||||
|             users.postValue(thread.getUsers()); | ||||
|         } | ||||
|         users.postValue(thread.getUsers()); | ||||
|         leftUsers.postValue(thread.getLeftUsers()); | ||||
|         fetching.postValue(false); | ||||
|     } | ||||
| 
 | ||||
| @ -637,6 +686,33 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|         } | ||||
|         final Call<DirectThreadBroadcastResponse> request = service.broadcastReaction( | ||||
|                 clientContext, threadIdOrUserIds, item.getItemId(), emojiUnicode, false); | ||||
|         handleBroadcastReactionRequest(data, item, request); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
|     public LiveData<Resource<DirectItem>> sendDeleteReaction(final String itemId) { | ||||
|         final MutableLiveData<Resource<DirectItem>> data = new MutableLiveData<>(); | ||||
|         final DirectItem item = getItem(itemId); | ||||
|         if (item == null) { | ||||
|             data.postValue(Resource.error("Invalid item", null)); | ||||
|             return data; | ||||
|         } | ||||
|         final DirectItemReactions reactions = item.getReactions(); | ||||
|         if (reactions == null) { | ||||
|             // already removed? | ||||
|             data.postValue(Resource.success(item)); | ||||
|             return data; | ||||
|         } | ||||
|         removeReaction(item); | ||||
|         final String clientContext = UUID.randomUUID().toString(); | ||||
|         final Call<DirectThreadBroadcastResponse> request = service.broadcastReaction(clientContext, threadIdOrUserIds, item.getItemId(), null, true); | ||||
|         handleBroadcastReactionRequest(data, item, request); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
|     private void handleBroadcastReactionRequest(final MutableLiveData<Resource<DirectItem>> data, | ||||
|                                                 final DirectItem item, | ||||
|                                                 @NonNull final Call<DirectThreadBroadcastResponse> request) { | ||||
|         request.enqueue(new Callback<DirectThreadBroadcastResponse>() { | ||||
|             @Override | ||||
|             public void onResponse(@NonNull final Call<DirectThreadBroadcastResponse> call, | ||||
| @ -662,13 +738,51 @@ public class DirectThreadViewModel extends AndroidViewModel { | ||||
|                 Log.e(TAG, "enqueueRequest: onFailure: ", t); | ||||
|             } | ||||
|         }); | ||||
|         return data; | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     private DirectItem getItem(final String itemId) { | ||||
|         if (itemId == null) return null; | ||||
|         final List<DirectItem> items = this.items.getValue(); | ||||
|         if (items == null) return null; | ||||
|         return items.stream() | ||||
|                     .filter(directItem -> directItem.getItemId().equals(itemId)) | ||||
|                     .findFirst() | ||||
|                     .orElse(null); | ||||
|     } | ||||
| 
 | ||||
|     public User getCurrentUser() { | ||||
|         return currentUser; | ||||
|     } | ||||
| 
 | ||||
|     public void setCurrentUser(final User currentUser) { | ||||
|         this.currentUser = currentUser; | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     public User getUser(final long userId) { | ||||
|         final LiveData<List<User>> users = getUsers(); | ||||
|         User match = null; | ||||
|         if (users != null && users.getValue() != null) { | ||||
|             final List<User> userList = users.getValue(); | ||||
|             match = userList.stream() | ||||
|                             .filter(user -> user.getPk() == userId) | ||||
|                             .findFirst() | ||||
|                             .orElse(null); | ||||
|         } | ||||
|         if (match == null) { | ||||
|             final LiveData<List<User>> leftUsers = getLeftUsers(); | ||||
|             if (leftUsers != null && leftUsers.getValue() != null) { | ||||
|                 final List<User> userList = leftUsers.getValue(); | ||||
|                 match = userList.stream() | ||||
|                                 .filter(user -> user.getPk() == userId) | ||||
|                                 .findFirst() | ||||
|                                 .orElse(null); | ||||
|             } | ||||
|         } | ||||
|         return match; | ||||
|     } | ||||
| 
 | ||||
|     private void enqueueRequest(@NonNull final Call<DirectThreadBroadcastResponse> request, | ||||
|                                 @NonNull final MutableLiveData<Resource<DirectItem>> data, | ||||
|                                 @NonNull final DirectItem directItem) { | ||||
|  | ||||
| @ -173,28 +173,34 @@ | ||||
| 
 | ||||
|         </awais.instagrabber.customviews.ChatMessageLayout> | ||||
| 
 | ||||
|         <androidx.emoji.widget.EmojiAppCompatTextView | ||||
|             android:id="@+id/emojis" | ||||
|         <FrameLayout | ||||
|             android:id="@+id/reactions_wrapper" | ||||
|             android:layout_width="0dp" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="4dp" | ||||
|             android:layout_marginBottom="4dp" | ||||
|             android:background="@drawable/bg_rounded_corner" | ||||
|             android:elevation="1dp" | ||||
|             android:maxLines="1" | ||||
|             android:padding="4dp" | ||||
|             android:textColor="?android:textColorPrimary" | ||||
|             android:textSize="18sp" | ||||
|             android:paddingBottom="2dp" | ||||
|             android:translationY="@dimen/dm_reaction_translation_y_type_1" | ||||
|             android:visibility="gone" | ||||
|             app:layout_constraintBottom_toBottomOf="parent" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintHorizontal_bias="0" | ||||
|             app:layout_constraintStart_toStartOf="@id/chat_message_layout" | ||||
|             app:layout_constraintTop_toBottomOf="parent" | ||||
|             app:layout_constraintWidth_max="wrap" | ||||
|             tools:text="😀" | ||||
|             tools:visibility="visible" /> | ||||
|             tools:visibility="visible"> | ||||
| 
 | ||||
|             <awais.instagrabber.customviews.ReactionEmojiTextView | ||||
|                 android:id="@+id/emojis" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:background="@drawable/bg_rounded_corner" | ||||
|                 android:elevation="1dp" | ||||
|                 android:ellipsize="end" | ||||
|                 android:padding="4dp" | ||||
|                 android:singleLine="true" | ||||
|                 android:textColor="?android:textColorPrimary" | ||||
|                 android:textSize="18sp" | ||||
|                 tools:text="😀😀😀😀😀😀😀" /> | ||||
|         </FrameLayout> | ||||
| 
 | ||||
|         <!--<FrameLayout--> | ||||
|         <!--    android:id="@+id/reactions"--> | ||||
|  | ||||
| @ -78,12 +78,26 @@ | ||||
|         android:duplicateParentState="true" | ||||
|         android:visibility="gone" | ||||
|         app:layout_constraintBottom_toBottomOf="@id/profile_pic" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintEnd_toStartOf="@id/secondary_image" | ||||
|         app:layout_constraintStart_toEndOf="@id/info" | ||||
|         app:layout_constraintTop_toTopOf="@id/profile_pic" | ||||
|         app:srcCompat="@drawable/ic_circle_check" | ||||
|         app:tint="@color/ic_circle_check_tint" | ||||
|         tools:visibility="visible" /> | ||||
|         tools:visibility="gone" /> | ||||
| 
 | ||||
|     <androidx.appcompat.widget.AppCompatImageView | ||||
|         android:id="@+id/secondary_image" | ||||
|         android:layout_width="30dp" | ||||
|         android:layout_height="30dp" | ||||
|         android:layout_marginStart="4dp" | ||||
|         android:duplicateParentState="true" | ||||
|         android:visibility="gone" | ||||
|         app:layout_constraintBottom_toBottomOf="@id/profile_pic" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@id/select" | ||||
|         app:layout_constraintTop_toTopOf="@id/profile_pic" | ||||
|         tools:srcCompat="@mipmap/ic_launcher" | ||||
|         tools:visibility="gone" /> | ||||
| 
 | ||||
|     <include | ||||
|         layout="@layout/item_pref_divider" | ||||
|  | ||||
| @ -32,7 +32,7 @@ | ||||
|     <dimen name="dm_message_item_margin">80dp</dimen> | ||||
|     <dimen name="dm_message_item_avatar_size">48dp</dimen> | ||||
|     <dimen name="dm_message_info_padding_small">4dp</dimen> | ||||
|     <dimen name="dm_reaction_adjust_margin">22dp</dimen> | ||||
|     <dimen name="dm_reaction_adjust_margin">24dp</dimen> | ||||
|     <dimen name="dm_reaction_translation_y_type_1">6dp</dimen> | ||||
|     <dimen name="dm_reaction_translation_y_type_2">-12dp</dimen> | ||||
| 
 | ||||
|  | ||||
| @ -397,4 +397,5 @@ | ||||
|     <string name="edit_unsuccessful">Edit was unsuccessful</string> | ||||
|     <string name="message">Message</string> | ||||
|     <string name="reply">Reply</string> | ||||
|     <string name="tap_to_remove">Tap to remove</string> | ||||
| </resources> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user