From 3a95cacfa28842e8475f2491799fc762b4d4d388 Mon Sep 17 00:00:00 2001 From: nuclearfog Date: Fri, 1 Dec 2023 23:47:42 +0100 Subject: [PATCH] added announcement reaction view --- .../org/nuclearfog/twidda/model/Reaction.java | 8 +- .../recyclerview/AnnouncementAdapter.java | 26 +++++- .../adapter/recyclerview/ReactionAdapter.java | 83 +++++++++++++++++++ .../holder/AnnouncementHolder.java | 20 ++++- .../holder/OnHolderClickListener.java | 2 + .../recyclerview/holder/ReactionHolder.java | 71 ++++++++++++++++ .../ui/fragments/AnnouncementFragment.java | 7 ++ app/src/main/res/layout/item_announcement.xml | 10 +-- app/src/main/res/layout/item_reaction.xml | 25 ++++++ app/src/main/res/values/dimens.xml | 5 ++ app/src/main/res/values/strings.xml | 1 + 11 files changed, 247 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/ReactionAdapter.java create mode 100644 app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/ReactionHolder.java create mode 100644 app/src/main/res/layout/item_reaction.xml diff --git a/app/src/main/java/org/nuclearfog/twidda/model/Reaction.java b/app/src/main/java/org/nuclearfog/twidda/model/Reaction.java index 184a240e..da0a8a47 100644 --- a/app/src/main/java/org/nuclearfog/twidda/model/Reaction.java +++ b/app/src/main/java/org/nuclearfog/twidda/model/Reaction.java @@ -7,7 +7,7 @@ import java.io.Serializable; * * @author nuclearfog */ -public interface Reaction extends Serializable { +public interface Reaction extends Serializable, Comparable { /** * @return title, emoji unicode or custom emoji shortcode of the reaction @@ -28,4 +28,10 @@ public interface Reaction extends Serializable { * @return true if selected by current user */ boolean isSelected(); + + + @Override + default int compareTo(Reaction reaction) { + return Integer.compare(reaction.getCount(), getCount()); + } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/AnnouncementAdapter.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/AnnouncementAdapter.java index a8b2e13b..8d601ac4 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/AnnouncementAdapter.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/AnnouncementAdapter.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView.Adapter; import org.nuclearfog.twidda.model.Announcement; +import org.nuclearfog.twidda.model.Reaction; import org.nuclearfog.twidda.model.lists.Announcements; import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.AnnouncementHolder; import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.OnHolderClickListener; @@ -49,10 +50,20 @@ public class AnnouncementAdapter extends Adapter implements @Override public void onItemClick(int position, int type, int... extras) { - if (type == ANNOUNCEMENT_DISMISS) { - listener.onAnnouncementDismiss(items.get(position)); - } else if (type == ANNOUNCEMENT_CLICK) { - listener.onAnnouncementClick(items.get(position)); + + switch(type) { + case ANNOUNCEMENT_DISMISS: + listener.onAnnouncementDismiss(items.get(position)); + break; + + case ANNOUNCEMENT_CLICK: + listener.onAnnouncementClick(items.get(position)); + break; + + case ANNOUNCEMENT_REACTION: + int reactionIndex = extras[0]; + listener.onReactionClick(items.get(position).getReactions()[reactionIndex]); + break; } } @@ -125,5 +136,12 @@ public class AnnouncementAdapter extends Adapter implements * @param announcement clicked item */ void onAnnouncementDismiss(Announcement announcement); + + /** + * called to select reaction + * + * @param reaction selected reaction + */ + void onReactionClick(Reaction reaction); } } \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/ReactionAdapter.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/ReactionAdapter.java new file mode 100644 index 00000000..8f2cbbd0 --- /dev/null +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/ReactionAdapter.java @@ -0,0 +1,83 @@ +package org.nuclearfog.twidda.ui.adapter.recyclerview; + +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView.Adapter; + +import org.nuclearfog.twidda.model.Reaction; +import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.OnHolderClickListener; +import org.nuclearfog.twidda.ui.adapter.recyclerview.holder.ReactionHolder; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * @author nuclearfog + */ +public class ReactionAdapter extends Adapter implements OnHolderClickListener { + + private OnReactionSelected listener; + private List items = new LinkedList<>(); + + /** + * + */ + public ReactionAdapter(OnReactionSelected listener) { + this.listener = listener; + } + + + @NonNull + @Override + public ReactionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new ReactionHolder(parent, this); + } + + + @Override + public void onBindViewHolder(@NonNull ReactionHolder holder, int position) { + holder.setContent(items.get(position)); + } + + + @Override + public int getItemCount() { + return items.size(); + } + + + @Override + public void onItemClick(int position, int type, int... extras) { + if (type == ANNOUNCEMENT_REACTION) { + listener.onReactionClick(position); + } + } + + + @Override + public boolean onPlaceholderClick(int index) { + return false; + } + + /** + * add adapter items + */ + public void setItems(Reaction[] reactions) { + items.clear(); + Arrays.sort(reactions); + items.addAll(Arrays.asList(reactions)); + notifyDataSetChanged(); + } + + /** + * + */ + public interface OnReactionSelected { + + void onReactionClick(int index); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/AnnouncementHolder.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/AnnouncementHolder.java index 003ebdb4..9dbc0386 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/AnnouncementHolder.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/AnnouncementHolder.java @@ -10,6 +10,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.ViewHolder; @@ -22,19 +23,22 @@ import org.nuclearfog.twidda.backend.utils.StringUtils; import org.nuclearfog.twidda.backend.utils.Tagger; import org.nuclearfog.twidda.config.GlobalSettings; import org.nuclearfog.twidda.model.Announcement; +import org.nuclearfog.twidda.ui.adapter.recyclerview.ReactionAdapter; +import org.nuclearfog.twidda.ui.adapter.recyclerview.ReactionAdapter.OnReactionSelected; /** * Viewholder for {@link org.nuclearfog.twidda.ui.adapter.recyclerview.AnnouncementAdapter} * * @author nuclearfog */ -public class AnnouncementHolder extends ViewHolder implements OnClickListener { +public class AnnouncementHolder extends ViewHolder implements OnClickListener, OnReactionSelected { private TextView time, content; private OnHolderClickListener listener; private GlobalSettings settings; private TextEmojiLoader emojiLoader; + private ReactionAdapter adapter; private AsyncExecutor.AsyncCallback textResult = this::setTextEmojis; private int iconSize; @@ -48,13 +52,17 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener { super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_announcement, parent, false)); settings = GlobalSettings.get(parent.getContext()); emojiLoader = new TextEmojiLoader(parent.getContext()); + adapter = new ReactionAdapter(this); CardView card = (CardView) itemView; ViewGroup container = itemView.findViewById(R.id.item_announcement_container); View dismiss = itemView.findViewById(R.id.item_announcement_dismiss); + RecyclerView reactionList = itemView.findViewById(R.id.item_announcement_list_reactions); time = itemView.findViewById(R.id.item_announcement_timestamp); content = itemView.findViewById(R.id.item_announcement_content); iconSize = parent.getResources().getDimensionPixelSize(R.dimen.item_announcement_icon_size); + reactionList.setLayoutManager(new LinearLayoutManager(parent.getContext(), LinearLayoutManager.HORIZONTAL, false)); + reactionList.setAdapter(adapter); card.setCardBackgroundColor(settings.getCardColor()); AppStyles.setTheme(container, Color.TRANSPARENT); @@ -76,6 +84,15 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener { } } + + @Override + public void onReactionClick(int index) { + int position = getLayoutPosition(); + if (position != RecyclerView.NO_POSITION) { + listener.onItemClick(position, OnHolderClickListener.ANNOUNCEMENT_REACTION, index); + } + } + /** * */ @@ -88,6 +105,7 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener { } content.setText(textSpan); time.setText(StringUtils.formatCreationTime(time.getResources(), announcement.getTimestamp())); + adapter.setItems(announcement.getReactions()); } /** diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/OnHolderClickListener.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/OnHolderClickListener.java index 2328b763..f56d253d 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/OnHolderClickListener.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/OnHolderClickListener.java @@ -61,6 +61,8 @@ public interface OnHolderClickListener { int ANNOUNCEMENT_DISMISS = 29; + int ANNOUNCEMENT_REACTION = 30; + /** * called when an item was clicked * diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/ReactionHolder.java b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/ReactionHolder.java new file mode 100644 index 00000000..bfcdd12a --- /dev/null +++ b/app/src/main/java/org/nuclearfog/twidda/ui/adapter/recyclerview/holder/ReactionHolder.java @@ -0,0 +1,71 @@ +package org.nuclearfog.twidda.ui.adapter.recyclerview.holder; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; + +import com.squareup.picasso.Picasso; + +import org.nuclearfog.twidda.R; +import org.nuclearfog.twidda.backend.image.PicassoBuilder; +import org.nuclearfog.twidda.config.GlobalSettings; +import org.nuclearfog.twidda.model.Reaction; + +/** + * @author nuclearfog + */ +public class ReactionHolder extends ViewHolder implements OnClickListener { + + private ImageView icon; + private TextView description; + + private OnHolderClickListener listener; + private GlobalSettings settings; + private Picasso picasso; + + public ReactionHolder(ViewGroup parent, OnHolderClickListener listener) { + super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_reaction, parent, false)); + icon = itemView.findViewById(R.id.item_reaction_icon); + description = itemView.findViewById(R.id.item_reaction_text); + picasso = PicassoBuilder.get(parent.getContext()); + settings = GlobalSettings.get(parent.getContext()); + this.listener = listener; + + description.setTextColor(settings.getTextColor()); + + itemView.setOnClickListener(this); + } + + + @Override + public void onClick(View v) { + if (v.getId() == R.id.item_reaction_root) { + int position = getLayoutPosition(); + if (position != RecyclerView.NO_POSITION) { + listener.onItemClick(position, OnHolderClickListener.ANNOUNCEMENT_REACTION); + } + } + } + + /** + * + */ + public void setContent(Reaction reaction) { + if (!reaction.getImageUrl().isEmpty() && settings.imagesEnabled()) { + icon.setVisibility(View.VISIBLE); + picasso.load(reaction.getImageUrl()).into(icon); + description.setText(""); + } else { + icon.setVisibility(View.GONE); + icon.setImageResource(0); + description.setText(reaction.getName() + " "); + } + description.append(Integer.toString(reaction.getCount())); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/fragments/AnnouncementFragment.java b/app/src/main/java/org/nuclearfog/twidda/ui/fragments/AnnouncementFragment.java index 2516f068..8b02f9b2 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/fragments/AnnouncementFragment.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/fragments/AnnouncementFragment.java @@ -14,6 +14,7 @@ import org.nuclearfog.twidda.backend.async.AnnouncementLoader; import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback; import org.nuclearfog.twidda.backend.utils.ErrorUtils; import org.nuclearfog.twidda.model.Announcement; +import org.nuclearfog.twidda.model.Reaction; import org.nuclearfog.twidda.model.lists.Announcements; import org.nuclearfog.twidda.ui.adapter.recyclerview.AnnouncementAdapter; import org.nuclearfog.twidda.ui.adapter.recyclerview.AnnouncementAdapter.OnAnnouncementClickListener; @@ -123,6 +124,12 @@ public class AnnouncementFragment extends ListFragment implements OnAnnouncement } } + + @Override + public void onReactionClick(Reaction reaction) { + // todo implement this + } + /** * */ diff --git a/app/src/main/res/layout/item_announcement.xml b/app/src/main/res/layout/item_announcement.xml index 4ab35855..b58d0c7f 100644 --- a/app/src/main/res/layout/item_announcement.xml +++ b/app/src/main/res/layout/item_announcement.xml @@ -1,7 +1,7 @@ - @@ -39,7 +39,7 @@ diff --git a/app/src/main/res/layout/item_reaction.xml b/app/src/main/res/layout/item_reaction.xml new file mode 100644 index 00000000..c7114202 --- /dev/null +++ b/app/src/main/res/layout/item_reaction.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index f36937fd..4cdde0d9 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -391,6 +391,11 @@ 5dp + + 20dp + 14sp + 5dp + 10dp 8dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b781692e..b87fd1be 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -329,6 +329,7 @@ Video preview button Vote finished voted + reaction of an announcement Status/Message attachment vote finished select network