From f50eac02d8aa5f0791ea8de9d468926678a86f3c Mon Sep 17 00:00:00 2001 From: sk Date: Mon, 21 Aug 2023 22:40:00 +0200 Subject: [PATCH] move adding reactions to reactions item --- .../android/fragments/StatusListFragment.java | 2 +- .../android/fragments/ThreadFragment.java | 4 + .../android/model/EmojiReaction.java | 40 ++++ .../EmojiReactionsStatusDisplayItem.java | 210 ++++++++++++------ .../displayitems/FooterStatusDisplayItem.java | 105 +-------- .../ui/displayitems/StatusDisplayItem.java | 3 +- .../displayitems/TextStatusDisplayItem.java | 4 +- .../ui/views/EmojiReactionsRecyclerView.java | 44 ++++ .../layout/display_item_emoji_reactions.xml | 43 ++++ .../main/res/layout/display_item_footer.xml | 34 --- 10 files changed, 283 insertions(+), 206 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/ui/views/EmojiReactionsRecyclerView.java create mode 100644 mastodon/src/main/res/layout/display_item_emoji_reactions.xml diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java index 14718da16..701b8959e 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java @@ -223,7 +223,7 @@ public abstract class StatusListFragment extends BaseStatusListFragment footer.rebind(); }else if(holder instanceof ExtendedFooterStatusDisplayItem.Holder footer && footer.getItem().status==s.getContentStatus()){ footer.rebind(); - }else if(holder instanceof EmojiReactionsStatusDisplayItem.Holder reactions && ev.viewHolder!=holder){ + }else if(holder instanceof EmojiReactionsStatusDisplayItem.Holder reactions && reactions.getItem().status==s.getContentStatus() && ev.viewHolder!=holder){ reactions.rebind(); } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java index fc1edcca1..31a981a7a 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java @@ -417,6 +417,10 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist adapter.notifyDataSetChanged(); } + public Status getMainStatus(){ + return mainStatus; + } + @Override public boolean isItemEnabled(String id){ return !id.equals(mainStatus.id) || !mainStatus.filterRevealed; diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/EmojiReaction.java b/mastodon/src/main/java/org/joinmastodon/android/model/EmojiReaction.java index ed73d31a8..a0fa142a9 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/EmojiReaction.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/EmojiReaction.java @@ -2,8 +2,14 @@ package org.joinmastodon.android.model; import org.parceler.Parcel; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import me.grishka.appkit.imageloader.requests.ImageLoaderRequest; +import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest; +import me.grishka.appkit.utils.V; + @Parcel public class EmojiReaction { public List accounts; @@ -13,4 +19,38 @@ public class EmojiReaction { public String name; public String url; public String staticUrl; + + public transient ImageLoaderRequest request; + + public static EmojiReaction of(Emoji info, Account me){ + EmojiReaction reaction=new EmojiReaction(); + reaction.me=true; + reaction.count=1; + reaction.name=info.shortcode; + reaction.url=info.url; + reaction.staticUrl=info.staticUrl; + reaction.accounts=new ArrayList<>(Collections.singleton(me)); + reaction.accountIds=new ArrayList<>(Collections.singleton(me.id)); + reaction.request=new UrlImageLoaderRequest(info.url, V.sp(24), V.sp(24)); + return reaction; + } + + public static EmojiReaction of(String emoji, Account me){ + EmojiReaction reaction=new EmojiReaction(); + reaction.me=true; + reaction.count=1; + reaction.name=emoji; + reaction.accounts=new ArrayList<>(Collections.singleton(me)); + reaction.accountIds=new ArrayList<>(Collections.singleton(me.id)); + return reaction; + } + + public void add(Account self){ + if(accounts==null) accounts=new ArrayList<>(); + if(accountIds==null) accountIds=new ArrayList<>(); + count++; + me=true; + accounts.add(self); + accountIds.add(self.id); + } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java index 3690e3bb7..c5dd6d89e 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java @@ -6,14 +6,16 @@ import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.view.MotionEvent; +import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import org.joinmastodon.android.E; import org.joinmastodon.android.R; @@ -22,18 +24,19 @@ import org.joinmastodon.android.api.requests.statuses.AddStatusReaction; import org.joinmastodon.android.api.requests.statuses.DeleteStatusReaction; import org.joinmastodon.android.api.requests.statuses.PleromaAddStatusReaction; import org.joinmastodon.android.api.requests.statuses.PleromaDeleteStatusReaction; +import org.joinmastodon.android.api.session.AccountSession; +import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.events.StatusCountersUpdatedEvent; import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.account_list.StatusEmojiReactionsListFragment; +import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.Emoji; import org.joinmastodon.android.model.EmojiReaction; import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.CustomEmojiPopupKeyboard; import org.joinmastodon.android.ui.utils.TextDrawable; import org.joinmastodon.android.ui.utils.UiUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - import me.grishka.appkit.Nav; import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.ErrorResponse; @@ -50,23 +53,18 @@ import me.grishka.appkit.views.UsableRecyclerView; public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { public final Status status; private final Drawable placeholder; - private List requests; + private final boolean hideAdd; + private final String accountID; - public EmojiReactionsStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status) { + public EmojiReactionsStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, String accountID, boolean hideAdd) { super(parentID, parentFragment); this.status=status; + this.hideAdd=hideAdd; + this.accountID=accountID; placeholder=parentFragment.getContext().getDrawable(R.drawable.image_placeholder).mutate(); placeholder.setBounds(0, 0, V.sp(24), V.sp(24)); } - private void refresh(Holder holder) { - requests=status.reactions.stream() - .map(e->e.url!=null ? new UrlImageLoaderRequest(e.url, V.sp(24), V.sp(24)) : null) - .collect(Collectors.toList()); - holder.list.setPadding(holder.list.getPaddingLeft(), - status.reactions.isEmpty() ? 0 : V.dp(8), holder.list.getPaddingRight(), 0); - } - @Override public int getImageCount(){ return (int) status.reactions.stream().filter(r->r.url != null).count(); @@ -74,7 +72,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { @Override public ImageLoaderRequest getImageRequest(int index){ - return requests.get(index); + return status.reactions.get(index).request; } @Override @@ -82,31 +80,119 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { return Type.EMOJI_REACTIONS; } - public static class Holder extends StatusDisplayItem.Holder implements ImageLoaderViewHolder { - private final UsableRecyclerView list; + public static class Holder extends StatusDisplayItem.Holder implements ImageLoaderViewHolder, CustomEmojiPopupKeyboard.Listener { + private final UsableRecyclerView list; + private final LinearLayout root, line; + private CustomEmojiPopupKeyboard emojiKeyboard; + private final View space; + private final ImageButton addButton; + private final EmojiReactionsAdapter adapter; + private final ListImageLoaderWrapper imgLoader; public Holder(Activity activity, ViewGroup parent) { - super(new UsableRecyclerView(activity) { - @Override - public boolean onTouchEvent(MotionEvent e){ - super.onTouchEvent(e); - // to pass through touch events (i.e. clicking the status) to the parent view - return false; - } - }); - list=(UsableRecyclerView) itemView; - list.setPadding(V.dp(12), 0, V.dp(12), 0); - list.setClipToPadding(false); + super(activity, R.layout.display_item_emoji_reactions, parent); + root=(LinearLayout) itemView; + line=findViewById(R.id.line); + list=findViewById(R.id.list); + imgLoader=new ListImageLoaderWrapper(activity, list, new RecyclerViewDelegate(list), null); + list.setAdapter(adapter=new EmojiReactionsAdapter(this, imgLoader)); + addButton=findViewById(R.id.add_btn); + addButton.setOnClickListener(this::onReactClick); + space=findViewById(R.id.space); + list.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)); } @Override public void onBind(EmojiReactionsStatusDisplayItem item) { - ListImageLoaderWrapper imgLoader=new ListImageLoaderWrapper(item.parentFragment.getContext(), list, new RecyclerViewDelegate(list), null); - list.setAdapter(new EmojiReactionsAdapter(this, imgLoader)); - list.setLayoutManager(new LinearLayoutManager(item.parentFragment.getContext(), LinearLayoutManager.HORIZONTAL, false)); - item.refresh(this); + if(emojiKeyboard != null) root.removeView(emojiKeyboard.getView()); + AccountSession session=item.parentFragment.getSession(); + item.status.reactions.forEach(r-> + r.request=r.url != null ? new UrlImageLoaderRequest(r.url, V.sp(24), V.sp(24)) : null); + emojiKeyboard=new CustomEmojiPopupKeyboard( + (Activity) item.parentFragment.getContext(), + AccountSessionManager.getInstance().getCustomEmojis(session.domain), + session.domain, true); + emojiKeyboard.setListener(this); + space.setVisibility(View.GONE); + root.addView(emojiKeyboard.getView()); + boolean nothingToShow=item.status.reactions.isEmpty() && item.hideAdd; + root.setVisibility(nothingToShow ? View.GONE : View.VISIBLE); + line.setVisibility(nothingToShow ? View.GONE : View.VISIBLE); + line.setPadding(list.getPaddingLeft(), nothingToShow ? 0 : V.dp(8), list.getPaddingRight(), 0); + imgLoader.updateImages(); + adapter.notifyDataSetChanged(); } + private void hideEmojiKeyboard(){ + space.setVisibility(View.GONE); + addButton.setSelected(false); + if(emojiKeyboard.isVisible()) emojiKeyboard.toggleKeyboardPopup(null); + } + + @Override + public void onEmojiSelected(Emoji emoji) { + addEmojiReaction(emoji.shortcode, emoji); + hideEmojiKeyboard(); + } + + @Override + public void onEmojiSelected(String emoji){ + addEmojiReaction(emoji, null); + hideEmojiKeyboard(); + } + + private void addEmojiReaction(String emoji, Emoji info) { + if(item.status.reactions.stream().filter(r->r.name.equals(emoji) && r.me).findAny().isPresent()) return; + + MastodonAPIRequest req = item.parentFragment.isInstanceAkkoma() + ? new PleromaAddStatusReaction(item.status.id, emoji) + : new AddStatusReaction(item.status.id, emoji); + req.setCallback(new Callback<>() { + @Override + public void onSuccess(Status result) { + Account me=AccountSessionManager.get(item.accountID).self; + boolean found=false; + for(int i=0; i 0.75) { + item.parentFragment.scrollBy(0, (int) (displayMetrics.heightPixels * 0.3)); + } + } + @Override public void setImage(int index, Drawable image){ View child=list.getChildAt(index); @@ -116,11 +202,11 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { @Override public void clearImage(int index){ + if(item.status.reactions.get(index).url==null) return; setImage(index, item.placeholder); } private class EmojiReactionsAdapter extends UsableRecyclerView.Adapter implements ImageLoaderRecyclerAdapter{ - RecyclerView list; ListImageLoaderWrapper imgLoader; Holder parentHolder; @@ -130,23 +216,18 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { this.imgLoader=imgLoader; } - @Override - public void onAttachedToRecyclerView(@NonNull RecyclerView list){ - super.onAttachedToRecyclerView(list); - this.list=list; - } - @NonNull @Override public EmojiReactionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){ + FrameLayout frame=new FrameLayout(parent.getContext()); + frame.setPaddingRelative(0, 0, V.dp(8), 0); Button btn=new Button(parent.getContext(), null, 0, R.style.Widget_Mastodon_M3_Button_Outlined_Icon); ViewGroup.MarginLayoutParams params=new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - params.setMarginEnd(V.dp(8)); - btn.setLayoutParams(params); btn.setCompoundDrawableTintList(null); btn.setBackgroundResource(R.drawable.bg_button_m3_tonal); btn.setCompoundDrawables(item.placeholder, null, null, null); - return new EmojiReactionViewHolder(btn, item); + frame.addView(btn); + return new EmojiReactionViewHolder(frame, item); } @Override @@ -167,7 +248,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { @Override public ImageLoaderRequest getImageRequest(int position, int image){ - return item.requests.get(position); + return item.status.reactions.get(position).request; } } @@ -177,7 +258,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { public EmojiReactionViewHolder(@NonNull View itemView, EmojiReactionsStatusDisplayItem parent){ super(itemView); - btn=(Button) itemView; + btn=(Button) ((FrameLayout) itemView).getChildAt(0); this.parent=parent; } @@ -197,7 +278,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { public void onBind(EmojiReaction item){ btn.setText(UiUtils.abbreviateNumber(item.count)); btn.setContentDescription(item.name); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)btn.setTooltipText(item.name); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) btn.setTooltipText(item.name); if(item.url==null){ Paint p=new Paint(); p.setTextSize(V.sp(18)); @@ -216,26 +297,25 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { req.setCallback(new Callback<>() { @Override public void onSuccess(Status result) { - List oldList=new ArrayList<>(parent.status.reactions); - parent.status.reactions.clear(); - parent.status.reactions.addAll(result.reactions); EmojiReactionsAdapter adapter = (EmojiReactionsAdapter) getBindingAdapter(); - // this handles addition/removal of new reactions - UiUtils.updateList(oldList, result.reactions, adapter.list, adapter, - (e1, e2) -> e1.name.equals(e2.name)); - - // update the existing reactions' counts - for(int i=0; ir.name.equals(newReaction.name)).findAny().ifPresent(r->{ - if(newReaction.count!=r.count) adapter.notifyItemChanged(index); - }); + for(int i=0; i{ - EmojiReaction emojiReaction=parent.status.reactions.stream().filter(r->r.name.equals(item.name)).findAny().orElseThrow(); + EmojiReaction emojiReaction=parent.status.reactions.get(getAbsoluteAdapterPosition()); Bundle args=new Bundle(); args.putString("account", parent.parentFragment.getAccountID()); args.putString("statusID", parent.status.id); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java index b1861ac70..b4196d622 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java @@ -6,9 +6,6 @@ import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -17,38 +14,26 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; -import android.view.inputmethod.InputMethodManager; import android.widget.Button; -import android.widget.EditText; import android.widget.FrameLayout; -import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; -import org.joinmastodon.android.api.MastodonAPIRequest; -import org.joinmastodon.android.api.requests.statuses.AddStatusReaction; -import org.joinmastodon.android.api.requests.statuses.PleromaAddStatusReaction; import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.ComposeFragment; -import org.joinmastodon.android.model.Emoji; import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.StatusPrivacy; -import org.joinmastodon.android.ui.CustomEmojiPopupKeyboard; import org.joinmastodon.android.ui.M3AlertDialogBuilder; import org.joinmastodon.android.ui.utils.UiUtils; import org.parceler.Parcels; import java.util.function.Consumer; -import java.util.regex.Pattern; import me.grishka.appkit.Nav; -import me.grishka.appkit.api.Callback; -import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.utils.CubicBezierInterpolator; import me.grishka.appkit.utils.V; @@ -69,14 +54,8 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ } public static class Holder extends StatusDisplayItem.Holder{ - private final FrameLayout reactLayout; private final TextView replies, boosts, favorites; - private final View reply, boost, favorite, share, bookmark, react; - private final InputMethodManager imm; - private CustomEmojiPopupKeyboard emojiKeyboard; - private LinearLayout emojiKeyboardContainer; - private boolean reactKeyboardVisible; - private final Activity activity; + private final View reply, boost, favorite, share, bookmark; private static final Animation opacityOut, opacityIn; private View touchingView = null; @@ -112,10 +91,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ public Holder(Activity activity, ViewGroup parent){ super(activity, R.layout.display_item_footer, parent); - this.activity = activity; - - reactLayout=findViewById(R.id.react_layout); - emojiKeyboardContainer=findViewById(R.id.footer_emoji_keyboard_container); replies=findViewById(R.id.reply); boosts=findViewById(R.id.boost); @@ -126,7 +101,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ favorite=findViewById(R.id.favorite_btn); share=findViewById(R.id.share_btn); bookmark=findViewById(R.id.bookmark_btn); - react=findViewById(R.id.react_btn); reply.setOnTouchListener(this::onButtonTouch); reply.setOnClickListener(this::onReplyClick); @@ -140,9 +114,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ favorite.setOnClickListener(this::onFavoriteClick); favorite.setOnLongClickListener(this::onFavoriteLongClick); favorite.setAccessibilityDelegate(buttonAccessibilityDelegate); - react.setOnTouchListener(this::onButtonTouch); - react.setOnClickListener(this::onReactClick); - react.setAccessibilityDelegate(buttonAccessibilityDelegate); bookmark.setOnTouchListener(this::onButtonTouch); bookmark.setOnClickListener(this::onBookmarkClick); bookmark.setOnLongClickListener(this::onBookmarkLongClick); @@ -151,8 +122,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ share.setOnClickListener(this::onShareClick); share.setOnLongClickListener(this::onShareLongClick); share.setAccessibilityDelegate(buttonAccessibilityDelegate); - - imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); } @Override @@ -169,11 +138,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ bookmark.setSelected(item.status.bookmarked); boost.setEnabled(item.status.isReblogPermitted(item.accountID)); - AccountSession accountSession=AccountSessionManager.get(item.accountID); - reactLayout.setVisibility(accountSession.getLocalPreferences().emojiReactionsEnabled - ? View.VISIBLE - : View.GONE); - int nextPos = getAbsoluteAdapterPosition() + 1; boolean nextIsWarning = item.parentFragment.getDisplayItems().size() > nextPos && item.parentFragment.getDisplayItems().get(nextPos) instanceof WarningFilteredStatusDisplayItem; @@ -185,28 +149,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ condenseBottom ? V.dp(-5) : 0); itemView.requestLayout(); - - reactKeyboardVisible=false; - emojiKeyboard=new CustomEmojiPopupKeyboard(activity, AccountSessionManager.getInstance().getCustomEmojis(accountSession.domain), accountSession.domain, true); - emojiKeyboard.setListener(new CustomEmojiPopupKeyboard.Listener(){ - @Override - public void onEmojiSelected(Emoji emoji) { - addEmojiReaction(emoji.shortcode); - emojiKeyboard.toggleKeyboardPopup(null); - } - - @Override - public void onEmojiSelected(String emoji){ - addEmojiReaction(emoji); - emojiKeyboard.toggleKeyboardPopup(null); - } - - @Override - public void onBackspace() {} - }); - - emojiKeyboardContainer.removeAllViews(); - emojiKeyboardContainer.addView(emojiKeyboard.getView()); } private void bindText(TextView btn, long count){ @@ -385,29 +327,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ return true; } - private boolean resetReact(View v){ - if(!reactKeyboardVisible) return false; - if(emojiKeyboard.isVisible()) emojiKeyboard.toggleKeyboardPopup(null); - reactKeyboardVisible=false; - v.setAlpha(1); - v.startAnimation(opacityIn); - return true; - } - - private void onReactClick(View v){ - if (resetReact(v)) return; - reactKeyboardVisible=true; - emojiKeyboard.toggleKeyboardPopup(null); - DisplayMetrics displayMetrics = new DisplayMetrics(); - int[] locationOnScreen = new int[2]; - activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); - v.getLocationOnScreen(locationOnScreen); - double fromScreenTop = (double) locationOnScreen[1] / displayMetrics.heightPixels; - if (fromScreenTop > 0.75) { - item.parentFragment.scrollBy(0, (int) (displayMetrics.heightPixels * 0.3)); - } - } - private void onBookmarkClick(View v){ bookmark.setSelected(!item.status.bookmarked); AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setBookmarked(item.status, !item.status.bookmarked, r->{ @@ -453,29 +372,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ return R.string.add_bookmark; if(id==R.id.share_btn) return R.string.button_share; - if(id==R.id.react_btn) - return R.string.sk_button_react; return 0; } - - private void addEmojiReaction(String emoji) { - MastodonAPIRequest req = item.parentFragment.isInstanceAkkoma() - ? new PleromaAddStatusReaction(item.status.id, emoji) - : new AddStatusReaction(item.status.id, emoji); - req.setCallback(new Callback<>() { - @Override - public void onSuccess(Status result) { - item.parentFragment.updateEmojiReactions(result, getItemID()); - } - - @Override - public void onError(ErrorResponse error) { - error.showToast(item.parentFragment.getContext()); - } - }) - .exec(item.accountID); - reactKeyboardVisible=false; - react.startAnimation(opacityIn); - } } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index 5a905f7f9..6ee911d46 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -291,7 +291,8 @@ public abstract class StatusDisplayItem{ items.addAll(contentItems); } if((flags & FLAG_NO_EMOJI_REACTIONS)==0 && AccountSessionManager.get(accountID).getLocalPreferences().emojiReactionsEnabled){ - items.add(new EmojiReactionsStatusDisplayItem(parentID, fragment, statusForContent)); + boolean isMainStatus=fragment instanceof ThreadFragment t && t.getMainStatus().id.equals(statusForContent.id); + items.add(new EmojiReactionsStatusDisplayItem(parentID, fragment, statusForContent, accountID, !isMainStatus)); } if((flags & FLAG_NO_FOOTER)==0){ FooterStatusDisplayItem footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java index 9703bf623..23d3ed04d 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java @@ -21,6 +21,7 @@ import org.joinmastodon.android.api.requests.statuses.TranslateStatus; import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.fragments.BaseStatusListFragment; +import org.joinmastodon.android.fragments.ThreadFragment; import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.StatusPrivacy; @@ -199,7 +200,8 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ if(item.parentFragment.getDisplayItems().size() > nextPos){ if(item.parentFragment.getDisplayItems().get(nextPos) instanceof FooterStatusDisplayItem) bottomPadding=V.dp(6); if(item.parentFragment.getDisplayItems().get(nextPos) instanceof EmojiReactionsStatusDisplayItem){ - bottomPadding=item.status.reactions.isEmpty() ? V.dp(6) : 0; + boolean reactionsHidden=item.status.reactions.isEmpty() && !(item.parentFragment instanceof ThreadFragment); + bottomPadding=reactionsHidden ? V.dp(6) : 0; } } itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), bottomPadding); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/views/EmojiReactionsRecyclerView.java b/mastodon/src/main/java/org/joinmastodon/android/ui/views/EmojiReactionsRecyclerView.java new file mode 100644 index 000000000..eaba1f6f5 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/views/EmojiReactionsRecyclerView.java @@ -0,0 +1,44 @@ +package org.joinmastodon.android.ui.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import me.grishka.appkit.views.UsableRecyclerView; + +public class EmojiReactionsRecyclerView extends UsableRecyclerView{ + public EmojiReactionsRecyclerView(Context context){ + super(context); + } + + public EmojiReactionsRecyclerView(Context context, AttributeSet attrs){ + super(context, attrs); + } + + public EmojiReactionsRecyclerView(Context context, AttributeSet attrs, int defStyle){ + super(context, attrs, defStyle); + } + + @Override + public boolean onTouchEvent(MotionEvent e){ + super.onTouchEvent(e); + // to pass through touch events (i.e. clicking the status) to the parent view + return false; + } + + // https://stackoverflow.com/questions/55372837/is-there-a-way-to-make-recyclerview-requiresfadingedge-unaffected-by-paddingtop + @Override + protected boolean isPaddingOffsetRequired() { + return true; + } + + @Override + protected int getLeftPaddingOffset(){ + return -getPaddingLeft(); + } + + @Override + protected int getRightPaddingOffset() { + return getPaddingRight(); + } +} diff --git a/mastodon/src/main/res/layout/display_item_emoji_reactions.xml b/mastodon/src/main/res/layout/display_item_emoji_reactions.xml new file mode 100644 index 000000000..3c895c8b8 --- /dev/null +++ b/mastodon/src/main/res/layout/display_item_emoji_reactions.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/mastodon/src/main/res/layout/display_item_footer.xml b/mastodon/src/main/res/layout/display_item_footer.xml index 93007cce1..b63a32e1f 100644 --- a/mastodon/src/main/res/layout/display_item_footer.xml +++ b/mastodon/src/main/res/layout/display_item_footer.xml @@ -126,40 +126,6 @@ - - - - - - - - -