mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-27 09:48:33 +00:00
Added send reaction, copy text & delete options to chat message long press menu
This commit is contained in:
parent
8269228b8a
commit
faf3e887b9
5 changed files with 113 additions and 5 deletions
|
|
@ -20,6 +20,9 @@
|
||||||
package org.linphone.ui.main.chat.fragment
|
package org.linphone.ui.main.chat.fragment
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.RenderEffect
|
import android.graphics.RenderEffect
|
||||||
import android.graphics.Shader
|
import android.graphics.Shader
|
||||||
|
|
@ -185,16 +188,33 @@ class ConversationFragment : GenericFragment() {
|
||||||
null,
|
null,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
layout.root.setOnClickListener {
|
layout.root.setOnClickListener {
|
||||||
dialog.dismiss()
|
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
|
layout.model = chatMessageModel
|
||||||
|
chatMessageModel.dismissLongPressMenuEvent.observe(viewLifecycleOwner) {
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
val screenY = yPosition - AppUtils.getDimension(
|
val screenY = yPosition - AppUtils.getDimension(
|
||||||
R.dimen.chat_bubble_long_press_menu_bubble_offset
|
R.dimen.chat_bubble_long_press_menu_bubble_offset
|
||||||
)
|
)
|
||||||
|
|
||||||
val rect = Rect()
|
val rect = Rect()
|
||||||
binding.root.getGlobalVisibleRect(rect)
|
binding.root.getGlobalVisibleRect(rect)
|
||||||
val height = rect.height()
|
val height = rect.height()
|
||||||
|
|
@ -209,6 +229,9 @@ class ConversationFragment : GenericFragment() {
|
||||||
set.applyTo(constraintLayout)
|
set.applyTo(constraintLayout)
|
||||||
|
|
||||||
dialog.setContentView(layout.root)
|
dialog.setContentView(layout.root)
|
||||||
|
dialog.setOnDismissListener {
|
||||||
|
binding.root.setRenderEffect(null)
|
||||||
|
}
|
||||||
|
|
||||||
dialog.window
|
dialog.window
|
||||||
?.setLayout(
|
?.setLayout(
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,25 @@ package org.linphone.ui.main.chat.model
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.core.Address
|
||||||
import org.linphone.core.ChatMessage
|
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.ui.main.contacts.model.ContactAvatarModel
|
||||||
|
import org.linphone.utils.Event
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
import org.linphone.utils.TimestampUtils
|
import org.linphone.utils.TimestampUtils
|
||||||
|
|
||||||
class ChatMessageModel @WorkerThread constructor(
|
class ChatMessageModel @WorkerThread constructor(
|
||||||
chatMessage: ChatMessage,
|
val chatMessage: ChatMessage,
|
||||||
val avatarModel: ContactAvatarModel
|
val avatarModel: ContactAvatarModel
|
||||||
) {
|
) {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "[Chat Message Model]"
|
||||||
|
}
|
||||||
|
|
||||||
val id = chatMessage.messageId
|
val id = chatMessage.messageId
|
||||||
|
|
||||||
val isOutgoing = chatMessage.isOutgoing
|
val isOutgoing = chatMessage.isOutgoing
|
||||||
|
|
@ -45,13 +55,47 @@ class ChatMessageModel @WorkerThread constructor(
|
||||||
|
|
||||||
val time = TimestampUtils.toString(timestamp)
|
val time = TimestampUtils.toString(timestamp)
|
||||||
|
|
||||||
init {
|
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)
|
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
|
@UiThread
|
||||||
fun onLongClick(): Boolean {
|
fun sendReaction(emoji: String) {
|
||||||
return true
|
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
|
@UiThread
|
||||||
|
|
|
||||||
|
|
@ -35,4 +35,11 @@ class EventLogModel @WorkerThread constructor(eventLog: EventLog, avatarModel: C
|
||||||
}
|
}
|
||||||
|
|
||||||
val notifyId = eventLog.notifyId
|
val notifyId = eventLog.notifyId
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
fun destroy() {
|
||||||
|
if (model is ChatMessageModel) {
|
||||||
|
model.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import org.linphone.core.EventLog
|
||||||
import org.linphone.core.Factory
|
import org.linphone.core.Factory
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
import org.linphone.core.tools.Log
|
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.chat.model.EventLogModel
|
||||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||||
import org.linphone.ui.main.contacts.model.GroupAvatarModel
|
import org.linphone.ui.main.contacts.model.GroupAvatarModel
|
||||||
|
|
@ -129,6 +130,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
||||||
|
|
||||||
coreContext.postOnCoreThread {
|
coreContext.postOnCoreThread {
|
||||||
chatRoom.removeListener(chatRoomListener)
|
chatRoom.removeListener(chatRoomListener)
|
||||||
|
events.value.orEmpty().forEach(EventLogModel::destroy)
|
||||||
avatarsMap.values.forEach(ContactAvatarModel::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
|
@WorkerThread
|
||||||
private fun configureChatRoom() {
|
private fun configureChatRoom() {
|
||||||
computeComposingLabel()
|
computeComposingLabel()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
<variable
|
||||||
|
name="copyClickListener"
|
||||||
|
type="View.OnClickListener" />
|
||||||
|
<variable
|
||||||
|
name="deleteClickListener"
|
||||||
|
type="View.OnClickListener" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.chat.model.ChatMessageModel" />
|
type="org.linphone.ui.main.chat.model.ChatMessageModel" />
|
||||||
|
|
@ -35,6 +41,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/thumbs_up"
|
android:id="@+id/thumbs_up"
|
||||||
|
android:onClick="@{() -> model.sendReaction(@string/emoji_thumbs_up)}"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
|
|
@ -48,6 +55,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/love"
|
android:id="@+id/love"
|
||||||
|
android:onClick="@{() -> model.sendReaction(@string/emoji_love)}"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
|
@ -60,6 +68,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/laughing"
|
android:id="@+id/laughing"
|
||||||
|
android:onClick="@{() -> model.sendReaction(@string/emoji_laughing)}"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
|
@ -72,6 +81,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/surprised"
|
android:id="@+id/surprised"
|
||||||
|
android:onClick="@{() -> model.sendReaction(@string/emoji_surprised)}"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
|
@ -84,6 +94,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/tear"
|
android:id="@+id/tear"
|
||||||
|
android:onClick="@{() -> model.sendReaction(@string/emoji_tear)}"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
|
@ -149,6 +160,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/copy"
|
android:id="@+id/copy"
|
||||||
|
android:onClick="@{copyClickListener}"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/menu_copy_chat_message"
|
android:text="@string/menu_copy_chat_message"
|
||||||
|
|
@ -175,6 +187,7 @@
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
|
android:onClick="@{deleteClickListener}"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/menu_delete_selected_item"
|
android:text="@string/menu_delete_selected_item"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue