From 3c6cd188637355e2ba1f28a9d06a7571c1461006 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Wed, 5 Feb 2025 15:39:58 -0500 Subject: [PATCH] Search for emoji to react with --- .../ui/ConversationFragment.java | 16 ++-- .../siacs/conversations/ui/XmppActivity.java | 83 ++++++++++++++++--- .../ui/adapter/MessageAdapter.java | 11 +-- src/main/res/layout/dialog_add_reaction.xml | 22 +++++ 4 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index db778d4da4e1dce372d9b63f98f45938f2136c56..1867735579571a3b5fbdfda5a4af0081398e5e2c 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -2968,16 +2968,12 @@ public class ConversationFragment extends XmppFragment } } - private void addReaction(final Message message) { - activity.addReaction( - message, - reactions -> { - if (activity.xmppConnectionService.sendReactions(message, reactions)) { - return; - } - Toast.makeText(activity, R.string.could_not_add_reaction, Toast.LENGTH_LONG) - .show(); - }); + public void addReaction(final Message message) { + activity.addReaction(emoji -> { + setupReply(message); + binding.textinput.setText(emoji.toInsert()); + sendMessage(); + }); } private void reportMessage(final Message message) { diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java index 0c0879dbdae53b6468ed4bfae904854b54fc7ff1..bee7d2f8ca4f65126214de2d06f58797eafbd664 100644 --- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java @@ -33,12 +33,15 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.PowerManager; import android.os.SystemClock; import android.preference.PreferenceManager; import android.provider.Settings; +import android.text.Editable; import android.text.Html; import android.text.InputType; +import android.text.Spannable; import android.util.DisplayMetrics; import android.util.Log; import android.util.Pair; @@ -59,12 +62,21 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.core.content.pm.ShortcutInfoCompat; import androidx.core.content.pm.ShortcutManagerCompat; import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.RecyclerView.Adapter; import com.google.android.material.color.MaterialColors; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.common.base.Strings; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableSet; +import com.cheogram.android.EmojiSearch; + +import com.otaliastudios.autocomplete.Autocomplete; +import com.otaliastudios.autocomplete.AutocompleteCallback; +import com.otaliastudios.autocomplete.AutocompletePolicy; +import com.otaliastudios.autocomplete.AutocompletePresenter; +import com.otaliastudios.autocomplete.RecyclerViewPresenter; + import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -359,7 +371,7 @@ public abstract class XmppActivity extends ActionBarActivity { builder.create().show(); } - public void addReaction(final Message message, Consumer> callback) { + public void addReaction(Consumer callback) { final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this); final var layoutInflater = this.getLayoutInflater(); final DialogAddReactionBinding viewBinding = @@ -375,20 +387,69 @@ public abstract class XmppActivity extends ActionBarActivity { button.setText(emoji); button.setOnClickListener( v -> { - final var aggregated = message.getAggregatedReactions(); - if (aggregated.ourReactions.contains(emoji)) { - callback.accept(aggregated.ourReactions); - } else { - final ImmutableSet.Builder reactionBuilder = - new ImmutableSet.Builder<>(); - reactionBuilder.addAll(aggregated.ourReactions); - reactionBuilder.add(emoji); - callback.accept(reactionBuilder.build()); - } + callback.accept(new EmojiSearch.Emoji(emoji, 0)); dialog.dismiss(); }); } + + final var emojiDebounce = new Handler(Looper.getMainLooper()); + final var emojiSearch = xmppConnectionService.emojiSearch(); + final var autocomplete = Autocomplete.on(viewBinding.search) + .with(getDrawable(R.drawable.background_message_bubble)) + .with(new AutocompletePolicy() { + @Override + public boolean shouldShowPopup(@NonNull Spannable text, int cursorPos) { return true; } + + @Override + public boolean shouldDismissPopup(@NonNull Spannable text, int cursorPos) { return false; } + + @Override + public CharSequence getQuery(@NonNull Spannable text) { return text; } + + @Override + public void onDismiss(@NonNull Spannable text) { } + }) + .with(new RecyclerViewPresenter(this) { + protected EmojiSearch.EmojiSearchAdapter adapter; + + @Override + protected Adapter instantiateAdapter() { + adapter = emojiSearch.makeAdapter(item -> dispatchClick(item)); + return adapter; + } + + @Override + protected void onViewHidden() { + if (getRecyclerView() == null) return; + super.onViewHidden(); + } + + @Override + protected void onQuery(CharSequence query) { + emojiDebounce.removeCallbacksAndMessages(null); + emojiDebounce.postDelayed(() -> { + if (getRecyclerView() == null) return; + getRecyclerView().setItemAnimator(null); + adapter.search(XmppActivity.this, getRecyclerView(), query.toString()); + }, 100L); + } + }) + .with(new AutocompleteCallback() { + @Override + public boolean onPopupItemClicked(Editable editable, EmojiSearch.Emoji emoji) { + callback.accept(emoji); + dialog.dismiss(); + return true; + } + + @Override + public void onPopupVisibilityChanged(boolean shown) {} + }).build(); + dialog.show(); + dialog.getWindow().getDecorView().post(() -> { + autocomplete.showPopup(""); + }); } protected void deleteAccount(final Account account) { 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 5a7f55d26b76115ee90101d0304b61f97524ba31..1365ea8f6f690f8dba90f69b2c4e248428deef8d 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -1834,15 +1834,8 @@ public class MessageAdapter extends ArrayAdapter { } private void addReaction(final Message message) { - activity.addReaction( - message, - reactions -> { - if (activity.xmppConnectionService.sendReactions(message, reactions)) { - return; - } - Toast.makeText(activity, R.string.could_not_add_reaction, Toast.LENGTH_LONG) - .show(); - }); + if (mConversationFragment == null) return; + mConversationFragment.addReaction(message); } private void promptOpenKeychainInstall(View view) { diff --git a/src/main/res/layout/dialog_add_reaction.xml b/src/main/res/layout/dialog_add_reaction.xml index 674e18c1af383c79d3b7d5320899e5285c029057..cd88bbefc9fa3e56fef7d62592c0f44cfc64dc6d 100644 --- a/src/main/res/layout/dialog_add_reaction.xml +++ b/src/main/res/layout/dialog_add_reaction.xml @@ -15,6 +15,28 @@ android:layout_height="wrap_content" android:layout_centerHorizontal="true" /> + + + + + + + + + +