Change summary
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 16
src/main/java/eu/siacs/conversations/ui/XmppActivity.java | 83
src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java | 11
src/main/res/layout/dialog_add_reaction.xml | 22
4 files changed, 102 insertions(+), 30 deletions(-)
Detailed changes
@@ -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) {
@@ -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<Collection<String>> callback) {
+ public void addReaction(Consumer<EmojiSearch.Emoji> 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<String> 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.<EmojiSearch.Emoji>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<EmojiSearch.Emoji>(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<EmojiSearch.Emoji>() {
+ @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) {
@@ -1834,15 +1834,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
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) {
@@ -15,6 +15,28 @@
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
+ <com.google.android.material.textfield.TextInputLayout
+ android:id="@+id/search_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/emojis"
+ android:hint="Search for emoji"
+ app:errorEnabled="true">
+
+ <EditText
+ android:padding="16dp"
+ android:id="@+id/search"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textPersonName">
+
+ <requestFocus />
+ </EditText>
+
+ </com.google.android.material.textfield.TextInputLayout>
+
+
</RelativeLayout>
</layout>