diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiItemDecoration.kt b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiItemDecoration.kt index 122cf615c..690875265 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiItemDecoration.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiItemDecoration.kt @@ -11,7 +11,7 @@ import org.thoughtcrime.securesms.util.InsetItemDecoration import org.thoughtcrime.securesms.util.ViewUtil private val EDGE_LENGTH: Int = ViewUtil.dpToPx(7) -private val HORIZONTAL_INSET: Int = ViewUtil.dpToPx(11) +private val HORIZONTAL_INSET: Int = ViewUtil.dpToPx(8) private val VERTICAL_INSET: Int = ViewUtil.dpToPx(8) /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java index 4a216c9e7..4037af4e3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java @@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.util.MappingModel; import org.thoughtcrime.securesms.util.MappingModelList; import org.thoughtcrime.securesms.util.ViewUtil; +import java.util.List; import java.util.Optional; public class EmojiPageView extends RecyclerView implements VariationSelectorListener { @@ -59,26 +60,26 @@ public class EmojiPageView extends RecyclerView implements VariationSelectorList @NonNull VariationSelectorListener variationSelectorListener, boolean allowVariations, @NonNull LinearLayoutManager layoutManager, - @LayoutRes int displayItemLayoutResId) + @LayoutRes int displayEmojiLayoutResId, + @LayoutRes int displayEmoticonLayoutResId) { super(context); - initialize(emojiSelectionListener, variationSelectorListener, allowVariations, layoutManager, displayItemLayoutResId); + initialize(emojiSelectionListener, variationSelectorListener, allowVariations, layoutManager, displayEmojiLayoutResId, displayEmoticonLayoutResId); } public void initialize(@NonNull EmojiEventListener emojiSelectionListener, @NonNull VariationSelectorListener variationSelectorListener, boolean allowVariations) { - initialize(emojiSelectionListener, variationSelectorListener, allowVariations, new GridLayoutManager(getContext(), 8), R.layout.emoji_display_item); - Drawable drawable = DrawableUtil.tint(ContextUtil.requireDrawable(getContext(), R.drawable.triangle_bottom_right_corner), ContextCompat.getColor(getContext(), R.color.signal_button_secondary_text_disabled)); - addItemDecoration(new EmojiItemDecoration(allowVariations, drawable)); + initialize(emojiSelectionListener, variationSelectorListener, allowVariations, new GridLayoutManager(getContext(), 8), R.layout.emoji_display_item_grid, R.layout.emoji_text_display_item_grid); } public void initialize(@NonNull EmojiEventListener emojiSelectionListener, @NonNull VariationSelectorListener variationSelectorListener, boolean allowVariations, @NonNull LinearLayoutManager layoutManager, - @LayoutRes int displayItemLayoutResId) + @LayoutRes int displayEmojiLayoutResId, + @LayoutRes int displayEmoticonLayoutResId) { this.variationSelectorListener = variationSelectorListener; @@ -89,7 +90,8 @@ public class EmojiPageView extends RecyclerView implements VariationSelectorList emojiSelectionListener, this, allowVariations, - displayItemLayoutResId); + displayEmojiLayoutResId, + displayEmoticonLayoutResId); if (this.layoutManager instanceof GridLayoutManager) { GridLayoutManager gridLayout = (GridLayoutManager) this.layoutManager; @@ -108,6 +110,9 @@ public class EmojiPageView extends RecyclerView implements VariationSelectorList } setLayoutManager(layoutManager); + + Drawable drawable = DrawableUtil.tint(ContextUtil.requireDrawable(getContext(), R.drawable.triangle_bottom_right_corner), ContextCompat.getColor(getContext(), R.color.signal_button_secondary_text_disabled)); + addItemDecoration(new EmojiItemDecoration(allowVariations, drawable)); } public void presentForEmojiKeyboard() { @@ -125,7 +130,7 @@ public class EmojiPageView extends RecyclerView implements VariationSelectorList } } - public void setList(@NonNull MappingModelList list) { + public void setList(@NonNull List> list) { this.model = null; EmojiPageViewGridAdapter adapter = adapterFactory.create(); setAdapter(adapter); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageViewGridAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageViewGridAdapter.java index 8b5ef44ad..7ad18c760 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageViewGridAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageViewGridAdapter.java @@ -22,15 +22,16 @@ public class EmojiPageViewGridAdapter extends MappingAdapter implements PopupWin @NonNull EmojiEventListener emojiEventListener, @NonNull VariationSelectorListener variationSelectorListener, boolean allowVariations, - @LayoutRes int displayItemLayoutResId) + @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), displayItemLayoutResId)); - registerFactory(EmojiTextModel.class, new LayoutFactory<>(v -> new EmojiTextViewHolder(v, emojiEventListener), R.layout.emoji_text_display_item)); + 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)); } @@ -118,7 +119,6 @@ public class EmojiPageViewGridAdapter extends MappingAdapter implements PopupWin private final boolean allowVariations; private final ImageView imageView; - private final ImageView hintCorner; public EmojiViewHolder(@NonNull View itemView, @NonNull EmojiEventListener emojiEventListener, @@ -134,7 +134,6 @@ public class EmojiPageViewGridAdapter extends MappingAdapter implements PopupWin this.allowVariations = allowVariations; this.imageView = itemView.findViewById(R.id.emoji_image); - this.hintCorner = itemView.findViewById(R.id.emoji_variation_hint); } @Override @@ -151,9 +150,6 @@ public class EmojiPageViewGridAdapter extends MappingAdapter implements PopupWin }); if (allowVariations && model.emoji.hasMultipleVariations()) { - if (hintCorner != null) { - hintCorner.setVisibility(View.VISIBLE); - } itemView.setOnLongClickListener(v -> { popup.dismiss(); popup.setVariations(model.emoji.getVariations()); @@ -162,9 +158,6 @@ public class EmojiPageViewGridAdapter extends MappingAdapter implements PopupWin return true; }); } else { - if (hintCorner != null) { - hintCorner.setVisibility(View.GONE); - } itemView.setOnLongClickListener(null); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageViewModel.kt index 6cee1e039..4b1c11de8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageViewModel.kt @@ -7,16 +7,12 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.emoji.EmojiPageModel -import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiHeader import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel -import org.thoughtcrime.securesms.components.emoji.parsing.EmojiTree import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.emoji.EmojiCategory -import org.thoughtcrime.securesms.emoji.EmojiSource.Companion.latest import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageCategoryMappingModel.EmojiCategoryMappingModel import org.thoughtcrime.securesms.util.DefaultValueLiveData -import org.thoughtcrime.securesms.util.MappingModel import org.thoughtcrime.securesms.util.MappingModelList import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.livedata.LiveDataUtil @@ -92,17 +88,3 @@ class EmojiKeyboardPageViewModel(repository: EmojiKeyboardPageRepository) : View } } } - -private fun EmojiPageModel.toMappingModels(): List> { - val emojiTree: EmojiTree = latest.emojiTree - - return displayEmoji.map { - val isTextEmoji = EmojiCategory.EMOTICONS.key == key || (RecentEmojiPageModel.KEY == key && emojiTree.getEmoji(it.value, 0, it.value.length) == null) - - if (isTextEmoji) { - EmojiPageViewGridAdapter.EmojiTextModel(key, it) - } else { - EmojiPageViewGridAdapter.EmojiModel(key, it) - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiPageModelExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiPageModelExtensions.kt new file mode 100644 index 000000000..20d4b45d3 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiPageModelExtensions.kt @@ -0,0 +1,23 @@ +package org.thoughtcrime.securesms.keyboard.emoji + +import org.thoughtcrime.securesms.components.emoji.EmojiPageModel +import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter +import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel +import org.thoughtcrime.securesms.components.emoji.parsing.EmojiTree +import org.thoughtcrime.securesms.emoji.EmojiCategory +import org.thoughtcrime.securesms.emoji.EmojiSource +import org.thoughtcrime.securesms.util.MappingModel + +fun EmojiPageModel.toMappingModels(): List> { + val emojiTree: EmojiTree = EmojiSource.latest.emojiTree + + return displayEmoji.map { + val isTextEmoji = EmojiCategory.EMOTICONS.key == key || (RecentEmojiPageModel.KEY == key && emojiTree.getEmoji(it.value, 0, it.value.length) == null) + + if (isTextEmoji) { + EmojiPageViewGridAdapter.EmojiTextModel(key, it) + } else { + EmojiPageViewGridAdapter.EmojiModel(key, it) + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt index a9cb27d39..2f4ddae8e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt @@ -40,17 +40,25 @@ class EmojiSearchFragment : Fragment(R.layout.emoji_search_fragment), EmojiPageV val searchBar: KeyboardPageSearchView = view.findViewById(R.id.emoji_search_view) val resultsContainer: FrameLayout = view.findViewById(R.id.emoji_search_results_container) val noResults: TextView = view.findViewById(R.id.emoji_search_empty) - val emojiPageView = EmojiPageView(requireContext(), eventListener, this, true, LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false), R.layout.emoji_search_result_display_item) + val emojiPageView = EmojiPageView( + requireContext(), + eventListener, + this, + true, + LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false), + R.layout.emoji_display_item_list, + R.layout.emoji_text_display_item_list + ) resultsContainer.addView(emojiPageView) searchBar.presentForEmojiSearch() searchBar.callbacks = SearchCallbacks() - viewModel.pageModel.observe(viewLifecycleOwner) { pageModel -> - emojiPageView.setModel(pageModel) + viewModel.emojiList.observe(viewLifecycleOwner) { results -> + emojiPageView.setList(results.emojiList) - if (pageModel.emoji.isNotEmpty() || pageModel.iconAttr == R.attr.emoji_category_recent) { + if (results.emojiList.isNotEmpty() || results.isRecents) { emojiPageView.visibility = View.VISIBLE noResults.visibility = View.GONE } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchViewModel.kt index e987a1224..3b492634d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchViewModel.kt @@ -5,21 +5,29 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import org.thoughtcrime.securesms.components.emoji.EmojiPageModel +import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel +import org.thoughtcrime.securesms.keyboard.emoji.toMappingModels +import org.thoughtcrime.securesms.util.MappingModel +import org.thoughtcrime.securesms.util.livedata.LiveDataUtil class EmojiSearchViewModel(private val repository: EmojiSearchRepository) : ViewModel() { - private val internalPageModel = MutableLiveData() + private val pageModel = MutableLiveData() - val pageModel: LiveData = internalPageModel + val emojiList: LiveData = LiveDataUtil.mapAsync(pageModel) { page -> + EmojiSearchResults(page.toMappingModels(), page.key == RecentEmojiPageModel.KEY) + } init { onQueryChanged("") } fun onQueryChanged(query: String) { - repository.submitQuery(query = query, includeRecents = true, consumer = internalPageModel::postValue) + repository.submitQuery(query = query, includeRecents = true, consumer = pageModel::postValue) } + data class EmojiSearchResults(val emojiList: List>, val isRecents: Boolean) + class Factory(private val repository: EmojiSearchRepository) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return requireNotNull(modelClass.cast(EmojiSearchViewModel(repository))) diff --git a/app/src/main/res/layout/emoji_display_item.xml b/app/src/main/res/layout/emoji_display_item_grid.xml similarity index 100% rename from app/src/main/res/layout/emoji_display_item.xml rename to app/src/main/res/layout/emoji_display_item_grid.xml diff --git a/app/src/main/res/layout/emoji_display_item_list.xml b/app/src/main/res/layout/emoji_display_item_list.xml new file mode 100644 index 000000000..3e2ba9814 --- /dev/null +++ b/app/src/main/res/layout/emoji_display_item_list.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/emoji_search_result_display_item.xml b/app/src/main/res/layout/emoji_search_result_display_item.xml deleted file mode 100644 index e2b967cf4..000000000 --- a/app/src/main/res/layout/emoji_search_result_display_item.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/emoji_text_display_item.xml b/app/src/main/res/layout/emoji_text_display_item_grid.xml similarity index 100% rename from app/src/main/res/layout/emoji_text_display_item.xml rename to app/src/main/res/layout/emoji_text_display_item_grid.xml diff --git a/app/src/main/res/layout/emoji_text_display_item_list.xml b/app/src/main/res/layout/emoji_text_display_item_list.xml new file mode 100644 index 000000000..690862e7d --- /dev/null +++ b/app/src/main/res/layout/emoji_text_display_item_list.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/keyboard_pager_emoji_page_fragment.xml b/app/src/main/res/layout/keyboard_pager_emoji_page_fragment.xml index 48f60eaca..73a90e465 100644 --- a/app/src/main/res/layout/keyboard_pager_emoji_page_fragment.xml +++ b/app/src/main/res/layout/keyboard_pager_emoji_page_fragment.xml @@ -34,8 +34,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:clipToPadding="false" - android:paddingStart="5dp" - android:paddingEnd="5dp" + android:paddingStart="8dp" + android:paddingEnd="8dp" android:paddingBottom="?actionBarSize" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 38b4a1e9b..525704ac8 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,7 +6,7 @@ 110dp 170dp 56dp - 54dp + 48dp 16sp 12sp 200sp