Added send reaction, copy text & delete options to chat message long press menu

This commit is contained in:
Sylvain Berfini 2023-10-12 15:21:34 +02:00
parent 8269228b8a
commit faf3e887b9
5 changed files with 113 additions and 5 deletions

View file

@ -20,6 +20,9 @@
package org.linphone.ui.main.chat.fragment
import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Rect
import android.graphics.RenderEffect
import android.graphics.Shader
@ -185,16 +188,33 @@ class ConversationFragment : GenericFragment() {
null,
false
)
layout.root.setOnClickListener {
dialog.dismiss()
binding.root.setRenderEffect(null)
}
layout.setDeleteClickListener {
viewModel.deleteChatMessage(chatMessageModel)
dialog.dismiss()
}
layout.setCopyClickListener {
val text = chatMessageModel.text
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val label = "Message"
clipboard.setPrimaryClip(ClipData.newPlainText(label, text))
dialog.dismiss()
}
layout.model = chatMessageModel
chatMessageModel.dismissLongPressMenuEvent.observe(viewLifecycleOwner) {
dialog.dismiss()
}
val screenY = yPosition - AppUtils.getDimension(
R.dimen.chat_bubble_long_press_menu_bubble_offset
)
val rect = Rect()
binding.root.getGlobalVisibleRect(rect)
val height = rect.height()
@ -209,6 +229,9 @@ class ConversationFragment : GenericFragment() {
set.applyTo(constraintLayout)
dialog.setContentView(layout.root)
dialog.setOnDismissListener {
binding.root.setRenderEffect(null)
}
dialog.window
?.setLayout(

View file

@ -22,15 +22,25 @@ package org.linphone.ui.main.chat.model
import androidx.annotation.UiThread
import androidx.annotation.WorkerThread
import androidx.lifecycle.MutableLiveData
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.core.Address
import org.linphone.core.ChatMessage
import org.linphone.core.ChatMessageListenerStub
import org.linphone.core.ChatMessageReaction
import org.linphone.core.tools.Log
import org.linphone.ui.main.contacts.model.ContactAvatarModel
import org.linphone.utils.Event
import org.linphone.utils.LinphoneUtils
import org.linphone.utils.TimestampUtils
class ChatMessageModel @WorkerThread constructor(
chatMessage: ChatMessage,
val chatMessage: ChatMessage,
val avatarModel: ContactAvatarModel
) {
companion object {
private const val TAG = "[Chat Message Model]"
}
val id = chatMessage.messageId
val isOutgoing = chatMessage.isOutgoing
@ -45,13 +55,47 @@ class ChatMessageModel @WorkerThread constructor(
val time = TimestampUtils.toString(timestamp)
val dismissLongPressMenuEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
private val chatMessageListener = object : ChatMessageListenerStub() {
@WorkerThread
override fun onMsgStateChanged(message: ChatMessage, messageState: ChatMessage.State?) {
state.postValue(chatMessage.state)
}
@WorkerThread
override fun onNewMessageReaction(message: ChatMessage, reaction: ChatMessageReaction) {
Log.i(
"$TAG New reaction [${reaction.body}] from [${reaction.fromAddress.asStringUriOnly()}] for chat message with ID [$id]"
)
}
@WorkerThread
override fun onReactionRemoved(message: ChatMessage, address: Address) {
Log.i("$TAG A reaction was removed for chat message with ID [$id]")
}
}
init {
chatMessage.addListener(chatMessageListener)
state.postValue(chatMessage.state)
}
@WorkerThread
fun destroy() {
chatMessage.removeListener(chatMessageListener)
}
@UiThread
fun onLongClick(): Boolean {
return true
fun sendReaction(emoji: String) {
coreContext.postOnCoreThread {
Log.i("$TAG Sending reaction [$emoji] to chat message with ID [$id]")
val reaction = chatMessage.createReaction(emoji)
reaction.send()
dismissLongPressMenuEvent.postValue(Event(true))
}
}
@UiThread

View file

@ -35,4 +35,11 @@ class EventLogModel @WorkerThread constructor(eventLog: EventLog, avatarModel: C
}
val notifyId = eventLog.notifyId
@WorkerThread
fun destroy() {
if (model is ChatMessageModel) {
model.destroy()
}
}
}

View file

@ -32,6 +32,7 @@ import org.linphone.core.EventLog
import org.linphone.core.Factory
import org.linphone.core.Friend
import org.linphone.core.tools.Log
import org.linphone.ui.main.chat.model.ChatMessageModel
import org.linphone.ui.main.chat.model.EventLogModel
import org.linphone.ui.main.contacts.model.ContactAvatarModel
import org.linphone.ui.main.contacts.model.GroupAvatarModel
@ -129,6 +130,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
coreContext.postOnCoreThread {
chatRoom.removeListener(chatRoomListener)
events.value.orEmpty().forEach(EventLogModel::destroy)
avatarsMap.values.forEach(ContactAvatarModel::destroy)
}
}
@ -186,6 +188,25 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
}
}
@UiThread
fun deleteChatMessage(chatMessageModel: ChatMessageModel) {
coreContext.postOnCoreThread {
val eventsLogs = events.value.orEmpty()
val found = eventsLogs.find {
it.model == chatMessageModel
}
if (found != null) {
val list = arrayListOf<EventLogModel>()
list.addAll(eventsLogs)
list.remove(found)
events.postValue(list)
}
Log.i("$TAG Deleting message id [${chatMessageModel.id}]")
chatRoom.deleteMessage(chatMessageModel.chatMessage)
}
}
@WorkerThread
private fun configureChatRoom() {
computeComposingLabel()

View file

@ -4,6 +4,12 @@
<data>
<import type="android.view.View" />
<variable
name="copyClickListener"
type="View.OnClickListener" />
<variable
name="deleteClickListener"
type="View.OnClickListener" />
<variable
name="model"
type="org.linphone.ui.main.chat.model.ChatMessageModel" />
@ -35,6 +41,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/thumbs_up"
android:onClick="@{() -> model.sendReaction(@string/emoji_thumbs_up)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@ -48,6 +55,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/love"
android:onClick="@{() -> model.sendReaction(@string/emoji_love)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
@ -60,6 +68,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/laughing"
android:onClick="@{() -> model.sendReaction(@string/emoji_laughing)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
@ -72,6 +81,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/surprised"
android:onClick="@{() -> model.sendReaction(@string/emoji_surprised)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
@ -84,6 +94,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tear"
android:onClick="@{() -> model.sendReaction(@string/emoji_tear)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
@ -149,6 +160,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/copy"
android:onClick="@{copyClickListener}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/menu_copy_chat_message"
@ -175,6 +187,7 @@
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/delete"
android:onClick="@{deleteClickListener}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/menu_delete_selected_item"