Commit 3e90ac4b authored by Thomas's avatar Thomas
Browse files

Merge pull request 'Add support for Nyastodon-style emoji reactions' (#789)...

Merge pull request 'Add support for Nyastodon-style emoji reactions' (#789) from skyevg/Fedilab:develop into develop

Reviewed-on: https://codeberg.org/tom79/Fedilab/pulls/789
parents c29a2bd0 4d92dc1f
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -318,4 +318,18 @@ public interface MastodonStatusesService {
            @Header("Authorization") String token,
            @Path("id") String id
    );

    @POST("statuses/{id}/react/{name}")
    Call<Void> addReaction(
            @Header("Authorization") String app_token,
            @Path("id") String id,
            @Path("name") String name
    );

    @POST("statuses/{id}/unreact/{name}")
    Call<Void> removeReaction(
            @Header("Authorization") String app_token,
            @Path("id") String id,
            @Path("name") String name
    );
}
+2 −0
Original line number Diff line number Diff line
@@ -109,6 +109,8 @@ public class Status implements Serializable, Cloneable {
    public boolean cached = false;
    @SerializedName("is_maths")
    public Boolean isMaths;
    @SerializedName("reactions")
    public List<Reaction> reactions;

    public Attachment art_attachment;
    public boolean isExpended = false;
+27 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import app.fedilab.android.mastodon.client.entities.api.Reaction;
import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.helper.ThemeHelper;
import app.fedilab.android.mastodon.viewmodel.mastodon.AnnouncementsVM;
import app.fedilab.android.mastodon.viewmodel.mastodon.StatusesVM;
import app.fedilab.android.mastodon.viewmodel.pleroma.ActionsVM;


@@ -46,18 +47,29 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
    private final List<Reaction> reactions;
    private final String announcementId;
    private final boolean statusReaction;
    private final boolean isPleroma;
    private Context context;


    ReactionAdapter(String announcementId, List<Reaction> reactions, boolean statusReaction, boolean isPleroma) {
        this.reactions = reactions;
        this.announcementId = announcementId;
        this.statusReaction = statusReaction;
        this.isPleroma = isPleroma;
    }

    ReactionAdapter(String announcementId, List<Reaction> reactions, boolean statusReaction) {
        this.reactions = reactions;
        this.announcementId = announcementId;
        this.statusReaction = statusReaction;
        this.isPleroma = true;
    }

    ReactionAdapter(String announcementId, List<Reaction> reactions) {
        this.reactions = reactions;
        this.announcementId = announcementId;
        this.statusReaction = false;
        this.isPleroma = true;
    }

    @NonNull
@@ -101,7 +113,7 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
                }
                notifyItemChanged(position);
            });
        } else {
        } else if (isPleroma) {
            ActionsVM actionVM = new ViewModelProvider((ViewModelStoreOwner) context).get(ActionsVM.class);
            holder.binding.reactionContainer.setOnClickListener(v -> {
                if (reaction.me) {
@@ -115,6 +127,20 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
                }
                notifyItemChanged(position);
            });
        } else {
            StatusesVM statusesVM = new ViewModelProvider((ViewModelStoreOwner) context).get(StatusesVM.class);
            holder.binding.reactionContainer.setOnClickListener(v -> {
                if (reaction.me) {
                    statusesVM.removeReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, announcementId, reaction.name);
                    reaction.me = false;
                    reaction.count -= 1;
                } else {
                    statusesVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, announcementId, reaction.name);
                    reaction.me = true;
                    reaction.count += 1;
                }
                notifyItemChanged(position);
            });
        }
    }

+108 −48
Original line number Diff line number Diff line
@@ -522,7 +522,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
            holder.binding.quotedMessage.cardviewContainer.setVisibility(View.GONE);
        }

        if (currentAccount != null && currentAccount.api == Account.API.PLEROMA) {
        if (currentAccount != null && currentAccount.api == Account.API.PLEROMA || status.reactions != null) {
            if (status.pleroma != null && status.pleroma.emoji_reactions != null && status.pleroma.emoji_reactions.size() > 0) {
                holder.binding.layoutReactions.getRoot().setVisibility(View.VISIBLE);
                ReactionAdapter reactionAdapter = new ReactionAdapter(status.id, status.pleroma.emoji_reactions, true);
@@ -530,6 +530,13 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                LinearLayoutManager layoutManager
                        = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
                holder.binding.layoutReactions.reactionsView.setLayoutManager(layoutManager);
            } else if (status.reactions != null && status.reactions.size() > 0) {
                holder.binding.layoutReactions.getRoot().setVisibility(View.VISIBLE);
                ReactionAdapter reactionAdapter = new ReactionAdapter(status.id, status.reactions, true, false);
                holder.binding.layoutReactions.reactionsView.setAdapter(reactionAdapter);
                LinearLayoutManager layoutManager
                        = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
                holder.binding.layoutReactions.reactionsView.setLayoutManager(layoutManager);
            } else {
                holder.binding.layoutReactions.getRoot().setVisibility(View.GONE);
                holder.binding.layoutReactions.reactionsView.setAdapter(null);
@@ -542,9 +549,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                        }).setOnEmojiClickListener((emoji, imageView) -> {
                            String emojiStr = imageView.getUnicode();
                            boolean alreadyAdded = false;
                            if (status.pleroma == null || status.pleroma.emoji_reactions == null) {
                                return;
                            }
                            if (status.pleroma != null && status.pleroma.emoji_reactions != null) {
                                for (Reaction reaction : status.pleroma.emoji_reactions) {
                                    if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
                                        alreadyAdded = true;
@@ -570,6 +575,32 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                                } else {
                                    actionVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
                                }
                            } else if (status.reactions != null) {
                                for (Reaction reaction : status.reactions) {
                                    if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
                                        alreadyAdded = true;
                                        reaction.count = (reaction.count - 1);
                                        if (reaction.count == 0) {
                                            status.reactions.remove(reaction);
                                        }
                                        adapter.notifyItemChanged(holder.getBindingAdapterPosition());
                                        break;
                                    }
                                }
                                if (!alreadyAdded) {
                                    Reaction reaction = new Reaction();
                                    reaction.me = true;
                                    reaction.count = 1;
                                    reaction.name = emojiStr;
                                    status.reactions.add(0, reaction);
                                    adapter.notifyItemChanged(holder.getBindingAdapterPosition());
                                }
                                if (alreadyAdded) {
                                    statusesVM.removeReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
                                } else {
                                    statusesVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
                                }
                            }
                        })
                        .build(holder.binding.layoutReactions.fakeEdittext);
                emojiPopup.toggle();
@@ -594,6 +625,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                        String url = emojis.get(BaseMainActivity.currentInstance).get(index).url;
                        String static_url = emojis.get(BaseMainActivity.currentInstance).get(index).static_url;
                        boolean alreadyAdded = false;
                        if (status.pleroma != null && status.pleroma.emoji_reactions != null) {
                            for (Reaction reaction : status.pleroma.emoji_reactions) {
                                if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
                                    alreadyAdded = true;
@@ -621,6 +653,34 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
                            } else {
                                actionsVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
                            }
                        } else if (status.reactions != null) {
                            for (Reaction reaction : status.reactions) {
                                if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) {
                                    alreadyAdded = true;
                                    reaction.count = (reaction.count - 1);
                                    if (reaction.count == 0) {
                                        status.reactions.remove(reaction);
                                    }
                                    adapter.notifyItemChanged(holder.getBindingAdapterPosition());
                                    break;
                                }
                            }
                            if (!alreadyAdded) {
                                Reaction reaction = new Reaction();
                                reaction.me = true;
                                reaction.count = 1;
                                reaction.name = emojiStr;
                                reaction.url = url;
                                reaction.static_url = static_url;
                                status.reactions.add(0, reaction);
                                adapter.notifyItemChanged(holder.getBindingAdapterPosition());
                            }
                            if (alreadyAdded) {
                                statusesVM.removeReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
                            } else {
                                statusesVM.addReaction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.id, emojiStr);
                            }
                        }
                    });
                    gridView.setPadding(paddingDp, paddingDp, paddingDp, paddingDp);
                    builder.setView(gridView);
+44 −0
Original line number Diff line number Diff line
@@ -1292,4 +1292,48 @@ public class StatusesVM extends AndroidViewModel {
        }).start();
        return voidMutableLiveData;
    }

    /**
     * React to a status with an emoji.
     *
     * @param instance Instance domain of the active account
     * @param token    Access token of the active account
     * @param id       Local ID of an announcement
     * @param name     Unicode emoji, or shortcode of custom emoji
     */
    public void addReaction(@NonNull String instance, String token, @NonNull String id, @NonNull String name) {
        MastodonStatusesService mastodonStatusesService = init(instance);
        new Thread(() -> {
            Call<Void> addReactionCall = mastodonStatusesService.addReaction(token, id, name);
            if (addReactionCall != null) {
                try {
                    addReactionCall.execute();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * Undo a react emoji to a status.
     *
     * @param instance Instance domain of the active account
     * @param token    Access token of the active account
     * @param id       Local ID of an announcement
     * @param name     Unicode emoji, or shortcode of custom emoji
     */
    public void removeReaction(@NonNull String instance, String token, @NonNull String id, @NonNull String name) {
        MastodonStatusesService mastodonStatusesService = init(instance);
        new Thread(() -> {
            Call<Void> removeReactionCall = mastodonStatusesService.removeReaction(token, id, name);
            if (removeReactionCall != null) {
                try {
                    removeReactionCall.execute();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}