move adding reactions to reactions item
This commit is contained in:
parent
9634db9061
commit
f50eac02d8
|
@ -223,7 +223,7 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
|
||||||
footer.rebind();
|
footer.rebind();
|
||||||
}else if(holder instanceof ExtendedFooterStatusDisplayItem.Holder footer && footer.getItem().status==s.getContentStatus()){
|
}else if(holder instanceof ExtendedFooterStatusDisplayItem.Holder footer && footer.getItem().status==s.getContentStatus()){
|
||||||
footer.rebind();
|
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();
|
reactions.rebind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,6 +417,10 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Status getMainStatus(){
|
||||||
|
return mainStatus;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isItemEnabled(String id){
|
public boolean isItemEnabled(String id){
|
||||||
return !id.equals(mainStatus.id) || !mainStatus.filterRevealed;
|
return !id.equals(mainStatus.id) || !mainStatus.filterRevealed;
|
||||||
|
|
|
@ -2,8 +2,14 @@ package org.joinmastodon.android.model;
|
||||||
|
|
||||||
import org.parceler.Parcel;
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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
|
@Parcel
|
||||||
public class EmojiReaction {
|
public class EmojiReaction {
|
||||||
public List<Account> accounts;
|
public List<Account> accounts;
|
||||||
|
@ -13,4 +19,38 @@ public class EmojiReaction {
|
||||||
public String name;
|
public String name;
|
||||||
public String url;
|
public String url;
|
||||||
public String staticUrl;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,16 @@ import android.graphics.drawable.Animatable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MotionEvent;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.R;
|
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.DeleteStatusReaction;
|
||||||
import org.joinmastodon.android.api.requests.statuses.PleromaAddStatusReaction;
|
import org.joinmastodon.android.api.requests.statuses.PleromaAddStatusReaction;
|
||||||
import org.joinmastodon.android.api.requests.statuses.PleromaDeleteStatusReaction;
|
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.events.StatusCountersUpdatedEvent;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.fragments.account_list.StatusEmojiReactionsListFragment;
|
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.EmojiReaction;
|
||||||
import org.joinmastodon.android.model.Status;
|
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.TextDrawable;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
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.Nav;
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
@ -50,23 +53,18 @@ import me.grishka.appkit.views.UsableRecyclerView;
|
||||||
public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
public final Status status;
|
public final Status status;
|
||||||
private final Drawable placeholder;
|
private final Drawable placeholder;
|
||||||
private List<ImageLoaderRequest> 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);
|
super(parentID, parentFragment);
|
||||||
this.status=status;
|
this.status=status;
|
||||||
|
this.hideAdd=hideAdd;
|
||||||
|
this.accountID=accountID;
|
||||||
placeholder=parentFragment.getContext().getDrawable(R.drawable.image_placeholder).mutate();
|
placeholder=parentFragment.getContext().getDrawable(R.drawable.image_placeholder).mutate();
|
||||||
placeholder.setBounds(0, 0, V.sp(24), V.sp(24));
|
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
|
@Override
|
||||||
public int getImageCount(){
|
public int getImageCount(){
|
||||||
return (int) status.reactions.stream().filter(r->r.url != null).count();
|
return (int) status.reactions.stream().filter(r->r.url != null).count();
|
||||||
|
@ -74,7 +72,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageLoaderRequest getImageRequest(int index){
|
public ImageLoaderRequest getImageRequest(int index){
|
||||||
return requests.get(index);
|
return status.reactions.get(index).request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,31 +80,119 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
return Type.EMOJI_REACTIONS;
|
return Type.EMOJI_REACTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Holder extends StatusDisplayItem.Holder<EmojiReactionsStatusDisplayItem> implements ImageLoaderViewHolder {
|
public static class Holder extends StatusDisplayItem.Holder<EmojiReactionsStatusDisplayItem> implements ImageLoaderViewHolder, CustomEmojiPopupKeyboard.Listener {
|
||||||
private final UsableRecyclerView list;
|
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) {
|
public Holder(Activity activity, ViewGroup parent) {
|
||||||
super(new UsableRecyclerView(activity) {
|
super(activity, R.layout.display_item_emoji_reactions, parent);
|
||||||
@Override
|
root=(LinearLayout) itemView;
|
||||||
public boolean onTouchEvent(MotionEvent e){
|
line=findViewById(R.id.line);
|
||||||
super.onTouchEvent(e);
|
list=findViewById(R.id.list);
|
||||||
// to pass through touch events (i.e. clicking the status) to the parent view
|
imgLoader=new ListImageLoaderWrapper(activity, list, new RecyclerViewDelegate(list), null);
|
||||||
return false;
|
list.setAdapter(adapter=new EmojiReactionsAdapter(this, imgLoader));
|
||||||
}
|
addButton=findViewById(R.id.add_btn);
|
||||||
});
|
addButton.setOnClickListener(this::onReactClick);
|
||||||
list=(UsableRecyclerView) itemView;
|
space=findViewById(R.id.space);
|
||||||
list.setPadding(V.dp(12), 0, V.dp(12), 0);
|
list.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false));
|
||||||
list.setClipToPadding(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(EmojiReactionsStatusDisplayItem item) {
|
public void onBind(EmojiReactionsStatusDisplayItem item) {
|
||||||
ListImageLoaderWrapper imgLoader=new ListImageLoaderWrapper(item.parentFragment.getContext(), list, new RecyclerViewDelegate(list), null);
|
if(emojiKeyboard != null) root.removeView(emojiKeyboard.getView());
|
||||||
list.setAdapter(new EmojiReactionsAdapter(this, imgLoader));
|
AccountSession session=item.parentFragment.getSession();
|
||||||
list.setLayoutManager(new LinearLayoutManager(item.parentFragment.getContext(), LinearLayoutManager.HORIZONTAL, false));
|
item.status.reactions.forEach(r->
|
||||||
item.refresh(this);
|
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<Status> 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<item.status.reactions.size(); i++){
|
||||||
|
EmojiReaction r=item.status.reactions.get(i);
|
||||||
|
if(r.name.equals(emoji)){
|
||||||
|
found=true;
|
||||||
|
r.add(me);
|
||||||
|
adapter.notifyItemChanged(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found){
|
||||||
|
item.status.reactions.add(info!=null ? EmojiReaction.of(info, me) : EmojiReaction.of(emoji, me));
|
||||||
|
adapter.notifyItemRangeInserted(item.status.reactions.size() - 1, 1);
|
||||||
|
}
|
||||||
|
E.post(new StatusCountersUpdatedEvent(item.status, adapter.parentHolder));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error) {
|
||||||
|
error.showToast(item.parentFragment.getContext());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec(item.accountID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackspace() {}
|
||||||
|
|
||||||
|
private void onReactClick(View v){
|
||||||
|
emojiKeyboard.toggleKeyboardPopup(null);
|
||||||
|
v.setSelected(emojiKeyboard.isVisible());
|
||||||
|
space.setVisibility(emojiKeyboard.isVisible() ? View.VISIBLE : View.GONE);
|
||||||
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||||
|
int[] locationOnScreen = new int[2];
|
||||||
|
((Activity) v.getContext()).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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setImage(int index, Drawable image){
|
public void setImage(int index, Drawable image){
|
||||||
View child=list.getChildAt(index);
|
View child=list.getChildAt(index);
|
||||||
|
@ -116,11 +202,11 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearImage(int index){
|
public void clearImage(int index){
|
||||||
|
if(item.status.reactions.get(index).url==null) return;
|
||||||
setImage(index, item.placeholder);
|
setImage(index, item.placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EmojiReactionsAdapter extends UsableRecyclerView.Adapter<EmojiReactionViewHolder> implements ImageLoaderRecyclerAdapter{
|
private class EmojiReactionsAdapter extends UsableRecyclerView.Adapter<EmojiReactionViewHolder> implements ImageLoaderRecyclerAdapter{
|
||||||
RecyclerView list;
|
|
||||||
ListImageLoaderWrapper imgLoader;
|
ListImageLoaderWrapper imgLoader;
|
||||||
Holder parentHolder;
|
Holder parentHolder;
|
||||||
|
|
||||||
|
@ -130,23 +216,18 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
this.imgLoader=imgLoader;
|
this.imgLoader=imgLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttachedToRecyclerView(@NonNull RecyclerView list){
|
|
||||||
super.onAttachedToRecyclerView(list);
|
|
||||||
this.list=list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public EmojiReactionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
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);
|
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);
|
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.setCompoundDrawableTintList(null);
|
||||||
btn.setBackgroundResource(R.drawable.bg_button_m3_tonal);
|
btn.setBackgroundResource(R.drawable.bg_button_m3_tonal);
|
||||||
btn.setCompoundDrawables(item.placeholder, null, null, null);
|
btn.setCompoundDrawables(item.placeholder, null, null, null);
|
||||||
return new EmojiReactionViewHolder(btn, item);
|
frame.addView(btn);
|
||||||
|
return new EmojiReactionViewHolder(frame, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -167,7 +248,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageLoaderRequest getImageRequest(int position, int image){
|
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){
|
public EmojiReactionViewHolder(@NonNull View itemView, EmojiReactionsStatusDisplayItem parent){
|
||||||
super(itemView);
|
super(itemView);
|
||||||
btn=(Button) itemView;
|
btn=(Button) ((FrameLayout) itemView).getChildAt(0);
|
||||||
this.parent=parent;
|
this.parent=parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +278,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
public void onBind(EmojiReaction item){
|
public void onBind(EmojiReaction item){
|
||||||
btn.setText(UiUtils.abbreviateNumber(item.count));
|
btn.setText(UiUtils.abbreviateNumber(item.count));
|
||||||
btn.setContentDescription(item.name);
|
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){
|
if(item.url==null){
|
||||||
Paint p=new Paint();
|
Paint p=new Paint();
|
||||||
p.setTextSize(V.sp(18));
|
p.setTextSize(V.sp(18));
|
||||||
|
@ -216,26 +297,25 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
req.setCallback(new Callback<>() {
|
req.setCallback(new Callback<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Status result) {
|
public void onSuccess(Status result) {
|
||||||
List<EmojiReaction> oldList=new ArrayList<>(parent.status.reactions);
|
|
||||||
parent.status.reactions.clear();
|
|
||||||
parent.status.reactions.addAll(result.reactions);
|
|
||||||
EmojiReactionsAdapter adapter = (EmojiReactionsAdapter) getBindingAdapter();
|
EmojiReactionsAdapter adapter = (EmojiReactionsAdapter) getBindingAdapter();
|
||||||
|
|
||||||
// this handles addition/removal of new reactions
|
for(int i=0; i<parent.status.reactions.size(); i++){
|
||||||
UiUtils.updateList(oldList, result.reactions, adapter.list, adapter,
|
EmojiReaction r=parent.status.reactions.get(i);
|
||||||
(e1, e2) -> e1.name.equals(e2.name));
|
if(!r.name.equals(item.name)) continue;
|
||||||
|
if(deleting && r.count==1) {
|
||||||
// update the existing reactions' counts
|
parent.status.reactions.remove(i);
|
||||||
for(int i=0; i<result.reactions.size(); i++){
|
adapter.notifyItemRemoved(i);
|
||||||
int index=i;
|
break;
|
||||||
EmojiReaction newReaction=result.reactions.get(index);
|
}
|
||||||
oldList.stream().filter(r->r.name.equals(newReaction.name)).findAny().ifPresent(r->{
|
r.me=!deleting;
|
||||||
if(newReaction.count!=r.count) adapter.notifyItemChanged(index);
|
if(deleting) r.count--;
|
||||||
});
|
else r.count++;
|
||||||
|
adapter.notifyItemChanged(i);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
parent.refresh(adapter.parentHolder);
|
|
||||||
adapter.imgLoader.updateImages();
|
E.post(new StatusCountersUpdatedEvent(parent.status, adapter.parentHolder));
|
||||||
E.post(new StatusCountersUpdatedEvent(result, adapter.parentHolder));
|
adapter.parentHolder.imgLoader.updateImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -249,7 +329,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
|
||||||
if (parent.parentFragment.isInstanceAkkoma()) {
|
if (parent.parentFragment.isInstanceAkkoma()) {
|
||||||
// glitch-soc doesn't have this, afaik
|
// glitch-soc doesn't have this, afaik
|
||||||
btn.setOnLongClickListener(e->{
|
btn.setOnLongClickListener(e->{
|
||||||
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();
|
Bundle args=new Bundle();
|
||||||
args.putString("account", parent.parentFragment.getAccountID());
|
args.putString("account", parent.parentFragment.getAccountID());
|
||||||
args.putString("statusID", parent.status.id);
|
args.putString("statusID", parent.status.id);
|
||||||
|
|
|
@ -6,9 +6,6 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -17,38 +14,26 @@ import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.view.animation.AlphaAnimation;
|
import android.view.animation.AlphaAnimation;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.joinmastodon.android.GlobalUserPreferences;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.R;
|
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.AccountSession;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.fragments.ComposeFragment;
|
import org.joinmastodon.android.fragments.ComposeFragment;
|
||||||
import org.joinmastodon.android.model.Emoji;
|
|
||||||
import org.joinmastodon.android.model.Instance;
|
import org.joinmastodon.android.model.Instance;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.model.StatusPrivacy;
|
import org.joinmastodon.android.model.StatusPrivacy;
|
||||||
import org.joinmastodon.android.ui.CustomEmojiPopupKeyboard;
|
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import me.grishka.appkit.Nav;
|
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.CubicBezierInterpolator;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
|
@ -69,14 +54,8 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
public static class Holder extends StatusDisplayItem.Holder<FooterStatusDisplayItem>{
|
||||||
private final FrameLayout reactLayout;
|
|
||||||
private final TextView replies, boosts, favorites;
|
private final TextView replies, boosts, favorites;
|
||||||
private final View reply, boost, favorite, share, bookmark, react;
|
private final View reply, boost, favorite, share, bookmark;
|
||||||
private final InputMethodManager imm;
|
|
||||||
private CustomEmojiPopupKeyboard emojiKeyboard;
|
|
||||||
private LinearLayout emojiKeyboardContainer;
|
|
||||||
private boolean reactKeyboardVisible;
|
|
||||||
private final Activity activity;
|
|
||||||
private static final Animation opacityOut, opacityIn;
|
private static final Animation opacityOut, opacityIn;
|
||||||
|
|
||||||
private View touchingView = null;
|
private View touchingView = null;
|
||||||
|
@ -112,10 +91,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(activity, R.layout.display_item_footer, 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);
|
replies=findViewById(R.id.reply);
|
||||||
boosts=findViewById(R.id.boost);
|
boosts=findViewById(R.id.boost);
|
||||||
|
@ -126,7 +101,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
favorite=findViewById(R.id.favorite_btn);
|
favorite=findViewById(R.id.favorite_btn);
|
||||||
share=findViewById(R.id.share_btn);
|
share=findViewById(R.id.share_btn);
|
||||||
bookmark=findViewById(R.id.bookmark_btn);
|
bookmark=findViewById(R.id.bookmark_btn);
|
||||||
react=findViewById(R.id.react_btn);
|
|
||||||
|
|
||||||
reply.setOnTouchListener(this::onButtonTouch);
|
reply.setOnTouchListener(this::onButtonTouch);
|
||||||
reply.setOnClickListener(this::onReplyClick);
|
reply.setOnClickListener(this::onReplyClick);
|
||||||
|
@ -140,9 +114,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
favorite.setOnClickListener(this::onFavoriteClick);
|
favorite.setOnClickListener(this::onFavoriteClick);
|
||||||
favorite.setOnLongClickListener(this::onFavoriteLongClick);
|
favorite.setOnLongClickListener(this::onFavoriteLongClick);
|
||||||
favorite.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
favorite.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
react.setOnTouchListener(this::onButtonTouch);
|
|
||||||
react.setOnClickListener(this::onReactClick);
|
|
||||||
react.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
|
||||||
bookmark.setOnTouchListener(this::onButtonTouch);
|
bookmark.setOnTouchListener(this::onButtonTouch);
|
||||||
bookmark.setOnClickListener(this::onBookmarkClick);
|
bookmark.setOnClickListener(this::onBookmarkClick);
|
||||||
bookmark.setOnLongClickListener(this::onBookmarkLongClick);
|
bookmark.setOnLongClickListener(this::onBookmarkLongClick);
|
||||||
|
@ -151,8 +122,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
share.setOnClickListener(this::onShareClick);
|
share.setOnClickListener(this::onShareClick);
|
||||||
share.setOnLongClickListener(this::onShareLongClick);
|
share.setOnLongClickListener(this::onShareLongClick);
|
||||||
share.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
share.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
|
|
||||||
imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -169,11 +138,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
bookmark.setSelected(item.status.bookmarked);
|
bookmark.setSelected(item.status.bookmarked);
|
||||||
boost.setEnabled(item.status.isReblogPermitted(item.accountID));
|
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;
|
int nextPos = getAbsoluteAdapterPosition() + 1;
|
||||||
boolean nextIsWarning = item.parentFragment.getDisplayItems().size() > nextPos &&
|
boolean nextIsWarning = item.parentFragment.getDisplayItems().size() > nextPos &&
|
||||||
item.parentFragment.getDisplayItems().get(nextPos) instanceof WarningFilteredStatusDisplayItem;
|
item.parentFragment.getDisplayItems().get(nextPos) instanceof WarningFilteredStatusDisplayItem;
|
||||||
|
@ -185,28 +149,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
condenseBottom ? V.dp(-5) : 0);
|
condenseBottom ? V.dp(-5) : 0);
|
||||||
|
|
||||||
itemView.requestLayout();
|
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){
|
private void bindText(TextView btn, long count){
|
||||||
|
@ -385,29 +327,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
return true;
|
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){
|
private void onBookmarkClick(View v){
|
||||||
bookmark.setSelected(!item.status.bookmarked);
|
bookmark.setSelected(!item.status.bookmarked);
|
||||||
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setBookmarked(item.status, !item.status.bookmarked, r->{
|
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;
|
return R.string.add_bookmark;
|
||||||
if(id==R.id.share_btn)
|
if(id==R.id.share_btn)
|
||||||
return R.string.button_share;
|
return R.string.button_share;
|
||||||
if(id==R.id.react_btn)
|
|
||||||
return R.string.sk_button_react;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEmojiReaction(String emoji) {
|
|
||||||
MastodonAPIRequest<Status> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,8 @@ public abstract class StatusDisplayItem{
|
||||||
items.addAll(contentItems);
|
items.addAll(contentItems);
|
||||||
}
|
}
|
||||||
if((flags & FLAG_NO_EMOJI_REACTIONS)==0 && AccountSessionManager.get(accountID).getLocalPreferences().emojiReactionsEnabled){
|
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){
|
if((flags & FLAG_NO_FOOTER)==0){
|
||||||
FooterStatusDisplayItem footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
|
FooterStatusDisplayItem footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
|
||||||
|
|
|
@ -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.AccountSession;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
|
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||||
import org.joinmastodon.android.model.Instance;
|
import org.joinmastodon.android.model.Instance;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.model.StatusPrivacy;
|
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().size() > nextPos){
|
||||||
if(item.parentFragment.getDisplayItems().get(nextPos) instanceof FooterStatusDisplayItem) bottomPadding=V.dp(6);
|
if(item.parentFragment.getDisplayItems().get(nextPos) instanceof FooterStatusDisplayItem) bottomPadding=V.dp(6);
|
||||||
if(item.parentFragment.getDisplayItems().get(nextPos) instanceof EmojiReactionsStatusDisplayItem){
|
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);
|
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), bottomPadding);
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/line"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/add_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:minWidth="48dp"
|
||||||
|
android:background="@drawable/bg_button_m3_tonal_circle"
|
||||||
|
android:tooltipText="@string/sk_button_react"
|
||||||
|
android:contentDescription="@string/sk_button_react"
|
||||||
|
android:src="@drawable/ic_fluent_add_24_filled" />
|
||||||
|
|
||||||
|
<org.joinmastodon.android.ui.views.EmojiReactionsRecyclerView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="-4dp"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:requiresFadingEdge="horizontal"
|
||||||
|
android:fadingEdgeLength="24dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:id="@+id/space"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -126,40 +126,6 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/react_layout"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/react_btn"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:paddingVertical="12dp">
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/react"
|
|
||||||
android:layout_width="24sp"
|
|
||||||
android:layout_height="24sp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginHorizontal="16dp"
|
|
||||||
android:src="@drawable/ic_fluent_emoji_laugh_24_regular"
|
|
||||||
android:tint="@color/bookmark_icon"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:textAppearance="@style/m3_label_large" />
|
|
||||||
</FrameLayout>
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone">
|
|
||||||
<EditText
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="20dp"
|
|
||||||
android:focusable="true"
|
|
||||||
android:focusableInTouchMode="true"
|
|
||||||
android:id="@+id/react_input"/>
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
Loading…
Reference in New Issue