diff --git a/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiCategory.kt b/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiCategory.kt index 4dfc2c2bc4..edf0979658 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiCategory.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiCategory.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.emoji import androidx.annotation.AttrRes +import androidx.annotation.StringRes import org.thoughtcrime.securesms.R /** @@ -17,8 +18,30 @@ enum class EmojiCategory(val priority: Int, val key: String, @AttrRes val icon: FLAGS(7, "Flags", R.attr.emoji_category_flags), EMOTICONS(8, "Emoticons", R.attr.emoji_category_emoticons); + @StringRes + fun getCategoryLabel(): Int { + return getCategoryLabel(icon) + } + companion object { @JvmStatic fun forKey(key: String) = values().first { it.key == key } + + @JvmStatic + @StringRes + fun getCategoryLabel(@AttrRes iconAttr: Int): Int { + return when (iconAttr) { + R.attr.emoji_category_people -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__smileys_and_people + R.attr.emoji_category_nature -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__nature + R.attr.emoji_category_foods -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__food + R.attr.emoji_category_activity -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__activities + R.attr.emoji_category_places -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__places + R.attr.emoji_category_objects -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__objects + R.attr.emoji_category_symbols -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__symbols + R.attr.emoji_category_flags -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__flags + R.attr.emoji_category_emoticons -> R.string.ReactWithAnyEmojiBottomSheetDialogFragment__emoticons + else -> throw AssertionError() + } + } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/BottomShadowBehavior.java b/app/src/main/java/org/thoughtcrime/securesms/keyboard/BottomShadowBehavior.java new file mode 100644 index 0000000000..5011685946 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/BottomShadowBehavior.java @@ -0,0 +1,51 @@ +package org.thoughtcrime.securesms.keyboard; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; + +import org.thoughtcrime.securesms.R; + + +@SuppressWarnings("unused") +public final class BottomShadowBehavior extends CoordinatorLayout.Behavior { + + private int bottomBarId; + private boolean shown = true; + + public BottomShadowBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + if (attrs != null) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BottomShadowBehavior); + bottomBarId = a.getResourceId(R.styleable.BottomShadowBehavior_bottom_bar_id, 0); + a.recycle(); + } + + if (bottomBarId == 0) { + throw new IllegalStateException(); + } + } + + @Override + public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) { + return dependency.getId() == bottomBarId; + } + + @Override + public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) { + float alpha = (dependency.getHeight() - (int) dependency.getTranslationY()) / (float) dependency.getHeight(); + child.setAlpha(alpha); + + float y = dependency.getY() - child.getHeight(); + if (y != child.getY()) { + child.setY(y); + return true; + } + + return false; + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/TopShadowBehavior.java b/app/src/main/java/org/thoughtcrime/securesms/keyboard/TopShadowBehavior.java new file mode 100644 index 0000000000..26e5b5ad02 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/TopShadowBehavior.java @@ -0,0 +1,76 @@ +package org.thoughtcrime.securesms.keyboard; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.recyclerview.widget.RecyclerView; + +import org.thoughtcrime.securesms.R; + + +@SuppressWarnings("unused") +public final class TopShadowBehavior extends CoordinatorLayout.Behavior { + + private int targetId; + private boolean shown = true; + + public TopShadowBehavior(int targetId) { + super(); + this.targetId = targetId; + } + + public TopShadowBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + if (attrs != null) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TopShadowBehavior); + targetId = a.getResourceId(R.styleable.TopShadowBehavior_app_bar_layout_id, 0); + a.recycle(); + } + + if (targetId == 0) { + throw new IllegalStateException(); + } + } + + @Override + public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) { + return dependency instanceof RecyclerView; + } + + @Override + public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) { + boolean shouldShow = dependency.getY() != parent.findViewById(targetId).getHeight(); + + if (shouldShow != shown) { + if (shouldShow) { + show(child); + } else { + hide(child); + } + shown = shouldShow; + } + + if (child.getY() != 0) { + child.setY(0); + return true; + } + + return false; + } + + private void show(View child) { + child.animate() + .setDuration(250) + .alpha(1f); + } + + private void hide(View child) { + child.animate() + .setDuration(250) + .alpha(0f); + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageAdapter.kt deleted file mode 100644 index 8e4353c89e..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageAdapter.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.thoughtcrime.securesms.keyboard.emoji - -import android.view.ViewGroup -import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider -import org.thoughtcrime.securesms.components.emoji.EmojiPageView -import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter -import org.thoughtcrime.securesms.util.MappingAdapter -import org.thoughtcrime.securesms.util.MappingViewHolder - -class EmojiKeyboardPageAdapter( - private val emojiSelectionListener: EmojiKeyboardProvider.EmojiEventListener, - private val variationSelectorListener: EmojiPageViewGridAdapter.VariationSelectorListener -) : MappingAdapter() { - - init { - registerFactory(EmojiPageMappingModel::class.java) { parent -> - val pageView = EmojiPageView(parent.context, emojiSelectionListener, variationSelectorListener, true) - - val layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - pageView.layoutParams = layoutParams - pageView.presentForEmojiKeyboard() - - ViewHolder(pageView) - } - } - - private class ViewHolder( - private val emojiPageView: EmojiPageView, - ) : MappingViewHolder(emojiPageView) { - - override fun bind(model: EmojiPageMappingModel) { - emojiPageView.bindSearchableAdapter(model.emojiPageModel) - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt index abbcc4cd03..dc1b1378df 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt @@ -6,28 +6,36 @@ import android.view.KeyEvent import android.view.View import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.viewpager2.widget.ViewPager2 +import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE +import com.google.android.material.appbar.AppBarLayout import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider +import org.thoughtcrime.securesms.components.emoji.EmojiPageView import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter +import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiHeader import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.keyvalue.SignalStore +import org.thoughtcrime.securesms.util.MappingModel +import java.util.Optional private val DELETE_KEY_EVENT: KeyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL) class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fragment), EmojiKeyboardProvider.EmojiEventListener, EmojiPageViewGridAdapter.VariationSelectorListener { private lateinit var viewModel: EmojiKeyboardPageViewModel - private lateinit var emojiPager: ViewPager2 + private lateinit var emojiPageView: EmojiPageView private lateinit var searchView: View private lateinit var emojiCategoriesRecycler: RecyclerView private lateinit var backspaceView: View private lateinit var eventListener: EmojiKeyboardProvider.EmojiEventListener private lateinit var callback: Callback - private lateinit var pagesAdapter: EmojiKeyboardPageAdapter private lateinit var categoriesAdapter: EmojiKeyboardPageCategoriesAdapter private lateinit var searchBar: KeyboardPageSearchView + private lateinit var appBarLayout: AppBarLayout + + private val categoryUpdateOnScroll = UpdateCategorySelectionOnScroll() override fun onAttach(context: Context) { super.onAttach(context) @@ -37,33 +45,28 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - emojiPager = view.findViewById(R.id.emoji_pager) + emojiPageView = view.findViewById(R.id.emoji_page_view) + emojiPageView.initialize(this, this, true) + emojiPageView.addOnScrollListener(categoryUpdateOnScroll) + searchView = view.findViewById(R.id.emoji_search) searchBar = view.findViewById(R.id.emoji_keyboard_search_text) emojiCategoriesRecycler = view.findViewById(R.id.emoji_categories_recycler) backspaceView = view.findViewById(R.id.emoji_backspace) + appBarLayout = view.findViewById(R.id.emoji_keyboard_search_appbar) } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - viewModel = ViewModelProviders.of(requireActivity()).get(EmojiKeyboardPageViewModel::class.java) - - pagesAdapter = EmojiKeyboardPageAdapter(this, this) + viewModel = ViewModelProviders.of(requireActivity(), EmojiKeyboardPageViewModel.Factory(requireContext())) + .get(EmojiKeyboardPageViewModel::class.java) categoriesAdapter = EmojiKeyboardPageCategoriesAdapter { key -> + scrollTo(key) viewModel.onKeySelected(key) - - val page = pagesAdapter.currentList.indexOfFirst { - (it as EmojiPageMappingModel).key == key - } - - if (emojiPager.currentItem != page) { - emojiPager.currentItem = page - } } - emojiPager.adapter = pagesAdapter emojiCategoriesRecycler.adapter = categoriesAdapter searchBar.callbacks = EmojiKeyboardPageSearchViewCallbacks() @@ -75,22 +78,24 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr backspaceView.setOnClickListener { eventListener.onKeyEvent(DELETE_KEY_EVENT) } viewModel.categories.observe(viewLifecycleOwner) { categories -> - categoriesAdapter.submitList(categories) + categoriesAdapter.submitList(categories) { + (emojiCategoriesRecycler.parent as View).invalidate() + emojiCategoriesRecycler.parent.requestLayout() + } } viewModel.pages.observe(viewLifecycleOwner) { pages -> - val registerPageCallback: Boolean = pagesAdapter.currentList.isEmpty() && pages.isNotEmpty() - pagesAdapter.submitList(pages) { updatePagerPosition(registerPageCallback) } + emojiPageView.setList(pages) } - viewModel.selectedKey.observe(viewLifecycleOwner) { updateCategoryTab() } + viewModel.selectedKey.observe(viewLifecycleOwner) { updateCategoryTab(it) } eventListener = findListener() ?: throw AssertionError("No emoji listener found") } - private fun updateCategoryTab() { + private fun updateCategoryTab(key: String) { emojiCategoriesRecycler.post { - val index: Int = categoriesAdapter.currentList.indexOfFirst { (it as? EmojiKeyboardPageCategoryMappingModel)?.key == viewModel.selectedKey.value } + val index: Int = categoriesAdapter.indexOfFirst(EmojiKeyboardPageCategoryMappingModel::class.java) { it.key == key } if (index != -1) { emojiCategoriesRecycler.smoothScrollToPosition(index) @@ -98,17 +103,14 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr } } - private fun updatePagerPosition(registerPageCallback: Boolean) { - val page = pagesAdapter.currentList.indexOfFirst { - (it as EmojiPageMappingModel).key == viewModel.selectedKey.value - } - - if (emojiPager.currentItem != page && page != -1) { - emojiPager.setCurrentItem(page, false) - } - - if (registerPageCallback) { - emojiPager.registerOnPageChangeCallback(PageChanged(pagesAdapter)) + private fun scrollTo(key: String) { + emojiPageView.adapter?.let { adapter -> + val index = adapter.indexOfFirst(EmojiHeader::class.java) { it.key == key } + if (index != -1) { + appBarLayout.setExpanded(false, true) + categoryUpdateOnScroll.startAutoScrolling() + emojiPageView.smoothScrollToPositionTop(index) + } } } @@ -122,16 +124,7 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr eventListener.onKeyEvent(keyEvent) } - override fun onVariationSelectorStateChanged(open: Boolean) { - emojiPager.isUserInputEnabled = !open - } - - private inner class PageChanged(private val adapter: EmojiKeyboardPageAdapter) : ViewPager2.OnPageChangeCallback() { - override fun onPageSelected(position: Int) { - val mappingModel: EmojiPageMappingModel = adapter.currentList[position] as EmojiPageMappingModel - viewModel.onKeySelected(mappingModel.key) - } - } + override fun onVariationSelectorStateChanged(open: Boolean) = Unit private inner class EmojiKeyboardPageSearchViewCallbacks : KeyboardPageSearchView.Callbacks { override fun onClicked() { @@ -139,6 +132,38 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr } } + private inner class UpdateCategorySelectionOnScroll : RecyclerView.OnScrollListener() { + + private var doneScrolling: Boolean = true + + fun startAutoScrolling() { + doneScrolling = false + } + + @Override + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + if (newState == SCROLL_STATE_IDLE && !doneScrolling) { + doneScrolling = true + onScrolled(recyclerView, 0, 0) + } + } + + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + if (recyclerView.layoutManager == null || !doneScrolling) { + return + } + + emojiPageView.adapter?.let { adapter -> + val layoutManager = recyclerView.layoutManager as LinearLayoutManager + val index = layoutManager.findFirstCompletelyVisibleItemPosition() + val item: Optional> = adapter.getModel(index) + if (item.isPresent && item.get() is EmojiPageViewGridAdapter.HasKey) { + viewModel.onKeySelected((item.get() as EmojiPageViewGridAdapter.HasKey).key) + } + } + } + } + interface Callback { fun openEmojiSearch() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageRepository.kt new file mode 100644 index 0000000000..d403ec4230 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageRepository.kt @@ -0,0 +1,23 @@ +package org.thoughtcrime.securesms.keyboard.emoji + +import android.content.Context +import org.signal.core.util.concurrent.SignalExecutors +import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider +import org.thoughtcrime.securesms.components.emoji.EmojiPageModel +import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel +import org.thoughtcrime.securesms.emoji.EmojiSource.Companion.latest +import java.util.function.Consumer + +class EmojiKeyboardPageRepository(context: Context) { + + private val recentEmojiPageModel: RecentEmojiPageModel = RecentEmojiPageModel(context, EmojiKeyboardProvider.RECENT_STORAGE_KEY) + + fun getEmoji(consumer: Consumer>) { + SignalExecutors.BOUNDED.execute { + val list = mutableListOf() + list += recentEmojiPageModel + list += latest.displayPages + consumer.accept(list) + } + } +} 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 7b0ba5994d..3fd2bff653 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 @@ -1,38 +1,66 @@ package org.thoughtcrime.securesms.keyboard.emoji +import android.content.Context import androidx.lifecycle.LiveData -import androidx.lifecycle.Transformations +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider +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.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.emoji.EmojiCategory import org.thoughtcrime.securesms.emoji.EmojiSource +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.livedata.LiveDataUtil -class EmojiKeyboardPageViewModel : ViewModel() { +class EmojiKeyboardPageViewModel(repository: EmojiKeyboardPageRepository) : ViewModel() { private val internalSelectedKey = DefaultValueLiveData(getStartingTab()) val selectedKey: LiveData get() = internalSelectedKey - val categories: LiveData = Transformations.map(internalSelectedKey) { selected -> - MappingModelList().apply { - add(EmojiKeyboardPageCategoryMappingModel.RecentsMappingModel(selected == RecentEmojiPageModel.KEY)) + val allEmojiModels: MutableLiveData> = MutableLiveData() + val pages: LiveData + val categories: LiveData - EmojiCategory.values().forEach { - add(EmojiKeyboardPageCategoryMappingModel.EmojiCategoryMappingModel(it, it.key == selected)) + init { + repository.getEmoji(allEmojiModels::postValue) + + pages = LiveDataUtil.mapAsync(allEmojiModels) { models -> + val list = MappingModelList() + models.forEach { pageModel -> + list += if (RecentEmojiPageModel.KEY == pageModel.key) { + EmojiHeader(pageModel.key, R.string.ReactWithAnyEmojiBottomSheetDialogFragment__recently_used) + } else { + val category = EmojiCategory.forKey(pageModel.key) + EmojiHeader(pageModel.key, category.getCategoryLabel()) + } + + list += pageModel.toMappingModels() } + + list } - } - val pages: LiveData = Transformations.map(categories) { categories -> - MappingModelList().apply { - categories.forEach { - add(getPageForCategory(it as EmojiKeyboardPageCategoryMappingModel)) + categories = LiveDataUtil.combineLatest(allEmojiModels, internalSelectedKey) { models, selectedKey -> + val list = MappingModelList() + list += models.map { m -> + if (RecentEmojiPageModel.KEY == m.key) { + EmojiKeyboardPageCategoryMappingModel.RecentsMappingModel(m.key == selectedKey) + } else { + val category = EmojiCategory.forKey(m.key) + EmojiCategoryMappingModel(category, category.key == selectedKey) + } } + list } } @@ -63,4 +91,21 @@ class EmojiKeyboardPageViewModel : ViewModel() { } } } + + class Factory(context: Context) : ViewModelProvider.Factory { + + private val repository = EmojiKeyboardPageRepository(context) + + override fun create(modelClass: Class): T { + return requireNotNull(modelClass.cast(EmojiKeyboardPageViewModel(repository))) + } + } +} + +private fun EmojiPageModel.toMappingModels(): List> { + return if (EmojiCategory.EMOTICONS.key == key) { + displayEmoji.map { EmojiPageViewGridAdapter.EmojiTextModel(key, it) } + } else { + displayEmoji.map { EmojiPageViewGridAdapter.EmojiModel(key, it) } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java index ec42f88b22..2b8b1c4058 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiRepository.java @@ -45,7 +45,7 @@ final class ReactWithAnyEmojiRepository { emojiPages.addAll(Stream.of(EmojiSource.getLatest().getDisplayPages()) .filterNot(p -> p.getIconAttr() == EmojiCategory.EMOTICONS.getIcon()) - .map(page -> new ReactWithAnyEmojiPage(Collections.singletonList(new ReactWithAnyEmojiPageBlock(getCategoryLabel(page.getIconAttr()), page)))) + .map(page -> new ReactWithAnyEmojiPage(Collections.singletonList(new ReactWithAnyEmojiPageBlock(EmojiCategory.getCategoryLabel(page.getIconAttr()), page)))) .toList()); } @@ -89,29 +89,4 @@ final class ReactWithAnyEmojiRepository { } }); } - - private @StringRes int getCategoryLabel(@AttrRes int iconAttr) { - switch (iconAttr) { - case R.attr.emoji_category_people: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__smileys_and_people; - case R.attr.emoji_category_nature: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__nature; - case R.attr.emoji_category_foods: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__food; - case R.attr.emoji_category_activity: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__activities; - case R.attr.emoji_category_places: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__places; - case R.attr.emoji_category_objects: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__objects; - case R.attr.emoji_category_symbols: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__symbols; - case R.attr.emoji_category_flags: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__flags; - case R.attr.emoji_category_emoticons: - return R.string.ReactWithAnyEmojiBottomSheetDialogFragment__emoticons; - default: - throw new AssertionError(); - } - } } 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 7adc13ee6c..48f60eaca1 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 @@ -19,22 +19,28 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginTop="8dp" - android:layout_marginBottom="8dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" app:click_only="true" app:layout_scrollFlags="scroll|snap" + app:search_icon_tint="@color/signal_icon_tint_tab_unselected" app:search_hint="@string/KeyboardPagerFragment_search_emoji" app:show_always="true" /> - + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index ba3bb8496c..bad1a9b095 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -294,4 +294,12 @@ + + + + + + + +