Merge pull request #4945 from nextcloud/reaction_list

Reaction list
This commit is contained in:
Marcel Hibbe 2025-05-14 16:08:23 +00:00 committed by GitHub
commit af1219290d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 110 additions and 25 deletions

View File

@ -41,10 +41,13 @@ import com.nextcloud.talk.utils.ConversationUtils
import com.nextcloud.talk.utils.DateConstants
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.SpreedFeatures
import com.vanniktech.emoji.Emoji
import com.vanniktech.emoji.EmojiPopup
import com.vanniktech.emoji.EmojiTextView
import com.vanniktech.emoji.installDisableKeyboardInput
import com.vanniktech.emoji.installForceSingleEmoji
import com.vanniktech.emoji.recent.RecentEmojiManager
import com.vanniktech.emoji.search.SearchEmojiManager
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@ -246,30 +249,35 @@ class MessageActionsDialog(
isPermitted(hasChatPermission) &&
isReactableMessageType(message)
) {
checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiThumbsUp)
dialogMessageActionsBinding.emojiThumbsUp.setOnClickListener {
clickOnEmoji(message, dialogMessageActionsBinding.emojiThumbsUp.text.toString())
}
checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiThumbsDown)
dialogMessageActionsBinding.emojiThumbsDown.setOnClickListener {
clickOnEmoji(message, dialogMessageActionsBinding.emojiThumbsDown.text.toString())
}
checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiLaugh)
dialogMessageActionsBinding.emojiLaugh.setOnClickListener {
clickOnEmoji(message, dialogMessageActionsBinding.emojiLaugh.text.toString())
}
checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiHeart)
dialogMessageActionsBinding.emojiHeart.setOnClickListener {
clickOnEmoji(message, dialogMessageActionsBinding.emojiHeart.text.toString())
}
checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiConfused)
dialogMessageActionsBinding.emojiConfused.setOnClickListener {
clickOnEmoji(message, dialogMessageActionsBinding.emojiConfused.text.toString())
}
checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiSad)
dialogMessageActionsBinding.emojiSad.setOnClickListener {
clickOnEmoji(message, dialogMessageActionsBinding.emojiSad.text.toString())
val recentEmojiManager = RecentEmojiManager(context, MAX_RECENTS)
val recentEmojis = recentEmojiManager.getRecentEmojis()
val searchEmojiManager = SearchEmojiManager()
val initialSearchKeywords = listOf(
"thumbsup",
"thumbsdown",
"heart",
"joy",
"confused",
"cry",
"pray",
"fire"
)
val initialEmojisFromSearch = mutableSetOf<Emoji>()
initialSearchKeywords.forEach { keyword ->
val searchResults = searchEmojiManager.search(keyword)
if (searchResults.isNotEmpty()) {
initialEmojisFromSearch.add(searchResults[ZERO_INDEX].component1())
recentEmojiManager.addEmoji(searchResults[ZERO_INDEX].component1())
}
if (initialEmojisFromSearch.size >= MAX_RECENTS) {
return@forEach
}
}
val combinedEmojis = (recentEmojis + initialEmojisFromSearch).toList().distinct().take(MAX_RECENTS)
setupEmojiView(combinedEmojis, recentEmojiManager)
dialogMessageActionsBinding.emojiMore.setOnClickListener {
dismiss()
@ -281,6 +289,50 @@ class MessageActionsDialog(
}
}
private fun setupEmojiView(combinedEmojis: List<Emoji>, recentEmojiManager: RecentEmojiManager) {
val emojiSearchKeywords = mapOf(
"👍" to "thumbsup",
"👎" to "thumbsdown",
"❤️" to "heart",
"😂" to "joy",
"😕" to "confused",
"😢" to "cry",
"🙏" to "pray",
"🔥" to "fire"
)
val emojiTextViews = listOf(
dialogMessageActionsBinding.emojiThumbsUp,
dialogMessageActionsBinding.emojiThumbsDown,
dialogMessageActionsBinding.emojiHeart,
dialogMessageActionsBinding.emojiLaugh,
dialogMessageActionsBinding.emojiConfused,
dialogMessageActionsBinding.emojiCry,
dialogMessageActionsBinding.emojiPray,
dialogMessageActionsBinding.emojiFire
)
emojiTextViews.forEachIndexed { index, textView ->
val emoji = combinedEmojis.getOrNull(index)?.unicode
if (emoji != null) {
textView.text = emoji
checkAndSetEmojiSelfReaction(textView)
textView.setOnClickListener {
clickOnEmoji(message, emoji)
val keyword = emojiSearchKeywords[emoji] ?: ""
val result = SearchEmojiManager().search(keyword)
if (result.isNotEmpty()) {
recentEmojiManager.addEmoji(result[ZERO_INDEX].component1())
recentEmojiManager.persist()
}
}
textView.visibility = View.VISIBLE
} else {
textView.visibility = View.GONE
}
}
}
private fun isPermitted(hasChatPermission: Boolean): Boolean {
return hasChatPermission && ConversationEnums.ConversationReadOnlyState.CONVERSATION_READ_ONLY !=
currentConversation?.conversationReadOnlyState
@ -531,5 +583,7 @@ class MessageActionsDialog(
private const val DELAY: Long = 200
private const val AGE_THRESHOLD_FOR_EDIT_MESSAGE: Long = 86400000
private const val ACTOR_BOTS = "bots"
private const val ZERO_INDEX = 0
private const val MAX_RECENTS = 8
}
}

View File

@ -17,9 +17,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:id="@+id/emojiBar"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/standard_quarter_margin"
android:layout_marginTop="@dimen/standard_half_margin"
@ -84,7 +90,7 @@
android:textSize="20sp" />
<com.vanniktech.emoji.EmojiTextView
android:id="@+id/emojiSad"
android:id="@+id/emojiCry"
android:layout_width="@dimen/reaction_bottom_sheet_layout_size"
android:layout_height="@dimen/reaction_bottom_sheet_layout_size"
android:layout_marginLeft="@dimen/standard_quarter_margin"
@ -94,6 +100,28 @@
android:text="@string/emoji_sad"
android:textSize="20sp" />
<com.vanniktech.emoji.EmojiTextView
android:id="@+id/emojiPray"
android:layout_width="@dimen/reaction_bottom_sheet_layout_size"
android:layout_height="@dimen/reaction_bottom_sheet_layout_size"
android:layout_marginLeft="@dimen/standard_quarter_margin"
android:layout_marginRight="@dimen/standard_quarter_margin"
android:cursorVisible="false"
android:gravity="center"
android:text="@string/emoji_pray"
android:textSize="20sp" />
<com.vanniktech.emoji.EmojiTextView
android:id="@+id/emojiFire"
android:layout_width="@dimen/reaction_bottom_sheet_layout_size"
android:layout_height="@dimen/reaction_bottom_sheet_layout_size"
android:layout_marginLeft="@dimen/standard_quarter_margin"
android:layout_marginRight="@dimen/standard_half_margin"
android:cursorVisible="false"
android:gravity="center"
android:text="@string/emoji_fire"
android:textSize="20sp" />
<com.vanniktech.emoji.EmojiEditText
android:id="@+id/emojiMore"
android:layout_width="0dp"
@ -106,6 +134,7 @@
android:paddingStart="@dimen/zero"
android:paddingEnd="@dimen/standard_padding" />
</LinearLayout>
</HorizontalScrollView>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"

View File

@ -384,6 +384,8 @@ How to translate with transifex:
<string name="emoji_heart" translatable="false">❤️</string>
<string name="emoji_confused" translatable="false">😯</string>
<string name="emoji_sad" translatable="false">😢</string>
<string name="emoji_pray" translatable="false">🙏</string>
<string name="emoji_fire" translatable="false">🔥</string>
<string name="emoji_more" translatable="false">More emojis</string>
<string name="dontClear">Don\'t clear</string>
<string name="today">Today</string>