241 lines
7.4 KiB
Java
241 lines
7.4 KiB
Java
package org.thoughtcrime.securesms.components.emoji;
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
import android.view.View;
|
|
import android.widget.ImageView;
|
|
import android.widget.PopupWindow;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.LayoutRes;
|
|
import androidx.annotation.NonNull;
|
|
|
|
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory;
|
|
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter;
|
|
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel;
|
|
import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder;
|
|
|
|
import network.loki.messenger.R;
|
|
|
|
public class EmojiPageViewGridAdapter extends MappingAdapter implements PopupWindow.OnDismissListener {
|
|
|
|
private final VariationSelectorListener variationSelectorListener;
|
|
|
|
public EmojiPageViewGridAdapter(@NonNull EmojiVariationSelectorPopup popup,
|
|
@NonNull EmojiEventListener emojiEventListener,
|
|
@NonNull VariationSelectorListener variationSelectorListener,
|
|
boolean allowVariations,
|
|
@LayoutRes int displayEmojiLayoutResId,
|
|
@LayoutRes int displayEmoticonLayoutResId)
|
|
{
|
|
this.variationSelectorListener = variationSelectorListener;
|
|
|
|
popup.setOnDismissListener(this);
|
|
|
|
registerFactory(EmojiHeader.class, new LayoutFactory<>(EmojiHeaderViewHolder::new, R.layout.emoji_grid_header));
|
|
registerFactory(EmojiModel.class, new LayoutFactory<>(v -> new EmojiViewHolder(v, emojiEventListener, variationSelectorListener, popup, allowVariations), displayEmojiLayoutResId));
|
|
registerFactory(EmojiTextModel.class, new LayoutFactory<>(v -> new EmojiTextViewHolder(v, emojiEventListener), displayEmoticonLayoutResId));
|
|
registerFactory(EmojiNoResultsModel.class, new LayoutFactory<>(MappingViewHolder.SimpleViewHolder::new, R.layout.emoji_grid_no_results));
|
|
}
|
|
|
|
@Override
|
|
public void onDismiss() {
|
|
variationSelectorListener.onVariationSelectorStateChanged(false);
|
|
}
|
|
|
|
public static class EmojiHeader implements MappingModel<EmojiHeader>, HasKey {
|
|
|
|
private final String key;
|
|
private final int title;
|
|
|
|
public EmojiHeader(@NonNull String key, int title) {
|
|
this.key = key;
|
|
this.title = title;
|
|
}
|
|
|
|
@Override
|
|
public @NonNull String getKey() {
|
|
return key;
|
|
}
|
|
|
|
@Override
|
|
public boolean areItemsTheSame(@NonNull EmojiHeader newItem) {
|
|
return title == newItem.title;
|
|
}
|
|
|
|
@Override
|
|
public boolean areContentsTheSame(@NonNull EmojiHeader newItem) {
|
|
return areItemsTheSame(newItem);
|
|
}
|
|
}
|
|
|
|
static class EmojiHeaderViewHolder extends MappingViewHolder<EmojiHeader> {
|
|
|
|
private final TextView title;
|
|
|
|
public EmojiHeaderViewHolder(@NonNull View itemView) {
|
|
super(itemView);
|
|
title = findViewById(R.id.emoji_grid_header_title);
|
|
}
|
|
|
|
@Override
|
|
public void bind(@NonNull EmojiHeader model) {
|
|
title.setText(model.title);
|
|
}
|
|
}
|
|
|
|
public static class EmojiModel implements MappingModel<EmojiModel>, HasKey {
|
|
|
|
private final String key;
|
|
private final Emoji emoji;
|
|
|
|
public EmojiModel(@NonNull String key, @NonNull Emoji emoji) {
|
|
this.key = key;
|
|
this.emoji = emoji;
|
|
}
|
|
|
|
@Override
|
|
public @NonNull String getKey() {
|
|
return key;
|
|
}
|
|
|
|
public @NonNull Emoji getEmoji() {
|
|
return emoji;
|
|
}
|
|
|
|
@Override
|
|
public boolean areItemsTheSame(@NonNull EmojiModel newItem) {
|
|
return newItem.emoji.getValue().equals(emoji.getValue());
|
|
}
|
|
|
|
@Override
|
|
public boolean areContentsTheSame(@NonNull EmojiModel newItem) {
|
|
return areItemsTheSame(newItem);
|
|
}
|
|
}
|
|
|
|
static class EmojiViewHolder extends MappingViewHolder<EmojiModel> {
|
|
|
|
private final EmojiVariationSelectorPopup popup;
|
|
private final VariationSelectorListener variationSelectorListener;
|
|
private final EmojiEventListener emojiEventListener;
|
|
private final boolean allowVariations;
|
|
|
|
private final ImageView imageView;
|
|
|
|
public EmojiViewHolder(@NonNull View itemView,
|
|
@NonNull EmojiEventListener emojiEventListener,
|
|
@NonNull VariationSelectorListener variationSelectorListener,
|
|
@NonNull EmojiVariationSelectorPopup popup,
|
|
boolean allowVariations)
|
|
{
|
|
super(itemView);
|
|
|
|
this.popup = popup;
|
|
this.variationSelectorListener = variationSelectorListener;
|
|
this.emojiEventListener = emojiEventListener;
|
|
this.allowVariations = allowVariations;
|
|
|
|
this.imageView = itemView.findViewById(R.id.emoji_image);
|
|
}
|
|
|
|
@Override
|
|
public void bind(@NonNull EmojiModel model) {
|
|
final Drawable drawable = EmojiProvider.getEmojiDrawable(imageView.getContext(), model.emoji.getValue());
|
|
|
|
if (drawable != null) {
|
|
imageView.setVisibility(View.VISIBLE);
|
|
imageView.setImageDrawable(drawable);
|
|
}
|
|
|
|
itemView.setOnClickListener(v -> {
|
|
emojiEventListener.onEmojiSelected(model.emoji.getValue());
|
|
});
|
|
|
|
if (allowVariations && model.emoji.hasMultipleVariations()) {
|
|
itemView.setOnLongClickListener(v -> {
|
|
popup.dismiss();
|
|
popup.setVariations(model.emoji.getVariations());
|
|
popup.showAsDropDown(itemView, 0, -(2 * itemView.getHeight()));
|
|
variationSelectorListener.onVariationSelectorStateChanged(true);
|
|
return true;
|
|
});
|
|
} else {
|
|
itemView.setOnLongClickListener(null);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class EmojiTextModel implements MappingModel<EmojiTextModel>, HasKey {
|
|
private final String key;
|
|
private final Emoji emoji;
|
|
|
|
public EmojiTextModel(@NonNull String key, @NonNull Emoji emoji) {
|
|
this.key = key;
|
|
this.emoji = emoji;
|
|
}
|
|
|
|
@Override
|
|
public @NonNull String getKey() {
|
|
return key;
|
|
}
|
|
|
|
public @NonNull Emoji getEmoji() {
|
|
return emoji;
|
|
}
|
|
|
|
@Override
|
|
public boolean areItemsTheSame(@NonNull EmojiTextModel newItem) {
|
|
return newItem.emoji.getValue().equals(emoji.getValue());
|
|
}
|
|
|
|
@Override
|
|
public boolean areContentsTheSame(@NonNull EmojiTextModel newItem) {
|
|
return areItemsTheSame(newItem);
|
|
}
|
|
}
|
|
|
|
static class EmojiTextViewHolder extends MappingViewHolder<EmojiTextModel> {
|
|
|
|
private final EmojiEventListener emojiEventListener;
|
|
private final AsciiEmojiView textView;
|
|
|
|
public EmojiTextViewHolder(@NonNull View itemView,
|
|
@NonNull EmojiEventListener emojiEventListener)
|
|
{
|
|
super(itemView);
|
|
|
|
this.emojiEventListener = emojiEventListener;
|
|
this.textView = itemView.findViewById(R.id.emoji_text);
|
|
}
|
|
|
|
@Override
|
|
public void bind(@NonNull EmojiTextModel model) {
|
|
textView.setEmoji(model.emoji.getValue());
|
|
|
|
itemView.setOnClickListener(v -> {
|
|
emojiEventListener.onEmojiSelected(model.emoji.getValue());
|
|
});
|
|
}
|
|
}
|
|
|
|
public static class EmojiNoResultsModel implements MappingModel<EmojiNoResultsModel> {
|
|
@Override
|
|
public boolean areItemsTheSame(@NonNull EmojiNoResultsModel newItem) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean areContentsTheSame(@NonNull EmojiNoResultsModel newItem) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public interface HasKey {
|
|
@NonNull String getKey();
|
|
}
|
|
|
|
public interface VariationSelectorListener {
|
|
void onVariationSelectorStateChanged(boolean open);
|
|
}
|
|
}
|