Group emojis in the picker
This commit is contained in:
parent
0f55cb0388
commit
2f79b4f8b2
|
@ -31,10 +31,15 @@ class EmojiAdapter(
|
|||
private val animate: Boolean
|
||||
) : RecyclerView.Adapter<BindingHolder<ItemEmojiButtonBinding>>() {
|
||||
|
||||
private val emojiList: List<Emoji> = emojiList.filter { emoji -> emoji.visibleInPicker == null || emoji.visibleInPicker }
|
||||
private val groupedEmojiList = emojiList.filter { emoji -> emoji.visibleInPicker ?: true }
|
||||
.sortedBy { it.shortcode.lowercase(Locale.ROOT) }
|
||||
.groupBy { emoji -> emoji.category.orEmpty() }
|
||||
.toList().sortedBy { it.first.lowercase(Locale.ROOT) }.toTypedArray()
|
||||
private var currentEmojiList: List<Emoji> = groupedEmojiList.firstOrNull()?.second ?: emptyList()
|
||||
|
||||
override fun getItemCount() = emojiList.size
|
||||
override fun getItemCount() = currentEmojiList.size
|
||||
|
||||
fun getGroupedEmojiList() = groupedEmojiList
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemEmojiButtonBinding> {
|
||||
val binding = ItemEmojiButtonBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
|
@ -42,7 +47,7 @@ class EmojiAdapter(
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BindingHolder<ItemEmojiButtonBinding>, position: Int) {
|
||||
val emoji = emojiList[position]
|
||||
val emoji = currentEmojiList[position]
|
||||
val emojiImageView = holder.binding.root
|
||||
|
||||
if (animate) {
|
||||
|
@ -63,6 +68,11 @@ class EmojiAdapter(
|
|||
emojiImageView.contentDescription = emoji.shortcode
|
||||
TooltipCompat.setTooltipText(emojiImageView, emoji.shortcode)
|
||||
}
|
||||
|
||||
fun changeGroup(index: Int) {
|
||||
currentEmojiList = groupedEmojiList[index].second
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
interface OnEmojiSelectedListener {
|
||||
|
|
|
@ -33,7 +33,6 @@ import com.google.android.material.color.MaterialColors
|
|||
import com.keylesspalace.tusky.BottomSheetActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.StatusListActivity
|
||||
import com.keylesspalace.tusky.adapter.EmojiAdapter
|
||||
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
|
||||
import com.keylesspalace.tusky.databinding.ActivityAnnouncementsBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
|
@ -69,17 +68,8 @@ class AnnouncementsActivity :
|
|||
|
||||
private lateinit var adapter: AnnouncementAdapter
|
||||
|
||||
private val picker by unsafeLazy { EmojiPicker(this) }
|
||||
private val pickerDialog by unsafeLazy {
|
||||
PopupWindow(this)
|
||||
.apply {
|
||||
contentView = picker
|
||||
isFocusable = true
|
||||
setOnDismissListener {
|
||||
currentAnnouncementId = null
|
||||
}
|
||||
}
|
||||
}
|
||||
private lateinit var emojiPicker : EmojiPicker
|
||||
private lateinit var pickerDialog : PopupWindow
|
||||
private var currentAnnouncementId: String? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -110,6 +100,17 @@ class AnnouncementsActivity :
|
|||
|
||||
binding.announcementsList.adapter = adapter
|
||||
|
||||
val emojiPopupView = layoutInflater.inflate(R.layout.emoji_picker, null)
|
||||
emojiPicker = EmojiPicker(emojiPopupView)
|
||||
pickerDialog = PopupWindow(this)
|
||||
.apply {
|
||||
contentView = emojiPopupView
|
||||
isFocusable = true
|
||||
setOnDismissListener {
|
||||
currentAnnouncementId = null
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.announcements.observe(this) {
|
||||
when (it) {
|
||||
is Success -> {
|
||||
|
@ -138,7 +139,7 @@ class AnnouncementsActivity :
|
|||
}
|
||||
|
||||
viewModel.emojis.observe(this) {
|
||||
picker.adapter = EmojiAdapter(it, this, animateEmojis)
|
||||
emojiPicker.populateEmojis(it, this, animateEmojis)
|
||||
}
|
||||
|
||||
viewModel.load()
|
||||
|
|
|
@ -72,6 +72,7 @@ import com.canhub.cropper.options
|
|||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.keylesspalace.tusky.BaseActivity
|
||||
import com.keylesspalace.tusky.BuildConfig
|
||||
import com.keylesspalace.tusky.R
|
||||
|
@ -111,6 +112,7 @@ import com.keylesspalace.tusky.util.show
|
|||
import com.keylesspalace.tusky.util.unsafeLazy
|
||||
import com.keylesspalace.tusky.util.viewBinding
|
||||
import com.keylesspalace.tusky.util.visible
|
||||
import com.keylesspalace.tusky.view.EmojiPicker
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
|
@ -149,6 +151,7 @@ class ComposeActivity :
|
|||
private lateinit var emojiBehavior: BottomSheetBehavior<*>
|
||||
private lateinit var scheduleBehavior: BottomSheetBehavior<*>
|
||||
private lateinit var previewBehavior: BottomSheetBehavior<*>
|
||||
private lateinit var emojiPicker: EmojiPicker
|
||||
|
||||
/** The account that is being used to compose the status */
|
||||
private lateinit var activeAccount: AccountEntity
|
||||
|
@ -511,7 +514,8 @@ class ComposeActivity :
|
|||
composeOptionsBehavior = BottomSheetBehavior.from(binding.composeOptionsBottomSheet)
|
||||
addMediaBehavior = BottomSheetBehavior.from(binding.addMediaBottomSheet)
|
||||
scheduleBehavior = BottomSheetBehavior.from(binding.composeScheduleView)
|
||||
emojiBehavior = BottomSheetBehavior.from(binding.emojiView)
|
||||
emojiBehavior = BottomSheetBehavior.from(binding.emojiPicker)
|
||||
emojiPicker = EmojiPicker(binding.emojiPicker);
|
||||
previewBehavior = BottomSheetBehavior.from(binding.previewScroll)
|
||||
|
||||
enableButton(binding.composeEmojiButton, clickable = false, colorActive = false)
|
||||
|
@ -1296,7 +1300,7 @@ class ComposeActivity :
|
|||
private fun setEmojiList(emojiList: List<Emoji>?) {
|
||||
if (emojiList != null) {
|
||||
val animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
|
||||
binding.emojiView.adapter = EmojiAdapter(emojiList, this@ComposeActivity, animateEmojis)
|
||||
emojiPicker.populateEmojis(emojiList, this@ComposeActivity, animateEmojis)
|
||||
enableButton(binding.composeEmojiButton, true, emojiList.isNotEmpty())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,45 @@
|
|||
package com.keylesspalace.tusky.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.adapter.EmojiAdapter
|
||||
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
|
||||
class EmojiPicker @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : RecyclerView(context, attrs) {
|
||||
class EmojiPicker constructor(view: View) {
|
||||
|
||||
private val emojiView : RecyclerView
|
||||
private val tabs : TabLayout
|
||||
|
||||
init {
|
||||
clipToPadding = false
|
||||
layoutManager = GridLayoutManager(context, 3, GridLayoutManager.HORIZONTAL, false)
|
||||
emojiView = view.findViewById(R.id.emojiView)
|
||||
emojiView.apply {
|
||||
layoutManager = GridLayoutManager(view.context, 3, GridLayoutManager.HORIZONTAL, false)
|
||||
clipToPadding = false
|
||||
}
|
||||
|
||||
tabs = view.findViewById(R.id.emojiCategoryTabLayout)
|
||||
}
|
||||
|
||||
fun populateEmojis(emojis: List<Emoji>, onEmojiSelectedListener: OnEmojiSelectedListener, animateEmojis: Boolean) {
|
||||
emojiView.adapter = EmojiAdapter(emojis, onEmojiSelectedListener, animateEmojis)
|
||||
|
||||
val emojiAdapter = emojiView.adapter as EmojiAdapter
|
||||
emojiAdapter.getGroupedEmojiList().forEach { (category, _) ->
|
||||
val newTab = tabs.newTab()
|
||||
newTab.text = if (category.isEmpty()) "Unsorted" else category.removePrefix("pack:") // pleroma prefixes categories with "pack:".. why though?
|
||||
tabs.addTab(newTab)
|
||||
}
|
||||
|
||||
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||
emojiAdapter.changeGroup(tab.position)
|
||||
}
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) { }
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) { }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,19 +236,37 @@
|
|||
android:textSize="?attr/status_text_medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.keylesspalace.tusky.view.EmojiPicker
|
||||
android:id="@+id/emojiView"
|
||||
<LinearLayout
|
||||
android:id="@+id/emojiPicker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
android:orientation="vertical"
|
||||
android:elevation="12dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="60dp"
|
||||
app:behavior_hideable="true"
|
||||
app:behavior_peekHeight="0dp"
|
||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
|
||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" >
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/emojiView"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/emojiCategoryTabLayout"
|
||||
style="@style/TuskyTabAppearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
app:tabGravity="center"
|
||||
app:tabIndicatorGravity="top"
|
||||
app:tabMode="scrollable"
|
||||
app:tabTextAppearance="@style/TuskyTabAppearance" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.keylesspalace.tusky.components.compose.view.ComposeOptionsView
|
||||
android:id="@+id/composeOptionsBottomSheet"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
android:orientation="vertical"
|
||||
android:elevation="12dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:behavior_hideable="true"
|
||||
app:behavior_peekHeight="0dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/emojiView"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/emojiCategoryTabLayout"
|
||||
style="@style/TuskyTabAppearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
app:tabGravity="center"
|
||||
app:tabIndicatorGravity="top"
|
||||
app:tabMode="scrollable"
|
||||
app:tabTextAppearance="@style/TuskyTabAppearance" />
|
||||
|
||||
</LinearLayout>
|
Loading…
Reference in New Issue