Added reply to chat message feature
This commit is contained in:
parent
80fa401d5b
commit
f7710e2ae2
34 changed files with 528 additions and 16 deletions
|
@ -29,7 +29,7 @@ if (crashlyticsEnabled()) {
|
||||||
|
|
||||||
def gitBranch = new ByteArrayOutputStream()
|
def gitBranch = new ByteArrayOutputStream()
|
||||||
task getGitVersion() {
|
task getGitVersion() {
|
||||||
def gitVersion = "4.5.0"
|
def gitVersion = "4.6.0"
|
||||||
def gitVersionStream = new ByteArrayOutputStream()
|
def gitVersionStream = new ByteArrayOutputStream()
|
||||||
def gitCommitsCount = new ByteArrayOutputStream()
|
def gitCommitsCount = new ByteArrayOutputStream()
|
||||||
def gitCommitHash = new ByteArrayOutputStream()
|
def gitCommitHash = new ByteArrayOutputStream()
|
||||||
|
@ -269,7 +269,7 @@ dependencies {
|
||||||
implementation 'com.google.firebase:firebase-messaging'
|
implementation 'com.google.firebase:firebase-messaging'
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation 'org.linphone:linphone-sdk-android:5.0+'
|
implementation 'org.linphone:linphone-sdk-android:5.1+'
|
||||||
|
|
||||||
// Only enable leak canary prior to release
|
// Only enable leak canary prior to release
|
||||||
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
|
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
|
||||||
|
|
|
@ -69,6 +69,10 @@ class ChatMessagesListAdapter(
|
||||||
MutableLiveData<Event<ChatMessage>>()
|
MutableLiveData<Event<ChatMessage>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val replyMessageEvent: MutableLiveData<Event<ChatMessage>> by lazy {
|
||||||
|
MutableLiveData<Event<ChatMessage>>()
|
||||||
|
}
|
||||||
|
|
||||||
val showImdnForMessageEvent: MutableLiveData<Event<ChatMessage>> by lazy {
|
val showImdnForMessageEvent: MutableLiveData<Event<ChatMessage>> by lazy {
|
||||||
MutableLiveData<Event<ChatMessage>>()
|
MutableLiveData<Event<ChatMessage>>()
|
||||||
}
|
}
|
||||||
|
@ -81,6 +85,10 @@ class ChatMessagesListAdapter(
|
||||||
MutableLiveData<Event<Content>>()
|
MutableLiveData<Event<Content>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val scrollToChatMessageEvent: MutableLiveData<Event<ChatMessage>> by lazy {
|
||||||
|
MutableLiveData<Event<ChatMessage>>()
|
||||||
|
}
|
||||||
|
|
||||||
private val contentClickedListener = object : OnContentClickedListener {
|
private val contentClickedListener = object : OnContentClickedListener {
|
||||||
override fun onContentClicked(content: Content) {
|
override fun onContentClicked(content: Content) {
|
||||||
openContentEvent.value = Event(content)
|
openContentEvent.value = Event(content)
|
||||||
|
@ -155,6 +163,13 @@ class ChatMessagesListAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setReplyClickListener {
|
||||||
|
val reply = chatMessageViewModel.replyData.value?.chatMessage
|
||||||
|
if (reply != null) {
|
||||||
|
scrollToChatMessageEvent.value = Event(reply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Grouping
|
// Grouping
|
||||||
var hasPrevious = false
|
var hasPrevious = false
|
||||||
var hasNext = false
|
var hasNext = false
|
||||||
|
@ -196,7 +211,7 @@ class ChatMessagesListAdapter(
|
||||||
)
|
)
|
||||||
|
|
||||||
val itemSize = AppUtils.getDimension(R.dimen.chat_message_popup_item_height).toInt()
|
val itemSize = AppUtils.getDimension(R.dimen.chat_message_popup_item_height).toInt()
|
||||||
var totalSize = itemSize * 6
|
var totalSize = itemSize * 7
|
||||||
if (chatMessage.chatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt()) ||
|
if (chatMessage.chatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt()) ||
|
||||||
chatMessage.state == ChatMessage.State.NotDelivered) { // No message id
|
chatMessage.state == ChatMessage.State.NotDelivered) { // No message id
|
||||||
popupView.imdnHidden = true
|
popupView.imdnHidden = true
|
||||||
|
@ -237,6 +252,10 @@ class ChatMessagesListAdapter(
|
||||||
forwardMessage()
|
forwardMessage()
|
||||||
popupWindow.dismiss()
|
popupWindow.dismiss()
|
||||||
}
|
}
|
||||||
|
popupView.setReplyClickListener {
|
||||||
|
replyMessage()
|
||||||
|
popupWindow.dismiss()
|
||||||
|
}
|
||||||
popupView.setImdnClickListener {
|
popupView.setImdnClickListener {
|
||||||
showImdnDeliveryFragment()
|
showImdnDeliveryFragment()
|
||||||
popupWindow.dismiss()
|
popupWindow.dismiss()
|
||||||
|
@ -287,6 +306,13 @@ class ChatMessagesListAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun replyMessage() {
|
||||||
|
val chatMessage = binding.data?.chatMessage
|
||||||
|
if (chatMessage != null) {
|
||||||
|
replyMessageEvent.value = Event(chatMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showImdnDeliveryFragment() {
|
private fun showImdnDeliveryFragment() {
|
||||||
val chatMessage = binding.data?.chatMessage
|
val chatMessage = binding.data?.chatMessage
|
||||||
if (chatMessage != null) {
|
if (chatMessage != null) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.linphone.R
|
||||||
import org.linphone.contact.GenericContactData
|
import org.linphone.contact.GenericContactData
|
||||||
import org.linphone.core.ChatMessage
|
import org.linphone.core.ChatMessage
|
||||||
import org.linphone.core.ChatMessageListenerStub
|
import org.linphone.core.ChatMessageListenerStub
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.utils.AppUtils
|
import org.linphone.utils.AppUtils
|
||||||
import org.linphone.utils.TimestampUtils
|
import org.linphone.utils.TimestampUtils
|
||||||
|
|
||||||
|
@ -56,6 +57,8 @@ class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMes
|
||||||
|
|
||||||
val text = MutableLiveData<Spannable>()
|
val text = MutableLiveData<Spannable>()
|
||||||
|
|
||||||
|
val replyData = MutableLiveData<ChatMessageData>()
|
||||||
|
|
||||||
private var countDownTimer: CountDownTimer? = null
|
private var countDownTimer: CountDownTimer? = null
|
||||||
|
|
||||||
private val listener = object : ChatMessageListenerStub() {
|
private val listener = object : ChatMessageListenerStub() {
|
||||||
|
@ -74,6 +77,15 @@ class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMes
|
||||||
|
|
||||||
backgroundRes.value = if (chatMessage.isOutgoing) R.drawable.chat_bubble_outgoing_full else R.drawable.chat_bubble_incoming_full
|
backgroundRes.value = if (chatMessage.isOutgoing) R.drawable.chat_bubble_outgoing_full else R.drawable.chat_bubble_incoming_full
|
||||||
hideAvatar.value = false
|
hideAvatar.value = false
|
||||||
|
|
||||||
|
if (chatMessage.isReply) {
|
||||||
|
val reply = chatMessage.replyMessage
|
||||||
|
if (reply != null) {
|
||||||
|
Log.i("[Chat Message Data] Message is a reply of message id [${chatMessage.replyMessageId}] sent by [${chatMessage.replyMessageSenderAddress?.asStringUriOnly()}]")
|
||||||
|
replyData.value = ChatMessageData(reply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
time.value = TimestampUtils.toString(chatMessage.time)
|
time.value = TimestampUtils.toString(chatMessage.time)
|
||||||
updateEphemeralTimer()
|
updateEphemeralTimer()
|
||||||
|
|
||||||
|
@ -84,6 +96,10 @@ class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMes
|
||||||
override fun destroy() {
|
override fun destroy() {
|
||||||
super.destroy()
|
super.destroy()
|
||||||
|
|
||||||
|
if (chatMessage.isReply) {
|
||||||
|
replyData.value?.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
contents.value.orEmpty().forEach(ChatMessageContentData::destroy)
|
contents.value.orEmpty().forEach(ChatMessageContentData::destroy)
|
||||||
chatMessage.removeListener(listener)
|
chatMessage.removeListener(listener)
|
||||||
contentListener = null
|
contentListener = null
|
||||||
|
|
|
@ -39,6 +39,7 @@ import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
|
@ -47,6 +48,7 @@ import org.linphone.activities.*
|
||||||
import org.linphone.activities.main.MainActivity
|
import org.linphone.activities.main.MainActivity
|
||||||
import org.linphone.activities.main.chat.ChatScrollListener
|
import org.linphone.activities.main.chat.ChatScrollListener
|
||||||
import org.linphone.activities.main.chat.adapters.ChatMessagesListAdapter
|
import org.linphone.activities.main.chat.adapters.ChatMessagesListAdapter
|
||||||
|
import org.linphone.activities.main.chat.data.ChatMessageData
|
||||||
import org.linphone.activities.main.chat.data.EventLogData
|
import org.linphone.activities.main.chat.data.EventLogData
|
||||||
import org.linphone.activities.main.chat.viewmodels.*
|
import org.linphone.activities.main.chat.viewmodels.*
|
||||||
import org.linphone.activities.main.fragments.MasterFragment
|
import org.linphone.activities.main.fragments.MasterFragment
|
||||||
|
@ -166,6 +168,28 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
||||||
layoutManager.stackFromEnd = true
|
layoutManager.stackFromEnd = true
|
||||||
binding.chatMessagesList.layoutManager = layoutManager
|
binding.chatMessagesList.layoutManager = layoutManager
|
||||||
|
|
||||||
|
// Swipe action
|
||||||
|
/*val swipeConfiguration = RecyclerViewSwipeConfiguration()
|
||||||
|
swipeConfiguration.leftToRightAction = RecyclerViewSwipeConfiguration.Action(icon = R.drawable.menu_reply_default)
|
||||||
|
val swipeListener = object : RecyclerViewSwipeListener {
|
||||||
|
override fun onLeftToRightSwipe(viewHolder: RecyclerView.ViewHolder) {
|
||||||
|
adapter.notifyItemChanged(viewHolder.adapterPosition)
|
||||||
|
|
||||||
|
val chatMessageEventLog = adapter.currentList[viewHolder.adapterPosition]
|
||||||
|
val chatMessage = chatMessageEventLog.chatMessage
|
||||||
|
if (chatMessage != null) {
|
||||||
|
chatSendingViewModel.pendingChatMessageToReplyTo.value?.destroy()
|
||||||
|
chatSendingViewModel.pendingChatMessageToReplyTo.value =
|
||||||
|
ChatMessageData(chatMessage)
|
||||||
|
chatSendingViewModel.isPendingAnswer.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRightToLeftSwipe(viewHolder: RecyclerView.ViewHolder) {}
|
||||||
|
}
|
||||||
|
RecyclerViewSwipeUtils(ItemTouchHelper.RIGHT, swipeConfiguration, swipeListener)
|
||||||
|
.attachToRecyclerView(binding.chatMessagesList)*/
|
||||||
|
|
||||||
val chatScrollListener: ChatScrollListener = object : ChatScrollListener(layoutManager) {
|
val chatScrollListener: ChatScrollListener = object : ChatScrollListener(layoutManager) {
|
||||||
override fun onLoadMore(totalItemsCount: Int) {
|
override fun onLoadMore(totalItemsCount: Int) {
|
||||||
listViewModel.loadMoreData(totalItemsCount)
|
listViewModel.loadMoreData(totalItemsCount)
|
||||||
|
@ -216,6 +240,14 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
adapter.replyMessageEvent.observe(viewLifecycleOwner, {
|
||||||
|
it.consume { chatMessage ->
|
||||||
|
chatSendingViewModel.pendingChatMessageToReplyTo.value?.destroy()
|
||||||
|
chatSendingViewModel.pendingChatMessageToReplyTo.value = ChatMessageData(chatMessage)
|
||||||
|
chatSendingViewModel.isPendingAnswer.value = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
adapter.showImdnForMessageEvent.observe(viewLifecycleOwner, {
|
adapter.showImdnForMessageEvent.observe(viewLifecycleOwner, {
|
||||||
it.consume { chatMessage ->
|
it.consume { chatMessage ->
|
||||||
val args = Bundle()
|
val args = Bundle()
|
||||||
|
@ -278,6 +310,23 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
adapter.scrollToChatMessageEvent.observe(viewLifecycleOwner, {
|
||||||
|
it.consume { chatMessage ->
|
||||||
|
val events = listViewModel.events.value.orEmpty()
|
||||||
|
val eventLog = events.find { eventLog ->
|
||||||
|
if (eventLog.eventLog.type == EventLog.Type.ConferenceChatMessage) {
|
||||||
|
(eventLog.data as ChatMessageData).chatMessage.messageId == chatMessage.messageId
|
||||||
|
} else false
|
||||||
|
}
|
||||||
|
val index = events.indexOf(eventLog)
|
||||||
|
try {
|
||||||
|
binding.chatMessagesList.smoothScrollToPosition(index)
|
||||||
|
} catch (iae: IllegalArgumentException) {
|
||||||
|
Log.e("[Chat Room] Can't scroll to position $index")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
binding.setBackClickListener {
|
binding.setBackClickListener {
|
||||||
goBack()
|
goBack()
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.activities.main.chat.data.ChatMessageAttachmentData
|
import org.linphone.activities.main.chat.data.ChatMessageAttachmentData
|
||||||
|
import org.linphone.activities.main.chat.data.ChatMessageData
|
||||||
import org.linphone.core.ChatMessage
|
import org.linphone.core.ChatMessage
|
||||||
import org.linphone.core.ChatRoom
|
import org.linphone.core.ChatRoom
|
||||||
import org.linphone.core.ChatRoomCapabilities
|
import org.linphone.core.ChatRoomCapabilities
|
||||||
|
@ -53,6 +54,10 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
|
|
||||||
var textToSend = MutableLiveData<String>()
|
var textToSend = MutableLiveData<String>()
|
||||||
|
|
||||||
|
val isPendingAnswer = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
var pendingChatMessageToReplyTo = MutableLiveData<ChatMessageData>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
attachments.value = arrayListOf()
|
attachments.value = arrayListOf()
|
||||||
|
|
||||||
|
@ -108,14 +113,18 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMessage() {
|
fun sendMessage() {
|
||||||
val isBasicChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt())
|
val pendingMessageToReplyTo = pendingChatMessageToReplyTo.value
|
||||||
val message: ChatMessage = chatRoom.createEmptyMessage()
|
val message: ChatMessage = if (isPendingAnswer.value == true && pendingMessageToReplyTo != null)
|
||||||
|
chatRoom.createReplyMessage(pendingMessageToReplyTo.chatMessage)
|
||||||
|
else
|
||||||
|
chatRoom.createEmptyMessage()
|
||||||
|
|
||||||
val toSend = textToSend.value
|
val toSend = textToSend.value
|
||||||
if (toSend != null && toSend.isNotEmpty()) {
|
if (toSend != null && toSend.isNotEmpty()) {
|
||||||
message.addUtf8TextContent(toSend.trim())
|
message.addUtf8TextContent(toSend.trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isBasicChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt())
|
||||||
var fileContent = false
|
var fileContent = false
|
||||||
for (attachment in attachments.value.orEmpty()) {
|
for (attachment in attachments.value.orEmpty()) {
|
||||||
val content = Factory.instance().createContent()
|
val content = Factory.instance().createContent()
|
||||||
|
@ -144,6 +153,7 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
message.send()
|
message.send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelReply()
|
||||||
attachments.value.orEmpty().forEach(ChatMessageAttachmentData::destroy)
|
attachments.value.orEmpty().forEach(ChatMessageAttachmentData::destroy)
|
||||||
attachments.value = arrayListOf()
|
attachments.value = arrayListOf()
|
||||||
}
|
}
|
||||||
|
@ -152,4 +162,9 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
val message = chatRoom.createForwardMessage(chatMessage)
|
val message = chatRoom.createForwardMessage(chatMessage)
|
||||||
message.send()
|
message.send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cancelReply() {
|
||||||
|
pendingChatMessageToReplyTo.value?.destroy()
|
||||||
|
isPendingAnswer.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,15 @@ class LinphoneUtils {
|
||||||
private const val RECORDING_DATE_PATTERN = "dd-MM-yyyy-HH-mm-ss"
|
private const val RECORDING_DATE_PATTERN = "dd-MM-yyyy-HH-mm-ss"
|
||||||
|
|
||||||
fun getDisplayName(address: Address): String {
|
fun getDisplayName(address: Address): String {
|
||||||
|
if (address.displayName == null) {
|
||||||
|
val account = coreContext.core.accountList.find { account ->
|
||||||
|
account.params.identityAddress?.asStringUriOnly() == address.asStringUriOnly()
|
||||||
|
}
|
||||||
|
val localDisplayName = account?.params?.identityAddress?.displayName
|
||||||
|
if (localDisplayName != null) {
|
||||||
|
return localDisplayName
|
||||||
|
}
|
||||||
|
}
|
||||||
return address.displayName ?: address.username ?: ""
|
return address.displayName ?: address.username ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
app/src/main/res/drawable-xhdpi/menu_reply_default.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/menu_reply_default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
app/src/main/res/drawable-xhdpi/replied_message_default.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/replied_message_default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8 KiB |
BIN
app/src/main/res/drawable-xhdpi/reply_message_default.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/reply_message_default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_incoming_color"/>
|
<solid android:color="@color/chat_bubble_incoming_color"/>
|
||||||
<corners android:radius="6.7dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_incoming_color"/>
|
<solid android:color="@color/chat_bubble_incoming_color"/>
|
||||||
<corners android:radius="6.7dp" android:bottomLeftRadius="0dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:bottomLeftRadius="0dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_incoming_color"/>
|
<solid android:color="@color/chat_bubble_incoming_color"/>
|
||||||
<corners android:radius="6.7dp" android:topLeftRadius="0dp" android:bottomLeftRadius="0dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:topLeftRadius="0dp" android:bottomLeftRadius="0dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_incoming_color"/>
|
<solid android:color="@color/chat_bubble_incoming_color"/>
|
||||||
<corners android:radius="6.7dp" android:topLeftRadius="0dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:topLeftRadius="0dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
||||||
<corners android:radius="6.7dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
||||||
<corners android:radius="6.7dp" android:bottomRightRadius="0dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:bottomRightRadius="0dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
||||||
<corners android:radius="6.7dp" android:topRightRadius="0dp" android:bottomRightRadius="0dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:topRightRadius="0dp" android:bottomRightRadius="0dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
<solid android:color="@color/chat_bubble_outgoing_color"/>
|
||||||
<corners android:radius="6.7dp" android:topRightRadius="0dp"/>
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:topRightRadius="0dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="?attr/backgroundColor"/>
|
||||||
|
<corners android:radius="@dimen/chat_message_round_corner_radius"/>
|
||||||
|
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/chat_bubble_file_background_color"/>
|
||||||
|
<stroke android:color="@color/chat_bubble_file_background_border_color" android:width="1dp" />
|
||||||
|
<corners android:radius="@dimen/chat_message_round_corner_radius"/>
|
||||||
|
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="@color/chat_bubble_incoming_color_dark"/>
|
||||||
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:topRightRadius="0dp" android:bottomRightRadius="0dp"/>
|
||||||
|
</shape>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="@color/chat_bubble_outgoing_color_dark"/>
|
||||||
|
<corners android:radius="@dimen/chat_message_round_corner_radius" android:topRightRadius="0dp" android:bottomRightRadius="0dp"/>
|
||||||
|
</shape>
|
7
app/src/main/res/drawable/menu_reply.xml
Normal file
7
app/src/main/res/drawable/menu_reply.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<bitmap android:src="@drawable/menu_reply_default"
|
||||||
|
android:tint="?attr/drawableTintColor"/>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -13,6 +13,9 @@
|
||||||
<variable
|
<variable
|
||||||
name="clickListener"
|
name="clickListener"
|
||||||
type="android.view.View.OnClickListener" />
|
type="android.view.View.OnClickListener" />
|
||||||
|
<variable
|
||||||
|
name="replyClickListener"
|
||||||
|
type="android.view.View.OnClickListener" />
|
||||||
<variable
|
<variable
|
||||||
name="position"
|
name="position"
|
||||||
type="Integer"/>
|
type="Integer"/>
|
||||||
|
@ -90,7 +93,6 @@
|
||||||
android:layout_marginBottom="1dp"
|
android:layout_marginBottom="1dp"
|
||||||
android:layout_marginRight="@{data.chatMessage.outgoing ? @dimen/outgoing_chat_message_bubble_right_margin : @dimen/incoming_chat_message_bubble_right_margin}"
|
android:layout_marginRight="@{data.chatMessage.outgoing ? @dimen/outgoing_chat_message_bubble_right_margin : @dimen/incoming_chat_message_bubble_right_margin}"
|
||||||
android:layout_marginLeft="@{selectionListViewModel.isEditionEnabled ? @dimen/edit_chat_message_bubble_left_margin : !data.chatMessage.outgoing ? @dimen/incoming_chat_message_bubble_left_margin : @dimen/outgoing_chat_message_bubble_left_margin}"
|
android:layout_marginLeft="@{selectionListViewModel.isEditionEnabled ? @dimen/edit_chat_message_bubble_left_margin : !data.chatMessage.outgoing ? @dimen/incoming_chat_message_bubble_left_margin : @dimen/outgoing_chat_message_bubble_left_margin}"
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="5dp">
|
android:paddingBottom="5dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -98,7 +100,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical|right"
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="5dp"
|
||||||
android:layout_marginLeft="5dp">
|
android:layout_marginLeft="5dp">
|
||||||
|
|
||||||
|
@ -123,9 +126,52 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="@{data.chatMessage.reply ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_marginLeft="5dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:src="@drawable/replied_message_default"
|
||||||
|
android:contentDescription="@string/content_description_replied_message"
|
||||||
|
android:layout_marginRight="3dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/chat_bubble_text_color"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textStyle="normal"
|
||||||
|
android:lineSpacingExtra="3.3sp"
|
||||||
|
android:text="@string/chat_message_replied"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/chat_message_reply_bubble"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_gravity="@{data.chatMessage.outgoing ? Gravity.RIGHT : Gravity.LEFT}"
|
||||||
|
app:data="@{data.replyData}"
|
||||||
|
app:clickListener="@{replyClickListener}"
|
||||||
|
android:visibility="@{data.chatMessage.reply ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="5dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="5dp"
|
||||||
android:longClickable="true"
|
android:longClickable="true"
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
<variable
|
<variable
|
||||||
name="forwardClickListener"
|
name="forwardClickListener"
|
||||||
type="View.OnClickListener" />
|
type="View.OnClickListener" />
|
||||||
|
<variable
|
||||||
|
name="replyClickListener"
|
||||||
|
type="View.OnClickListener" />
|
||||||
<variable
|
<variable
|
||||||
name="imdnClickListener"
|
name="imdnClickListener"
|
||||||
type="View.OnClickListener" />
|
type="View.OnClickListener" />
|
||||||
|
@ -70,6 +73,15 @@
|
||||||
style="@style/popup_item_font"
|
style="@style/popup_item_font"
|
||||||
android:text="@string/chat_message_context_menu_forward" />
|
android:text="@string/chat_message_context_menu_forward" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/chat_message_popup_item_height"
|
||||||
|
android:background="@drawable/menu_background"
|
||||||
|
android:onClick="@{replyClickListener}"
|
||||||
|
android:drawableRight="@drawable/menu_reply"
|
||||||
|
style="@style/popup_item_font"
|
||||||
|
android:text="@string/chat_message_context_menu_reply" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/chat_message_popup_item_height"
|
android:layout_height="@dimen/chat_message_popup_item_height"
|
||||||
|
|
74
app/src/main/res/layout/chat_message_reply.xml
Normal file
74
app/src/main/res/layout/chat_message_reply.xml
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="cancelClickListener"
|
||||||
|
type="android.view.View.OnClickListener" />
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.main.chat.data.ChatMessageData" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:background="@{data.chatMessage.isOutgoing ? @color/chat_bubble_outgoing_color : @color/chat_bubble_incoming_color, default=@color/chat_bubble_incoming_color}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_toLeftOf="@id/clear_reply">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/chat_message_reply_sender_font"
|
||||||
|
android:text="@{data.contact.fullName ?? data.displayName, default=Tintin}"/>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:visibility="@{data.contents.size() == 0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:entries="@{data.contents}"
|
||||||
|
app:layout="@{@layout/chat_message_reply_preview_content_cell}"/>
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:visibility="@{data.text.length() == 0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
style="@style/chat_message_reply_font"
|
||||||
|
android:text="@{data.text, default=`Lorem Ipsum`}"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/clear_reply"
|
||||||
|
android:onClick="@{cancelClickListener}"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:src="@drawable/field_clean" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
79
app/src/main/res/layout/chat_message_reply_bubble.xml
Normal file
79
app/src/main/res/layout/chat_message_reply_bubble.xml
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="clickListener"
|
||||||
|
type="android.view.View.OnClickListener" />
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.main.chat.data.ChatMessageData" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:background="@drawable/chat_bubble_reply_background"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:onClick="@{clickListener}">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/color"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@{data.chatMessage.isOutgoing ? @drawable/chat_bubble_reply_outgoing_indicator : @drawable/chat_bubble_reply_incoming_indicator, default=@drawable/chat_bubble_reply_outgoing_indicator}" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:visibility="@{data.contents.size() > 0 ? View.VISIBLE : View.GONE}">
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintWidth_max="120dp"
|
||||||
|
app:entries="@{data.contents}"
|
||||||
|
app:layout="@{@layout/chat_message_reply_content_cell}"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:alignItems="center"
|
||||||
|
app:justifyContent="flex_start"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/chat_message_reply_sender_font"
|
||||||
|
android:text="@{data.contact.fullName ?? data.displayName, default=Tintin}"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:visibility="@{data.text.length() == 0 ? View.GONE : View.VISIBLE}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
style="@style/chat_message_reply_font"
|
||||||
|
android:text="@{data.text, default=`Lorem ipsum`}"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</layout>
|
61
app/src/main/res/layout/chat_message_reply_content_cell.xml
Normal file
61
app/src/main/res/layout/chat_message_reply_content_cell.xml
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<import type="android.widget.ImageView.ScaleType"/>
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.main.chat.data.ChatMessageContentData" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:contentDescription="@string/content_description_downloaded_file_transfer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxHeight="@dimen/chat_message_bubble_image_height_small"
|
||||||
|
android:layout_size="@{data.alone ? 0f : @dimen/chat_message_small_bubble_file_size}"
|
||||||
|
app:glidePath="@{data.filePath}"
|
||||||
|
android:visibility="@{data.image ? View.VISIBLE : View.GONE}"
|
||||||
|
android:scaleType="@{ScaleType.CENTER_CROP}"
|
||||||
|
android:adjustViewBounds="true" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:contentDescription="@string/content_description_downloaded_file_transfer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxHeight="@dimen/chat_message_bubble_image_height_small"
|
||||||
|
android:layout_size="@{data.alone ? 0f : @dimen/chat_message_small_bubble_file_size}"
|
||||||
|
android:src="@{data.videoPreview}"
|
||||||
|
android:visibility="@{data.video ? View.VISIBLE : View.GONE}"
|
||||||
|
android:scaleType="@{ScaleType.CENTER_CROP}"
|
||||||
|
android:adjustViewBounds="true" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:visibility="@{data.video ? View.VISIBLE : View.GONE}"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:src="@drawable/recording_play_pause"
|
||||||
|
android:contentDescription="@string/content_description_chat_message_video_attachment"
|
||||||
|
android:layout_centerInParent="true"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxHeight="@dimen/chat_message_bubble_image_height_small"
|
||||||
|
android:layout_size="@{data.alone ? 0f : @dimen/chat_message_small_bubble_file_size}"
|
||||||
|
android:background="@drawable/chat_bubble_reply_file_background"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:contentDescription="@{data.fileName}"
|
||||||
|
android:visibility="@{data.downloadable || data.pdf || data.audio || data.genericFile ? View.VISIBLE : View.GONE}"
|
||||||
|
android:src="@{data.video ? @drawable/file_video : (data.image ? @drawable/file_picture : (data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : @drawable/file))), default=@drawable/file}" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<import type="android.widget.ImageView.ScaleType"/>
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.main.chat.data.ChatMessageContentData" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:contentDescription="@string/content_description_downloaded_file_transfer"
|
||||||
|
android:layout_width="@dimen/chat_message_small_bubble_file_size"
|
||||||
|
android:layout_height="@dimen/chat_message_small_bubble_file_size"
|
||||||
|
app:glidePath="@{data.filePath}"
|
||||||
|
android:visibility="@{data.image ? View.VISIBLE : View.GONE}"
|
||||||
|
android:scaleType="@{ScaleType.CENTER_CROP}"
|
||||||
|
android:adjustViewBounds="true" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:contentDescription="@string/content_description_downloaded_file_transfer"
|
||||||
|
android:layout_width="@dimen/chat_message_small_bubble_file_size"
|
||||||
|
android:layout_height="@dimen/chat_message_small_bubble_file_size"
|
||||||
|
android:src="@{data.videoPreview}"
|
||||||
|
android:visibility="@{data.video ? View.VISIBLE : View.GONE}"
|
||||||
|
android:scaleType="@{ScaleType.CENTER_CROP}"
|
||||||
|
android:adjustViewBounds="true" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:visibility="@{data.video ? View.VISIBLE : View.GONE}"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:src="@drawable/recording_play_pause"
|
||||||
|
android:contentDescription="@string/content_description_chat_message_video_attachment"
|
||||||
|
android:layout_centerInParent="true"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@dimen/chat_message_small_bubble_file_size"
|
||||||
|
android:layout_height="@dimen/chat_message_small_bubble_file_size"
|
||||||
|
android:background="@drawable/chat_bubble_reply_file_background"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:contentDescription="@{data.fileName}"
|
||||||
|
android:visibility="@{data.downloadable || data.pdf || data.audio || data.genericFile ? View.VISIBLE : View.GONE}"
|
||||||
|
android:src="@{data.video ? @drawable/file_video : (data.image ? @drawable/file_picture : (data.pdf ? @drawable/file_pdf : (data.audio ? @drawable/file_audio : @drawable/file))), default=@drawable/file}" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
|
@ -147,6 +147,12 @@
|
||||||
android:background="?attr/lightToolbarBackgroundColor"
|
android:background="?attr/lightToolbarBackgroundColor"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:visibility="@{chatSendingViewModel.isPendingAnswer ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:data="@{chatSendingViewModel.pendingChatMessageToReplyTo}"
|
||||||
|
app:cancelClickListener="@{() -> chatSendingViewModel.cancelReply()}"
|
||||||
|
layout="@layout/chat_message_reply" />
|
||||||
|
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -166,7 +172,9 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="?attr/backgroundColor"
|
android:background="@color/toolbar_color"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -182,6 +190,7 @@
|
||||||
android:id="@+id/message"
|
android:id="@+id/message"
|
||||||
android:enabled="@{!chatSendingViewModel.isReadOnly}"
|
android:enabled="@{!chatSendingViewModel.isReadOnly}"
|
||||||
android:text="@={chatSendingViewModel.textToSend}"
|
android:text="@={chatSendingViewModel.textToSend}"
|
||||||
|
android:hint="@{chatSendingViewModel.isPendingAnswer ? @string/chat_room_sending_reply_hint : @string/chat_room_sending_message_hint}"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
|
|
|
@ -605,4 +605,8 @@
|
||||||
<string name="chat_room_choose_conversation_for_file_sharing">Sélectionnez ou créez une conversation pour partager le(s) fichier(s)</string>
|
<string name="chat_room_choose_conversation_for_file_sharing">Sélectionnez ou créez une conversation pour partager le(s) fichier(s)</string>
|
||||||
<string name="chat_room_choose_conversation_for_text_sharing">Sélectionnez ou créez une conversation pour partager le texte</string>
|
<string name="chat_room_choose_conversation_for_text_sharing">Sélectionnez ou créez une conversation pour partager le texte</string>
|
||||||
<string name="chat_settins_enable_ephemeral_messages_beta_title">Messages éphémères (bêta)</string>
|
<string name="chat_settins_enable_ephemeral_messages_beta_title">Messages éphémères (bêta)</string>
|
||||||
|
<string name="chat_message_context_menu_reply">Répondre</string>
|
||||||
|
<string name="chat_room_sending_reply_hint">Réponse</string>
|
||||||
|
<string name="chat_room_sending_message_hint">Message</string>
|
||||||
|
<string name="chat_message_replied">Réponse</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -20,13 +20,18 @@
|
||||||
<color name="toolbar_color">#e1e1e1</color>
|
<color name="toolbar_color">#e1e1e1</color>
|
||||||
<color name="header_background_color">#f3f3f3</color>
|
<color name="header_background_color">#f3f3f3</color>
|
||||||
<color name="security_gray_color">#c2c2c2</color>
|
<color name="security_gray_color">#c2c2c2</color>
|
||||||
|
|
||||||
<color name="chat_bubble_text_color">#a1a1a1</color>
|
<color name="chat_bubble_text_color">#a1a1a1</color>
|
||||||
<color name="chat_bubble_incoming_color">#f3f3f3</color>
|
<color name="chat_bubble_incoming_color">#f3f3f3</color>
|
||||||
|
<color name="chat_bubble_incoming_color_dark">#9b9b9b</color>
|
||||||
<!-- Do not use a color with transparency here, it will look bad when in dark mode!
|
<!-- Do not use a color with transparency here, it will look bad when in dark mode!
|
||||||
We use a solid color representation of the primary color but with 10% transparency.
|
We use a solid color representation of the primary color but with 10% transparency.
|
||||||
For each RGB value of the color, the math to get is:
|
For each RGB value of the color, the math to get is:
|
||||||
C' = C * (A / 255) + 255 * (1 - (A / 255)) so for 10% transparency: C' = C * 0.1 + 229.5 -->
|
C' = C * (A / 255) + 255 * (1 - (A / 255)) so for 10% transparency: C' = C * 0.1 + 229.5 -->
|
||||||
<color name="chat_bubble_outgoing_color">#ffeee5</color>
|
<color name="chat_bubble_outgoing_color">#ffeee5</color>
|
||||||
|
<color name="chat_bubble_outgoing_color_dark">#ff9e67</color>
|
||||||
|
<color name="chat_bubble_file_background_color">#f4f4f4</color>
|
||||||
|
<color name="chat_bubble_file_background_border_color">#dedede</color>
|
||||||
|
|
||||||
<color name="disabled_color">#808080</color>
|
<color name="disabled_color">#808080</color>
|
||||||
<color name="contact_disabled_color">#99ffffff</color>
|
<color name="contact_disabled_color">#99ffffff</color>
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<dimen name="chat_message_bubble_image_height_small">100dp</dimen>
|
<dimen name="chat_message_bubble_image_height_small">100dp</dimen>
|
||||||
<dimen name="chat_message_bubble_file_size">120dp</dimen>
|
<dimen name="chat_message_bubble_file_size">120dp</dimen>
|
||||||
<dimen name="chat_message_bubble_file_icon_size">30dp</dimen>
|
<dimen name="chat_message_bubble_file_icon_size">30dp</dimen>
|
||||||
|
<dimen name="chat_message_small_bubble_file_size">50dp</dimen>
|
||||||
<dimen name="chat_message_bubble_desired_height">600dp</dimen>
|
<dimen name="chat_message_bubble_desired_height">600dp</dimen>
|
||||||
<dimen name="video_preview_max_size">200dp</dimen>
|
<dimen name="video_preview_max_size">200dp</dimen>
|
||||||
<dimen name="video_preview_pip_max_size">45dp</dimen>
|
<dimen name="video_preview_pip_max_size">45dp</dimen>
|
||||||
|
@ -26,4 +27,5 @@
|
||||||
<dimen name="call_overlay_size">60dp</dimen>
|
<dimen name="call_overlay_size">60dp</dimen>
|
||||||
<dimen name="chat_message_popup_width">250dp</dimen>
|
<dimen name="chat_message_popup_width">250dp</dimen>
|
||||||
<dimen name="chat_message_popup_item_height">50dp</dimen>
|
<dimen name="chat_message_popup_item_height">50dp</dimen>
|
||||||
|
<dimen name="chat_message_round_corner_radius">6.7dp</dimen>
|
||||||
</resources>
|
</resources>
|
|
@ -168,9 +168,11 @@
|
||||||
<string name="chat_message_imdn_undelivered">Undelivered</string>
|
<string name="chat_message_imdn_undelivered">Undelivered</string>
|
||||||
<string name="chat_message_imdn_sent">Sent</string>
|
<string name="chat_message_imdn_sent">Sent</string>
|
||||||
<string name="chat_message_forwarded">Forwarded</string>
|
<string name="chat_message_forwarded">Forwarded</string>
|
||||||
|
<string name="chat_message_replied">Reply</string>
|
||||||
<string name="chat_message_context_menu_resend">Resend</string>
|
<string name="chat_message_context_menu_resend">Resend</string>
|
||||||
<string name="chat_message_context_menu_copy_text">Copy text</string>
|
<string name="chat_message_context_menu_copy_text">Copy text</string>
|
||||||
<string name="chat_message_context_menu_forward">Forward</string>
|
<string name="chat_message_context_menu_forward">Forward</string>
|
||||||
|
<string name="chat_message_context_menu_reply">Reply</string>
|
||||||
<string name="chat_message_context_menu_imdn_info">Delivery status</string>
|
<string name="chat_message_context_menu_imdn_info">Delivery status</string>
|
||||||
<string name="chat_message_context_menu_delete">Delete</string>
|
<string name="chat_message_context_menu_delete">Delete</string>
|
||||||
<string name="chat_message_context_menu_add_to_contacts">Add to contacts</string>
|
<string name="chat_message_context_menu_add_to_contacts">Add to contacts</string>
|
||||||
|
@ -214,6 +216,8 @@
|
||||||
<string name="chat_message_cant_open_file_in_app_dialog_message">Would you like to open it as text or export it (unencrypted) to a third party app if available?</string>
|
<string name="chat_message_cant_open_file_in_app_dialog_message">Would you like to open it as text or export it (unencrypted) to a third party app if available?</string>
|
||||||
<string name="chat_message_cant_open_file_in_app_dialog_export_button">Export</string>
|
<string name="chat_message_cant_open_file_in_app_dialog_export_button">Export</string>
|
||||||
<string name="chat_message_cant_open_file_in_app_dialog_open_as_text_button">Open as text</string>
|
<string name="chat_message_cant_open_file_in_app_dialog_open_as_text_button">Open as text</string>
|
||||||
|
<string name="chat_room_sending_reply_hint">Reply</string>
|
||||||
|
<string name="chat_room_sending_message_hint">Message</string>
|
||||||
|
|
||||||
<!-- Recordings -->
|
<!-- Recordings -->
|
||||||
<string name="recordings_empty_list">No recordings</string>
|
<string name="recordings_empty_list">No recordings</string>
|
||||||
|
@ -622,6 +626,7 @@
|
||||||
<string name="content_description_downloaded_file_transfer">Attached file</string>
|
<string name="content_description_downloaded_file_transfer">Attached file</string>
|
||||||
<string name="content_description_delivery_status">Message delivery status</string>
|
<string name="content_description_delivery_status">Message delivery status</string>
|
||||||
<string name="content_description_forwarded_message">Message has been forwarded</string>
|
<string name="content_description_forwarded_message">Message has been forwarded</string>
|
||||||
|
<string name="content_description_replied_message">Message is a reply</string>
|
||||||
<string name="content_description_forward_message">Forward message in this conversation</string>
|
<string name="content_description_forward_message">Forward message in this conversation</string>
|
||||||
<string name="content_description_ephemeral_message">Message is ephemeral</string>
|
<string name="content_description_ephemeral_message">Message is ephemeral</string>
|
||||||
<string name="content_description_linphone_user">Contact is a &appName; user</string>
|
<string name="content_description_linphone_user">Contact is a &appName; user</string>
|
||||||
|
@ -636,6 +641,7 @@
|
||||||
<string name="content_description_show_chat_room_menu">Show chat room menu</string>
|
<string name="content_description_show_chat_room_menu">Show chat room menu</string>
|
||||||
<string name="content_description_enter_edition_mode">Enter edition mode</string>
|
<string name="content_description_enter_edition_mode">Enter edition mode</string>
|
||||||
<string name="content_description_attach_file">Attach a file to the message</string>
|
<string name="content_description_attach_file">Attach a file to the message</string>
|
||||||
|
<string name="content_description_attached_file">File attached to the message</string>
|
||||||
<string name="content_description_send_message">Send message</string>
|
<string name="content_description_send_message">Send message</string>
|
||||||
<string name="content_description_toggle_participant_devices_list">Show or hide the participant devices</string>
|
<string name="content_description_toggle_participant_devices_list">Show or hide the participant devices</string>
|
||||||
<string name="content_description_ephemeral_duration_selected">Ephemeral duration selected</string>
|
<string name="content_description_ephemeral_duration_selected">Ephemeral duration selected</string>
|
||||||
|
|
|
@ -111,6 +111,20 @@
|
||||||
<item name="android:textSize">13sp</item>
|
<item name="android:textSize">13sp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Chat related -->
|
||||||
|
|
||||||
|
<style name="chat_message_reply_sender_font">
|
||||||
|
<item name="android:textColor">?attr/primaryTextColor</item>
|
||||||
|
<item name="android:textSize">13sp</item>
|
||||||
|
<item name="android:fontFamily">sans-serif-medium</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="chat_message_reply_font">
|
||||||
|
<item name="android:textColor">?attr/primaryTextColor</item>
|
||||||
|
<item name="android:textSize">15sp</item>
|
||||||
|
<item name="android:fontFamily">sans-serif</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<!-- Call stats -->
|
<!-- Call stats -->
|
||||||
|
|
||||||
<style name="call_stats_title_font" parent="@android:style/TextAppearance.Medium">
|
<style name="call_stats_title_font" parent="@android:style/TextAppearance.Medium">
|
||||||
|
|
Loading…
Reference in a new issue