diff --git a/build.gradle b/build.gradle index 4f62ba369..04f6e98b5 100644 --- a/build.gradle +++ b/build.gradle @@ -135,6 +135,7 @@ dependencies { implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.mikepenz:materialdrawer:9.0.1' implementation 'org.jitsi:org.otr4j:0.23' + implementation "com.github.pgreze:android-reactions:1.6" } ext { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index c9c50b9ce..73cdde789 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -1783,9 +1783,9 @@ public class ConversationFragment extends XmppFragment if (message.isPrivateMessage()) privateMessageWith(message.getCounterpart()); setThread(message.getThread()); conversation.setUserSelectedThread(true); + conversation.setUserSelectedThread(true); } - if (conversation.getMode() == Conversational.MODE_SINGLE - || conversation.getMucOptions().participating()) addReaction(message); + // if (conversation.getMode() == Conversational.MODE_SINGLE || conversation.getMucOptions().participating()) addReaction(message); }); messageListAdapter.setOnMessageBoxSwiped(message -> { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 4cb866ca2..5e07c7320 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -333,6 +333,8 @@ public abstract class XmppActivity extends ActionBarActivity { } public void addReaction(final Message message, Consumer> callback) { + + PopupWindow popupWindow = new PopupWindow(this); final var layoutInflater = this.getLayoutInflater(); final DialogAddReactionBinding viewBinding = diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index ae313decc..2ff2260b4 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.ui.adapter; import static android.view.View.GONE; import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; @@ -54,6 +55,9 @@ import androidx.core.widget.ImageViewCompat; import androidx.databinding.DataBindingUtil; import com.bumptech.glide.Glide; +import com.github.pgreze.reactions.ReactionPopup; +import com.github.pgreze.reactions.ReactionsConfig; +import com.github.pgreze.reactions.ReactionsConfigBuilder; import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.shape.CornerFamily; import com.google.android.material.shape.ShapeAppearanceModel; @@ -73,9 +77,11 @@ import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.lelloman.identicon.view.GithubIdenticonView; import com.daimajia.swipe.SwipeLayout; +import eu.siacs.conversations.ui.AddReactionActivity; import io.ipfs.cid.Cid; import java.io.IOException; @@ -87,6 +93,7 @@ import java.util.List; import java.util.Map; import java.util.Locale; import java.util.UUID; +import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -1460,23 +1467,109 @@ public class MessageAdapter extends ArrayAdapter { } }); - - - - - - // Treat touch-up as click so we don't have to touch twice - // (touch twice is because it's waiting to see if you double-touch for text selection) - viewHolder.messageBody.setOnTouchListener((v, event) -> { - if (event.getAction() == MotionEvent.ACTION_UP) { - if (MessageAdapter.this.mOnMessageBoxClickedListener != null) { - MessageAdapter.this.mOnMessageBoxClickedListener - .onContactPictureClicked(message); + // new reactions popup + new Thread(() -> activity.runOnUiThread(() -> { + Consumer> callback = reactions -> activity.xmppConnectionService.sendReactions(message, reactions); + ReactionsConfig config = new ReactionsConfigBuilder(activity) + .withReactions(new int[]{ + R.drawable.red_heart_2764_fe0f, + R.drawable.thumbs_up_1f44d, + R.drawable.thumbs_down_1f44e, + R.drawable.face_with_tears_of_joy_1f602, + R.drawable.astonished_face_1f632, + R.drawable.crying_face_1f622, + R.drawable.ic_more_horiz_24dp + }) + .withPopupAlpha(170) + .build(); + ReactionPopup popup = new ReactionPopup(activity, config, (positionPopup) -> { + if (positionPopup.equals(0)) { + final var aggregated = message.getAggregatedReactions(); + if (aggregated.ourReactions.contains("❤\uFE0F")) { + callback.accept(aggregated.ourReactions); + } else { + final ImmutableSet.Builder reactionBuilder = + new ImmutableSet.Builder<>(); + reactionBuilder.addAll(aggregated.ourReactions); + reactionBuilder.add("❤\uFE0F"); + callback.accept(reactionBuilder.build()); + } + } else if (positionPopup.equals(1)) { + final var aggregated = message.getAggregatedReactions(); + if (aggregated.ourReactions.contains("\uD83D\uDC4D")) { + callback.accept(aggregated.ourReactions); + } else { + final ImmutableSet.Builder reactionBuilder = + new ImmutableSet.Builder<>(); + reactionBuilder.addAll(aggregated.ourReactions); + reactionBuilder.add("\uD83D\uDC4D"); + callback.accept(reactionBuilder.build()); + } + } else if (positionPopup.equals(2)) { + final var aggregated = message.getAggregatedReactions(); + if (aggregated.ourReactions.contains("\uD83D\uDC4E")) { + callback.accept(aggregated.ourReactions); + } else { + final ImmutableSet.Builder reactionBuilder = + new ImmutableSet.Builder<>(); + reactionBuilder.addAll(aggregated.ourReactions); + reactionBuilder.add("\uD83D\uDC4E"); + callback.accept(reactionBuilder.build()); + } + } else if (positionPopup.equals(3)) { + final var aggregated = message.getAggregatedReactions(); + if (aggregated.ourReactions.contains("\uD83D\uDE02")) { + callback.accept(aggregated.ourReactions); + } else { + final ImmutableSet.Builder reactionBuilder = + new ImmutableSet.Builder<>(); + reactionBuilder.addAll(aggregated.ourReactions); + reactionBuilder.add("\uD83D\uDE02"); + callback.accept(reactionBuilder.build()); + } + } else if (positionPopup.equals(4)) { + final var aggregated = message.getAggregatedReactions(); + if (aggregated.ourReactions.contains("\uD83D\uDE32")) { + callback.accept(aggregated.ourReactions); + } else { + final ImmutableSet.Builder reactionBuilder = + new ImmutableSet.Builder<>(); + reactionBuilder.addAll(aggregated.ourReactions); + reactionBuilder.add("\uD83D\uDE32"); + callback.accept(reactionBuilder.build()); + } + } else if (positionPopup.equals(5)) { + final var aggregated = message.getAggregatedReactions(); + if (aggregated.ourReactions.contains("\uD83D\uDE22")) { + callback.accept(aggregated.ourReactions); + } else { + final ImmutableSet.Builder reactionBuilder = + new ImmutableSet.Builder<>(); + reactionBuilder.addAll(aggregated.ourReactions); + reactionBuilder.add("\uD83D\uDE22"); + callback.accept(reactionBuilder.build()); + } + } else if (positionPopup.equals(6)) { + final var intent = new Intent(activity, AddReactionActivity.class); + intent.putExtra("conversation", message.getConversation().getUuid()); + intent.putExtra("message", message.getUuid()); + activity.startActivity(intent); } - } + return true; // true is closing popup, false is requesting a new selection + }); + + viewHolder.message_box.setOnTouchListener((v, event) -> { + if (event.getAction() == MotionEvent.ACTION_UP) { + if (MessageAdapter.this.mOnMessageBoxClickedListener != null) { + popup.onTouch(v, event); + } + } + + return false; + }); + })).start(); + - return false; - }); viewHolder.messageBody.setOnClickListener(v -> { if (MessageAdapter.this.mOnMessageBoxClickedListener != null) { MessageAdapter.this.mOnMessageBoxClickedListener @@ -1864,7 +1957,10 @@ public class MessageAdapter extends ArrayAdapter { } private void addReaction(final Message message) { - activity.addReaction(message, reactions -> activity.xmppConnectionService.sendReactions(message,reactions)); + final var intent = new Intent(activity, AddReactionActivity.class); + intent.putExtra("conversation", message.getConversation().getUuid()); + intent.putExtra("message", message.getUuid()); + activity.startActivity(intent); } private void promptOpenKeychainInstall(View view) { diff --git a/src/main/res/drawable/astonished_face_1f632.webp b/src/main/res/drawable/astonished_face_1f632.webp new file mode 100644 index 000000000..26a280763 Binary files /dev/null and b/src/main/res/drawable/astonished_face_1f632.webp differ diff --git a/src/main/res/drawable/crying_face_1f622.webp b/src/main/res/drawable/crying_face_1f622.webp new file mode 100644 index 000000000..ab21e39a1 Binary files /dev/null and b/src/main/res/drawable/crying_face_1f622.webp differ diff --git a/src/main/res/drawable/face_with_tears_of_joy_1f602.webp b/src/main/res/drawable/face_with_tears_of_joy_1f602.webp new file mode 100644 index 000000000..7340af107 Binary files /dev/null and b/src/main/res/drawable/face_with_tears_of_joy_1f602.webp differ diff --git a/src/main/res/drawable/red_heart_2764_fe0f.webp b/src/main/res/drawable/red_heart_2764_fe0f.webp new file mode 100644 index 000000000..c7f85a14c Binary files /dev/null and b/src/main/res/drawable/red_heart_2764_fe0f.webp differ diff --git a/src/main/res/drawable/thumbs_down_1f44e.webp b/src/main/res/drawable/thumbs_down_1f44e.webp new file mode 100644 index 000000000..54e92b0f0 Binary files /dev/null and b/src/main/res/drawable/thumbs_down_1f44e.webp differ diff --git a/src/main/res/drawable/thumbs_up_1f44d.webp b/src/main/res/drawable/thumbs_up_1f44d.webp new file mode 100644 index 000000000..b5691441d Binary files /dev/null and b/src/main/res/drawable/thumbs_up_1f44d.webp differ