mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
No longer use dialog for chat message long press
This commit is contained in:
parent
a73e483478
commit
4c9bdec61e
8 changed files with 668 additions and 550 deletions
|
|
@ -21,15 +21,9 @@ package org.linphone.ui.main.chat.fragment
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
|
|
@ -40,18 +34,13 @@ import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import android.view.Window
|
|
||||||
import android.view.WindowManager
|
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import androidx.activity.result.PickVisualMediaRequest
|
import androidx.activity.result.PickVisualMediaRequest
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
|
@ -75,7 +64,6 @@ import org.linphone.R
|
||||||
import org.linphone.compatibility.Compatibility
|
import org.linphone.compatibility.Compatibility
|
||||||
import org.linphone.core.ChatMessage
|
import org.linphone.core.ChatMessage
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.ChatBubbleLongPressMenuBinding
|
|
||||||
import org.linphone.databinding.ChatConversationFragmentBinding
|
import org.linphone.databinding.ChatConversationFragmentBinding
|
||||||
import org.linphone.databinding.ChatConversationPopupMenuBinding
|
import org.linphone.databinding.ChatConversationPopupMenuBinding
|
||||||
import org.linphone.ui.GenericActivity
|
import org.linphone.ui.GenericActivity
|
||||||
|
|
@ -88,6 +76,7 @@ import org.linphone.ui.main.chat.model.MessageDeliveryModel
|
||||||
import org.linphone.ui.main.chat.model.MessageModel
|
import org.linphone.ui.main.chat.model.MessageModel
|
||||||
import org.linphone.ui.main.chat.model.MessageReactionsModel
|
import org.linphone.ui.main.chat.model.MessageReactionsModel
|
||||||
import org.linphone.ui.main.chat.view.RichEditText
|
import org.linphone.ui.main.chat.view.RichEditText
|
||||||
|
import org.linphone.ui.main.chat.viewmodel.ChatMessageLongPressViewModel
|
||||||
import org.linphone.ui.main.chat.viewmodel.ConversationViewModel
|
import org.linphone.ui.main.chat.viewmodel.ConversationViewModel
|
||||||
import org.linphone.ui.main.chat.viewmodel.ConversationViewModel.Companion.SCROLLING_POSITION_NOT_SET
|
import org.linphone.ui.main.chat.viewmodel.ConversationViewModel.Companion.SCROLLING_POSITION_NOT_SET
|
||||||
import org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel
|
import org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel
|
||||||
|
|
@ -119,12 +108,12 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
protected lateinit var sendMessageViewModel: SendMessageInConversationViewModel
|
protected lateinit var sendMessageViewModel: SendMessageInConversationViewModel
|
||||||
|
|
||||||
|
protected lateinit var messageLongPressViewModel: ChatMessageLongPressViewModel
|
||||||
|
|
||||||
private lateinit var adapter: ConversationEventAdapter
|
private lateinit var adapter: ConversationEventAdapter
|
||||||
|
|
||||||
private lateinit var bottomSheetAdapter: MessageBottomSheetAdapter
|
private lateinit var bottomSheetAdapter: MessageBottomSheetAdapter
|
||||||
|
|
||||||
private var messageLongPressDialog: Dialog? = null
|
|
||||||
|
|
||||||
private val args: ConversationFragmentArgs by navArgs()
|
private val args: ConversationFragmentArgs by navArgs()
|
||||||
|
|
||||||
private var bottomSheetDialog: BottomSheetDialogFragment? = null
|
private var bottomSheetDialog: BottomSheetDialogFragment? = null
|
||||||
|
|
@ -364,6 +353,11 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
binding.sendMessageViewModel = sendMessageViewModel
|
binding.sendMessageViewModel = sendMessageViewModel
|
||||||
observeToastEvents(sendMessageViewModel)
|
observeToastEvents(sendMessageViewModel)
|
||||||
|
|
||||||
|
messageLongPressViewModel = ViewModelProvider(this)[ChatMessageLongPressViewModel::class.java]
|
||||||
|
binding.messageLongPressViewModel = messageLongPressViewModel
|
||||||
|
observeToastEvents(messageLongPressViewModel)
|
||||||
|
messageLongPressViewModel.setupEmojiPicker(binding.longPressMenu.emojiPickerBottomSheet)
|
||||||
|
|
||||||
binding.setBackClickListener {
|
binding.setBackClickListener {
|
||||||
goBack()
|
goBack()
|
||||||
}
|
}
|
||||||
|
|
@ -617,7 +611,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
viewModel.fileToDisplayEvent.observe(viewLifecycleOwner) {
|
viewModel.fileToDisplayEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume { model ->
|
it.consume { model ->
|
||||||
if (messageLongPressDialog != null) return@consume
|
if (messageLongPressViewModel.visible.value == true) return@consume
|
||||||
Log.i("$TAG User clicked on file [${model.path}], let's display it in file viewer")
|
Log.i("$TAG User clicked on file [${model.path}], let's display it in file viewer")
|
||||||
goToFileViewer(model)
|
goToFileViewer(model)
|
||||||
}
|
}
|
||||||
|
|
@ -625,7 +619,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
viewModel.conferenceToJoinEvent.observe(viewLifecycleOwner) {
|
viewModel.conferenceToJoinEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume { conferenceUri ->
|
it.consume { conferenceUri ->
|
||||||
if (messageLongPressDialog != null) return@consume
|
if (messageLongPressViewModel.visible.value == true) return@consume
|
||||||
Log.i("$TAG Requesting to go to waiting room for conference URI [$conferenceUri]")
|
Log.i("$TAG Requesting to go to waiting room for conference URI [$conferenceUri]")
|
||||||
sharedViewModel.goToMeetingWaitingRoomEvent.value = Event(conferenceUri)
|
sharedViewModel.goToMeetingWaitingRoomEvent.value = Event(conferenceUri)
|
||||||
}
|
}
|
||||||
|
|
@ -633,7 +627,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
viewModel.openWebBrowserEvent.observe(viewLifecycleOwner) {
|
viewModel.openWebBrowserEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume { url ->
|
it.consume { url ->
|
||||||
if (messageLongPressDialog != null) return@consume
|
if (messageLongPressViewModel.visible.value == true) return@consume
|
||||||
Log.i("$TAG Requesting to open web browser on page [$url]")
|
Log.i("$TAG Requesting to open web browser on page [$url]")
|
||||||
try {
|
try {
|
||||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||||
|
|
@ -648,7 +642,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
viewModel.contactToDisplayEvent.observe(viewLifecycleOwner) {
|
viewModel.contactToDisplayEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume { friendRefKey ->
|
it.consume { friendRefKey ->
|
||||||
if (messageLongPressDialog != null) return@consume
|
if (messageLongPressViewModel.visible.value == true) return@consume
|
||||||
Log.i("$TAG Navigating to contact with ref key [$friendRefKey]")
|
Log.i("$TAG Navigating to contact with ref key [$friendRefKey]")
|
||||||
sharedViewModel.navigateToContactsEvent.value = Event(true)
|
sharedViewModel.navigateToContactsEvent.value = Event(true)
|
||||||
sharedViewModel.showContactEvent.value = Event(friendRefKey)
|
sharedViewModel.showContactEvent.value = Event(friendRefKey)
|
||||||
|
|
@ -671,6 +665,49 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
messageLongPressViewModel.replyToMessageEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
val model = messageLongPressViewModel.messageModel.value
|
||||||
|
if (model != null) {
|
||||||
|
sendMessageViewModel.replyToMessage(model)
|
||||||
|
// Open keyboard & focus edit text
|
||||||
|
binding.sendArea.messageToSend.showKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageLongPressViewModel.deleteMessageEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
val model = messageLongPressViewModel.messageModel.value
|
||||||
|
if (model != null) {
|
||||||
|
viewModel.deleteChatMessage(model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageLongPressViewModel.forwardMessageEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
val model = messageLongPressViewModel.messageModel.value
|
||||||
|
if (model != null) {
|
||||||
|
// Remove observer before setting the message to forward
|
||||||
|
// as we don't want to forward it in this chat room
|
||||||
|
sharedViewModel.messageToForwardEvent.removeObservers(viewLifecycleOwner)
|
||||||
|
sharedViewModel.messageToForwardEvent.postValue(Event(model))
|
||||||
|
|
||||||
|
if (findNavController().currentDestination?.id == R.id.conversationFragment) {
|
||||||
|
val action = ConversationFragmentDirections.actionConversationFragmentToConversationForwardMessageFragment()
|
||||||
|
findNavController().navigate(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageLongPressViewModel.onDismissedEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
Compatibility.removeBlurRenderEffect(binding.coordinatorLayout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sharedViewModel.richContentUri.observe(
|
sharedViewModel.richContentUri.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) {
|
) {
|
||||||
|
|
@ -1008,116 +1045,16 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
popupWindow.showAsDropDown(view, 0, 0, Gravity.BOTTOM)
|
popupWindow.showAsDropDown(view, 0, 0, Gravity.BOTTOM)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dismissDialog() {
|
@UiThread
|
||||||
messageLongPressDialog?.dismiss()
|
|
||||||
messageLongPressDialog = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showChatMessageLongPressMenu(chatMessageModel: MessageModel) {
|
private fun showChatMessageLongPressMenu(chatMessageModel: MessageModel) {
|
||||||
Compatibility.setBlurRenderEffect(binding.root)
|
Compatibility.setBlurRenderEffect(binding.coordinatorLayout)
|
||||||
|
messageLongPressViewModel.setMessage(chatMessageModel)
|
||||||
val layout: ChatBubbleLongPressMenuBinding = DataBindingUtil.inflate(
|
|
||||||
LayoutInflater.from(context),
|
|
||||||
R.layout.chat_bubble_long_press_menu,
|
|
||||||
null,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
val emojiSheetBehavior = BottomSheetBehavior.from(layout.emojiPickerBottomSheet.root)
|
|
||||||
emojiSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
|
|
||||||
emojiSheetBehavior.skipCollapsed = true
|
|
||||||
|
|
||||||
layout.root.setOnClickListener {
|
|
||||||
dismissDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.setDeleteClickListener {
|
|
||||||
Log.i("$TAG Deleting message")
|
|
||||||
viewModel.deleteChatMessage(chatMessageModel)
|
|
||||||
dismissDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.setCopyClickListener {
|
|
||||||
Log.i("$TAG Copying message text into clipboard")
|
|
||||||
val text = chatMessageModel.text.value?.toString()
|
|
||||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val label = "Message"
|
|
||||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, text))
|
|
||||||
|
|
||||||
dismissDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.setPickEmojiClickListener {
|
|
||||||
Log.i("$TAG Opening emoji-picker for reaction")
|
|
||||||
emojiSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.setResendClickListener {
|
|
||||||
Log.i("$TAG Re-sending message in error state")
|
|
||||||
chatMessageModel.resend()
|
|
||||||
dismissDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.setForwardClickListener {
|
|
||||||
Log.i("$TAG Forwarding message")
|
|
||||||
// Remove observer before setting the message to forward
|
|
||||||
// as we don't want to forward it in this chat room
|
|
||||||
sharedViewModel.messageToForwardEvent.removeObservers(viewLifecycleOwner)
|
|
||||||
sharedViewModel.messageToForwardEvent.postValue(Event(chatMessageModel))
|
|
||||||
dismissDialog()
|
|
||||||
|
|
||||||
if (findNavController().currentDestination?.id == R.id.conversationFragment) {
|
|
||||||
val action = ConversationFragmentDirections.actionConversationFragmentToConversationForwardMessageFragment()
|
|
||||||
findNavController().navigate(action)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.setReplyClickListener {
|
|
||||||
Log.i("$TAG Updating sending area to reply to selected message")
|
|
||||||
sendMessageViewModel.replyToMessage(chatMessageModel)
|
|
||||||
dismissDialog()
|
|
||||||
|
|
||||||
// Open keyboard & focus edit text
|
|
||||||
binding.sendArea.messageToSend.showKeyboard()
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.model = chatMessageModel
|
|
||||||
chatMessageModel.dismissLongPressMenuEvent.observe(viewLifecycleOwner) {
|
chatMessageModel.dismissLongPressMenuEvent.observe(viewLifecycleOwner) {
|
||||||
dismissDialog()
|
it.consume {
|
||||||
}
|
messageLongPressViewModel.dismiss()
|
||||||
|
|
||||||
val dialog = Dialog(requireContext(), R.style.Theme_LinphoneDialog)
|
|
||||||
dialog.apply {
|
|
||||||
setOnDismissListener {
|
|
||||||
Compatibility.removeBlurRenderEffect(binding.root)
|
|
||||||
}
|
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
|
||||||
|
|
||||||
window?.apply {
|
|
||||||
setLayout(
|
|
||||||
WindowManager.LayoutParams.MATCH_PARENT,
|
|
||||||
WindowManager.LayoutParams.MATCH_PARENT
|
|
||||||
)
|
|
||||||
|
|
||||||
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
|
||||||
|
|
||||||
val d: Drawable = ColorDrawable(
|
|
||||||
requireContext().getColor(R.color.grey_300)
|
|
||||||
)
|
|
||||||
d.alpha = 102
|
|
||||||
setBackgroundDrawable(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
setContentView(layout.root)
|
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(layout.root) { v, windowInsets ->
|
|
||||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
||||||
v.updatePadding(0, 0, 0, insets.bottom)
|
|
||||||
WindowInsetsCompat.CONSUMED
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
messageLongPressViewModel.visible.value = true
|
||||||
dialog.show()
|
|
||||||
messageLongPressDialog = dialog
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.ui.main.chat.viewmodel
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import androidx.annotation.UiThread
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
import org.linphone.databinding.ChatBubbleEmojiPickerBottomSheetBinding
|
||||||
|
import org.linphone.ui.GenericViewModel
|
||||||
|
import org.linphone.ui.main.chat.model.MessageModel
|
||||||
|
import org.linphone.utils.Event
|
||||||
|
|
||||||
|
class ChatMessageLongPressViewModel : GenericViewModel() {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "[Chat Message LongPress ViewModel]"
|
||||||
|
}
|
||||||
|
|
||||||
|
val visible = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val hideForward = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val horizontalBias = MutableLiveData<Float>()
|
||||||
|
|
||||||
|
val isChatRoomReadOnly = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val messageModel = MutableLiveData<MessageModel>()
|
||||||
|
|
||||||
|
val isMessageOutgoing = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val isMessageInError = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val replyToMessageEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
val forwardMessageEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
val deleteMessageEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
val onDismissedEvent = MutableLiveData<Event<Boolean>>()
|
||||||
|
|
||||||
|
private lateinit var emojiBottomSheet: ChatBubbleEmojiPickerBottomSheetBinding
|
||||||
|
private lateinit var emojiBottomSheetBehavior: BottomSheetBehavior<View>
|
||||||
|
|
||||||
|
init {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun setupEmojiPicker(bottomSheet: ChatBubbleEmojiPickerBottomSheetBinding) {
|
||||||
|
emojiBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet.root)
|
||||||
|
emojiBottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
emojiBottomSheetBehavior.skipCollapsed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun setMessage(model: MessageModel) {
|
||||||
|
isChatRoomReadOnly.value = model.chatRoomIsReadOnly
|
||||||
|
isMessageOutgoing.value = model.isOutgoing
|
||||||
|
isMessageInError.value = model.isInError
|
||||||
|
horizontalBias.value = if (model.isOutgoing) 1f else 0f
|
||||||
|
messageModel.value = model
|
||||||
|
|
||||||
|
emojiBottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun dismiss() {
|
||||||
|
onDismissedEvent.value = Event(true)
|
||||||
|
emojiBottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun resend() {
|
||||||
|
Log.i("$TAG Re-sending message in error state")
|
||||||
|
messageModel.value?.resend()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun reply() {
|
||||||
|
Log.i("$TAG Replying to message")
|
||||||
|
replyToMessageEvent.value = Event(true)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun copyClickListener() {
|
||||||
|
Log.i("$TAG Copying message text into clipboard")
|
||||||
|
|
||||||
|
val text = messageModel.value?.text?.value?.toString()
|
||||||
|
val clipboard = coreContext.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val label = "Message"
|
||||||
|
clipboard.setPrimaryClip(ClipData.newPlainText(label, text))
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun forwardClickListener() {
|
||||||
|
Log.i("$TAG Forwarding message")
|
||||||
|
forwardMessageEvent.value = Event(true)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun deleteClickListener() {
|
||||||
|
Log.i("$TAG Deleting message")
|
||||||
|
deleteMessageEvent.value = Event(true)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun pickEmoji() {
|
||||||
|
Log.i("$TAG Opening emoji-picker for reaction")
|
||||||
|
emojiBottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,12 @@
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.chat.model.MessageModel" />
|
type="org.linphone.ui.main.chat.model.MessageModel" />
|
||||||
|
<variable
|
||||||
|
name="inflatedVisibility"
|
||||||
|
type="Integer" />
|
||||||
|
<variable
|
||||||
|
name="skipGroupMargins"
|
||||||
|
type="Boolean" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|
@ -30,8 +36,10 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="32dp"
|
android:layout_marginEnd="32dp"
|
||||||
android:layout_marginBottom="@{model.groupedWithNextMessage ? @dimen/chat_bubble_grouped_bottom_margin : @dimen/chat_bubble_bottom_margin, default=@dimen/chat_bubble_bottom_margin}"
|
android:layout_marginBottom="@{skipGroupMargins || model.groupedWithNextMessage ? @dimen/chat_bubble_grouped_bottom_margin : @dimen/chat_bubble_bottom_margin, default=@dimen/chat_bubble_bottom_margin}"
|
||||||
android:layout_marginTop="@{model.groupedWithPreviousMessage ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}">
|
android:layout_marginTop="@{skipGroupMargins || model.groupedWithPreviousMessage ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}"
|
||||||
|
android:visibility="@{inflatedVisibility == View.VISIBLE ? View.VISIBLE : View.GONE}"
|
||||||
|
inflatedLifecycleOwner="@{true}">
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/avatar"
|
android:id="@+id/avatar"
|
||||||
|
|
|
||||||
|
|
@ -6,186 +6,171 @@
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<variable
|
<variable
|
||||||
name="resendClickListener"
|
name="viewModel"
|
||||||
type="View.OnClickListener" />
|
type="org.linphone.ui.main.chat.viewmodel.ChatMessageLongPressViewModel" />
|
||||||
<variable
|
|
||||||
name="replyClickListener"
|
|
||||||
type="View.OnClickListener" />
|
|
||||||
<variable
|
|
||||||
name="copyClickListener"
|
|
||||||
type="View.OnClickListener" />
|
|
||||||
<variable
|
|
||||||
name="forwardClickListener"
|
|
||||||
type="View.OnClickListener" />
|
|
||||||
<variable
|
|
||||||
name="deleteClickListener"
|
|
||||||
type="View.OnClickListener" />
|
|
||||||
<variable
|
|
||||||
name="pickEmojiClickListener"
|
|
||||||
type="View.OnClickListener" />
|
|
||||||
<variable
|
|
||||||
name="model"
|
|
||||||
type="org.linphone.ui.main.chat.model.MessageModel" />
|
|
||||||
<variable
|
|
||||||
name="hideForward"
|
|
||||||
type="Boolean" />
|
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:onClick="@{() -> viewModel.dismiss()}">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/constraint_layout"
|
android:id="@+id/constraint_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/gray_300_alpha_40">
|
||||||
<androidx.constraintlayout.widget.Barrier
|
|
||||||
android:id="@+id/bubble_top_barrier"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:barrierDirection="top"
|
|
||||||
app:constraint_referenced_ids="incoming_bubble, outgoing_bubble" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
|
||||||
android:id="@+id/bottom_barrier"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:barrierDirection="top"
|
|
||||||
app:constraint_referenced_ids="action_reply, action_resend" />
|
|
||||||
|
|
||||||
<ViewStub
|
|
||||||
android:id="@+id/outgoing_bubble"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:layout="@layout/chat_bubble_outgoing"
|
|
||||||
android:visibility="@{model.outgoing ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
bind:inflatedVisibility="@{model.outgoing ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/emojis"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/bottom_barrier"
|
|
||||||
app:layout_constraintHeight_max="@dimen/chat_bubble_max_height_long_press"
|
|
||||||
bind:model="@{model}"/>
|
|
||||||
|
|
||||||
<ViewStub
|
|
||||||
android:id="@+id/incoming_bubble"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:layout="@layout/chat_bubble_incoming"
|
|
||||||
android:visibility="@{model.outgoing ? View.GONE : View.VISIBLE}"
|
|
||||||
bind:inflatedVisibility="@{model.outgoing ? View.GONE : View.VISIBLE}"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/emojis"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/bottom_barrier"
|
|
||||||
app:layout_constraintHeight_max="@dimen/chat_bubble_max_height_long_press"
|
|
||||||
bind:model="@{model}"/>
|
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/emojis"
|
android:id="@+id/emojis"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:visibility="@{model.chatRoomIsReadOnly ? View.GONE : View.VISIBLE}"
|
android:visibility="@{viewModel.isChatRoomReadOnly ? View.GONE : View.VISIBLE}"
|
||||||
layout="@layout/chat_emoji_reaction_picker"
|
layout="@layout/chat_emoji_reaction_picker"
|
||||||
bind:model="@{model}"
|
bind:model="@{viewModel.messageModel}"
|
||||||
bind:pickEmojiClickListener="@{pickEmojiClickListener}"
|
bind:pickEmojiClickListener="@{() -> viewModel.pickEmoji()}"
|
||||||
app:layout_constraintVertical_bias="1"
|
app:layout_constraintHorizontal_bias="@{viewModel.horizontalBias, default=0}"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintWidth_max="@dimen/dialog_max_width"
|
||||||
app:layout_constraintBottom_toTopOf="@id/bubble_top_barrier"
|
app:layout_constraintBottom_toTopOf="@id/bubbles"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
<View
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/actions_background"
|
android:id="@+id/bubbles"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="?attr/color_main2_200"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/bottom_barrier"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
style="@style/context_menu_action_label_style"
|
|
||||||
android:id="@+id/action_resend"
|
|
||||||
android:onClick="@{resendClickListener}"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="1dp"
|
android:layout_marginStart="16dp"
|
||||||
android:text="@string/menu_resend_chat_message"
|
android:layout_marginEnd="16dp"
|
||||||
android:background="@drawable/menu_item_background"
|
android:layout_marginBottom="5dp"
|
||||||
android:drawableStart="@drawable/paper_plane_right"
|
|
||||||
android:visibility="@{model.isInError && model.isOutgoing ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/action_reply"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/actions">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<ViewStub
|
||||||
style="@style/context_menu_action_label_style"
|
android:id="@+id/outgoing_bubble"
|
||||||
android:id="@+id/action_reply"
|
android:layout_width="match_parent"
|
||||||
android:onClick="@{replyClickListener}"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout="@layout/chat_bubble_outgoing"
|
||||||
|
android:visibility="@{viewModel.isMessageOutgoing ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
bind:inflatedVisibility="@{viewModel.isMessageOutgoing ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
bind:model="@{viewModel.messageModel}"
|
||||||
|
bind:skipGroupMargins="@{true}"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_max="@dimen/chat_bubble_max_height_long_press"/>
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/incoming_bubble"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout="@layout/chat_bubble_incoming"
|
||||||
|
android:visibility="@{viewModel.isMessageOutgoing ? View.GONE : View.VISIBLE}"
|
||||||
|
bind:inflatedVisibility="@{viewModel.isMessageOutgoing ? View.GONE : View.VISIBLE}"
|
||||||
|
bind:model="@{viewModel.messageModel}"
|
||||||
|
bind:skipGroupMargins="@{true}"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_max="@dimen/chat_bubble_max_height_long_press"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/actions"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="1dp"
|
android:orientation="vertical"
|
||||||
android:text="@string/menu_reply_to_chat_message"
|
android:layout_marginStart="16dp"
|
||||||
android:visibility="@{model.chatRoomIsReadOnly ? View.GONE : View.VISIBLE}"
|
android:layout_marginEnd="16dp"
|
||||||
android:background="@drawable/menu_item_background"
|
android:layout_marginBottom="60dp"
|
||||||
android:drawableStart="@drawable/reply"
|
android:background="@drawable/shape_squircle_white_background"
|
||||||
app:layout_constraintBottom_toTopOf="@id/action_copy"
|
app:layout_constraintWidth_max="250dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintHorizontal_bias="@{viewModel.horizontalBias, default=0}"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
style="@style/context_menu_action_label_style"
|
|
||||||
android:id="@+id/action_copy"
|
|
||||||
android:onClick="@{copyClickListener}"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="1dp"
|
|
||||||
android:text="@string/menu_copy_chat_message"
|
|
||||||
android:background="@drawable/menu_item_background"
|
|
||||||
android:drawableStart="@drawable/copy"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/action_forward"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
style="@style/context_menu_action_label_style"
|
|
||||||
android:id="@+id/action_forward"
|
|
||||||
android:onClick="@{forwardClickListener}"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="1dp"
|
|
||||||
android:text="@string/menu_forward_chat_message"
|
|
||||||
android:background="@drawable/menu_item_background"
|
|
||||||
android:drawableStart="@drawable/forward"
|
|
||||||
android:visibility="@{hideForward ? View.GONE : View.VISIBLE}"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/action_delete"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
style="@style/context_menu_danger_action_label_style"
|
|
||||||
android:id="@+id/action_delete"
|
|
||||||
android:onClick="@{deleteClickListener}"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="1dp"
|
|
||||||
android:text="@string/menu_delete_selected_item"
|
|
||||||
android:background="@drawable/menu_item_background"
|
|
||||||
android:drawableStart="@drawable/trash_simple"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/popup_menu_action_label_style"
|
||||||
|
android:id="@+id/action_resend"
|
||||||
|
android:onClick="@{() -> viewModel.resend()}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/menu_resend_chat_message"
|
||||||
|
android:drawableEnd="@drawable/paper_plane_right"
|
||||||
|
android:visibility="@{viewModel.isMessageInError && viewModel.isMessageOutgoing ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/color_main2_200"
|
||||||
|
android:visibility="@{viewModel.isMessageInError && viewModel.isMessageOutgoing ? View.VISIBLE : View.GONE, default=gone}"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/popup_menu_action_label_style"
|
||||||
|
android:id="@+id/action_reply"
|
||||||
|
android:onClick="@{() -> viewModel.reply()}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/menu_reply_to_chat_message"
|
||||||
|
android:visibility="@{viewModel.isChatRoomReadOnly ? View.GONE : View.VISIBLE}"
|
||||||
|
android:drawableEnd="@drawable/reply" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/color_main2_200"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/popup_menu_action_label_style"
|
||||||
|
android:id="@+id/action_copy"
|
||||||
|
android:onClick="@{() -> viewModel.copyClickListener()}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/menu_copy_chat_message"
|
||||||
|
android:drawableEnd="@drawable/copy" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/color_main2_200"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/popup_menu_action_label_style"
|
||||||
|
android:id="@+id/action_forward"
|
||||||
|
android:onClick="@{() -> viewModel.forwardClickListener()}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/menu_forward_chat_message"
|
||||||
|
android:drawableEnd="@drawable/forward"
|
||||||
|
android:visibility="@{viewModel.hideForward ? View.GONE : View.VISIBLE}" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="?attr/color_main2_200"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/popup_menu_danger_action_label_style"
|
||||||
|
android:id="@+id/action_delete"
|
||||||
|
android:onClick="@{() -> viewModel.deleteClickListener()}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/menu_delete_selected_item"
|
||||||
|
android:drawableEnd="@drawable/trash_simple" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/emoji_picker_bottom_sheet"
|
android:id="@+id/emoji_picker_bottom_sheet"
|
||||||
layout="@layout/chat_bubble_emoji_picker_bottom_sheet"
|
layout="@layout/chat_bubble_emoji_picker_bottom_sheet"
|
||||||
bind:model="@{model}"/>
|
bind:model="@{viewModel.messageModel}"/>
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.chat.model.MessageModel" />
|
type="org.linphone.ui.main.chat.model.MessageModel" />
|
||||||
|
<variable
|
||||||
|
name="inflatedVisibility"
|
||||||
|
type="Integer" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|
@ -31,7 +34,9 @@
|
||||||
android:layout_marginStart="32dp"
|
android:layout_marginStart="32dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginBottom="@{model.groupedWithNextMessage ? @dimen/chat_bubble_grouped_bottom_margin : @dimen/chat_bubble_bottom_margin, default=@dimen/chat_bubble_bottom_margin}"
|
android:layout_marginBottom="@{model.groupedWithNextMessage ? @dimen/chat_bubble_grouped_bottom_margin : @dimen/chat_bubble_bottom_margin, default=@dimen/chat_bubble_bottom_margin}"
|
||||||
android:layout_marginTop="@{model.groupedWithPreviousMessage ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}">
|
android:layout_marginTop="@{model.groupedWithPreviousMessage ? @dimen/chat_bubble_grouped_top_margin : @dimen/chat_bubble_top_margin, default=@dimen/chat_bubble_top_margin}"
|
||||||
|
android:visibility="@{inflatedVisibility == View.VISIBLE ? View.VISIBLE : View.GONE}"
|
||||||
|
inflatedLifecycleOwner="@{true}">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
<androidx.constraintlayout.widget.Group
|
||||||
android:id="@+id/reply_group"
|
android:id="@+id/reply_group"
|
||||||
|
|
|
||||||
|
|
@ -35,301 +35,317 @@
|
||||||
<variable
|
<variable
|
||||||
name="sendMessageViewModel"
|
name="sendMessageViewModel"
|
||||||
type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" />
|
type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" />
|
||||||
|
<variable
|
||||||
|
name="messageLongPressViewModel"
|
||||||
|
type="org.linphone.ui.main.chat.viewmodel.ChatMessageLongPressViewModel" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/coordinator_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:background="?attr/color_main2_000">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
app:constraint_referenced_ids="avatar, title, show_menu"
|
android:background="?attr/color_main2_000">
|
||||||
android:visibility="@{viewModel.searchBarVisible ? View.GONE : View.VISIBLE}" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
<androidx.constraintlayout.widget.Group
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:constraint_referenced_ids="cancel_search, search, clear_field"
|
app:constraint_referenced_ids="avatar, title, show_menu"
|
||||||
android:visibility="@{viewModel.searchBarVisible ? View.VISIBLE : View.GONE, default=gone}" />
|
android:visibility="@{viewModel.searchBarVisible ? View.GONE : View.VISIBLE}" />
|
||||||
|
|
||||||
<ImageView
|
<androidx.constraintlayout.widget.Group
|
||||||
android:id="@+id/back"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="@dimen/top_bar_height"
|
app:constraint_referenced_ids="cancel_search, search, clear_field"
|
||||||
android:padding="15dp"
|
android:visibility="@{viewModel.searchBarVisible ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:onClick="@{backClickListener}"
|
|
||||||
android:visibility="@{viewModel.isInCallConversation || viewModel.showBackButton && !viewModel.searchBarVisible ? View.VISIBLE : View.GONE}"
|
|
||||||
android:src="@drawable/caret_left"
|
|
||||||
android:contentDescription="@string/content_description_go_back_icon"
|
|
||||||
app:tint="?attr/color_main1_500"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"/>
|
|
||||||
|
|
||||||
<include
|
<ImageView
|
||||||
android:id="@+id/avatar"
|
android:id="@+id/back"
|
||||||
android:onClick="@{goToInfoClickListener}"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="@dimen/top_bar_height"
|
||||||
android:layout_height="wrap_content"
|
android:padding="15dp"
|
||||||
android:layout_marginTop="5dp"
|
android:adjustViewBounds="true"
|
||||||
android:layout_marginBottom="5dp"
|
android:onClick="@{backClickListener}"
|
||||||
android:layout_marginStart="5dp"
|
android:visibility="@{viewModel.isInCallConversation || viewModel.showBackButton && !viewModel.searchBarVisible ? View.VISIBLE : View.GONE}"
|
||||||
layout="@layout/contact_avatar"
|
android:src="@drawable/caret_left"
|
||||||
bind:model="@{viewModel.avatarModel}"
|
android:contentDescription="@string/content_description_go_back_icon"
|
||||||
app:layout_constraintStart_toEndOf="@id/back"
|
app:tint="?attr/color_main1_500"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<include
|
||||||
style="@style/default_text_style"
|
android:id="@+id/avatar"
|
||||||
android:id="@+id/title"
|
android:onClick="@{goToInfoClickListener}"
|
||||||
android:onClick="@{goToInfoClickListener}"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginTop="5dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:maxLines="1"
|
layout="@layout/contact_avatar"
|
||||||
android:ellipsize="end"
|
bind:model="@{viewModel.avatarModel}"
|
||||||
android:text="@{viewModel.isGroup ? viewModel.subject : viewModel.avatarModel.name, default=`John Doe`}"
|
app:layout_constraintStart_toEndOf="@id/back"
|
||||||
android:textSize="16sp"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
android:textColor="?attr/color_main2_600"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/start_call"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/avatar"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/subtitle_barrier"/>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/subtitle_barrier"
|
style="@style/default_text_style"
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/title"
|
||||||
android:layout_height="wrap_content"
|
android:onClick="@{goToInfoClickListener}"
|
||||||
app:barrierDirection="top"
|
android:layout_width="0dp"
|
||||||
app:constraint_referenced_ids="muted, ephemeral_enabled" />
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
<ImageView
|
android:layout_marginEnd="5dp"
|
||||||
android:id="@+id/muted"
|
android:maxLines="1"
|
||||||
android:layout_width="@dimen/small_icon_size"
|
android:ellipsize="end"
|
||||||
android:layout_height="@dimen/small_icon_size"
|
android:text="@{viewModel.isGroup ? viewModel.subject : viewModel.avatarModel.name, default=`John Doe`}"
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:src="@drawable/bell_simple_slash"
|
|
||||||
android:contentDescription="@string/content_description_chat_muted"
|
|
||||||
android:visibility="@{viewModel.isMuted ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/title"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/ephemeral_enabled"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/title"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"
|
|
||||||
app:tint="@color/main1_500"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/ephemeral_enabled"
|
|
||||||
android:layout_width="@dimen/small_icon_size"
|
|
||||||
android:layout_height="@dimen/small_icon_size"
|
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:src="@drawable/clock_countdown"
|
|
||||||
android:contentDescription="@string/content_description_chat_ephemeral_enabled"
|
|
||||||
android:visibility="@{viewModel.ephemeralLifetime > 0L ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/muted"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/title"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/avatar"
|
|
||||||
app:tint="@color/main1_500"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/show_menu"
|
|
||||||
android:onClick="@{showMenuClickListener}"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="@dimen/top_bar_height"
|
|
||||||
android:padding="15dp"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:src="@drawable/dots_three_vertical"
|
|
||||||
android:contentDescription="@string/content_description_show_popup_menu"
|
|
||||||
android:visibility="@{viewModel.isInCallConversation ? View.GONE : View.VISIBLE}"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:tint="?attr/color_main2_500"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/start_call"
|
|
||||||
android:onClick="@{() -> viewModel.startCall()}"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="@dimen/top_bar_height"
|
|
||||||
android:padding="15dp"
|
|
||||||
android:src="@drawable/phone"
|
|
||||||
android:contentDescription="@string/content_description_call_start"
|
|
||||||
android:visibility="@{viewModel.isInCallConversation || viewModel.isReadOnly || viewModel.searchBarVisible ? View.GONE : View.VISIBLE}"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/show_menu"
|
|
||||||
app:tint="?attr/color_main2_500" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/cancel_search"
|
|
||||||
android:onClick="@{() -> viewModel.closeSearchBar()}"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:padding="15dp"
|
|
||||||
android:src="@drawable/caret_left"
|
|
||||||
android:contentDescription="@string/content_description_cancel_filter"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/search"
|
|
||||||
app:tint="?attr/color_main2_500" />
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
style="?attr/textInputFilledStyle"
|
|
||||||
android:id="@+id/search"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/top_bar_height"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:textColorHint="?attr/color_main2_400"
|
|
||||||
app:hintEnabled="false"
|
|
||||||
app:hintAnimationEnabled="false"
|
|
||||||
app:hintTextColor="?attr/color_main2_400"
|
|
||||||
app:boxStrokeWidth="0dp"
|
|
||||||
app:boxStrokeWidthFocused="0dp"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/clear_field"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/cancel_search"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:textCursorDrawable="@null"
|
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:inputType="text"
|
android:textColor="?attr/color_main2_600"
|
||||||
android:paddingVertical="1dp"
|
android:gravity="center_vertical"
|
||||||
android:text="@={viewModel.searchFilter}"
|
app:layout_constraintEnd_toStartOf="@id/start_call"
|
||||||
android:background="@android:color/transparent" />
|
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/subtitle_barrier"/>
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
<androidx.constraintlayout.widget.Barrier
|
||||||
|
android:id="@+id/subtitle_barrier"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:barrierDirection="top"
|
||||||
|
app:constraint_referenced_ids="muted, ephemeral_enabled" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/clear_field"
|
android:id="@+id/muted"
|
||||||
android:onClick="@{() -> viewModel.clearFilter()}"
|
android:layout_width="@dimen/small_icon_size"
|
||||||
android:enabled="@{viewModel.searchFilter.length() > 0}"
|
android:layout_height="@dimen/small_icon_size"
|
||||||
android:layout_width="wrap_content"
|
android:layout_marginEnd="5dp"
|
||||||
android:layout_height="wrap_content"
|
android:src="@drawable/bell_simple_slash"
|
||||||
android:padding="6dp"
|
android:contentDescription="@string/content_description_chat_muted"
|
||||||
android:layout_marginEnd="9dp"
|
android:visibility="@{viewModel.isMuted ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
android:src="@drawable/x"
|
app:layout_constraintStart_toStartOf="@id/title"
|
||||||
android:contentDescription="@string/content_description_clear_filter"
|
app:layout_constraintEnd_toStartOf="@id/ephemeral_enabled"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/search"
|
app:layout_constraintTop_toBottomOf="@id/title"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintBottom_toBottomOf="@id/avatar"
|
||||||
app:layout_constraintTop_toTopOf="@id/search"
|
app:tint="@color/main1_500"/>
|
||||||
app:tint="?attr/color_main2_500" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<ImageView
|
||||||
android:id="@+id/events_list"
|
android:id="@+id/ephemeral_enabled"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="@dimen/small_icon_size"
|
||||||
android:layout_height="0dp"
|
android:layout_height="@dimen/small_icon_size"
|
||||||
android:layout_marginTop="55dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:paddingBottom="5dp"
|
android:src="@drawable/clock_countdown"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
android:contentDescription="@string/content_description_chat_ephemeral_enabled"
|
||||||
app:layout_constraintBottom_toTopOf="@id/composing"/>
|
android:visibility="@{viewModel.ephemeralLifetime > 0L ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/muted"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/title"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"
|
||||||
|
app:tint="@color/main1_500"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/show_menu"
|
||||||
|
android:onClick="@{showMenuClickListener}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/top_bar_height"
|
||||||
|
android:padding="15dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:src="@drawable/dots_three_vertical"
|
||||||
|
android:contentDescription="@string/content_description_show_popup_menu"
|
||||||
|
android:visibility="@{viewModel.isInCallConversation ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:tint="?attr/color_main2_500"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/start_call"
|
||||||
|
android:onClick="@{() -> viewModel.startCall()}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/top_bar_height"
|
||||||
|
android:padding="15dp"
|
||||||
|
android:src="@drawable/phone"
|
||||||
|
android:contentDescription="@string/content_description_call_start"
|
||||||
|
android:visibility="@{viewModel.isInCallConversation || viewModel.isReadOnly || viewModel.searchBarVisible ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/show_menu"
|
||||||
|
app:tint="?attr/color_main2_500" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cancel_search"
|
||||||
|
android:onClick="@{() -> viewModel.closeSearchBar()}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:padding="15dp"
|
||||||
|
android:src="@drawable/caret_left"
|
||||||
|
android:contentDescription="@string/content_description_cancel_filter"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/search"
|
||||||
|
app:tint="?attr/color_main2_500" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="?attr/textInputFilledStyle"
|
||||||
|
android:id="@+id/search"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="@dimen/top_bar_height"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColorHint="?attr/color_main2_400"
|
||||||
|
app:hintEnabled="false"
|
||||||
|
app:hintAnimationEnabled="false"
|
||||||
|
app:hintTextColor="?attr/color_main2_400"
|
||||||
|
app:boxStrokeWidth="0dp"
|
||||||
|
app:boxStrokeWidthFocused="0dp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/clear_field"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/cancel_search"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:textCursorDrawable="@null"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:inputType="text"
|
||||||
|
android:paddingVertical="1dp"
|
||||||
|
android:text="@={viewModel.searchFilter}"
|
||||||
|
android:background="@android:color/transparent" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/clear_field"
|
||||||
|
android:onClick="@{() -> viewModel.clearFilter()}"
|
||||||
|
android:enabled="@{viewModel.searchFilter.length() > 0}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="6dp"
|
||||||
|
android:layout_marginEnd="9dp"
|
||||||
|
android:src="@drawable/x"
|
||||||
|
android:contentDescription="@string/content_description_clear_filter"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/search"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/search"
|
||||||
|
app:tint="?attr/color_main2_500" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/events_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="55dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/composing"/>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/secured_event"
|
||||||
|
android:onClick="@{endToEndEncryptedEventClickListener}"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{viewModel.isEmpty && viewModel.isEndToEndEncrypted ? View.VISIBLE : View.GONE}"
|
||||||
|
layout="@layout/chat_conversation_secured_first_event"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/events_list"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/events_list"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/events_list" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/default_text_style_800"
|
||||||
|
android:id="@+id/no_result"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/list_filter_no_result_found"
|
||||||
|
android:textColor="?attr/color_main2_600"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:visibility="@{viewModel.noMatchingResultForFilter ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/search"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/send_area"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/default_text_style_300"
|
||||||
|
android:id="@+id/composing"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:background="?attr/color_main2_000"
|
||||||
|
android:text="@{viewModel.composingLabel, default=`John Doe is composing...`}"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="?attr/color_main2_400"
|
||||||
|
android:visibility="@{viewModel.composingLabel.length() == 0 ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/warning_disabled_not_secured"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
style="@style/default_text_style"
|
||||||
|
android:id="@+id/warning_disabled_not_secured"
|
||||||
|
android:onClick="@{warningConversationDisabledClickListener}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{viewModel.isDisabledBecauseNotSecured ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
layout="@layout/chat_conversation_send_area_disabled_unsecured_warning"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/send_area"/>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/send_area"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{viewModel.isReadOnly || viewModel.isDisabledBecauseNotSecured ? View.GONE : View.VISIBLE}"
|
||||||
|
layout="@layout/chat_conversation_send_area"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
bind:openFilePickerClickListener="@{openFilePickerClickListener}"
|
||||||
|
bind:openCameraClickListener="@{openCameraClickListener}"
|
||||||
|
bind:viewModel="@{sendMessageViewModel}"/>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/scroll_to_bottom"
|
||||||
|
android:onClick="@{scrollToBottomClickListener}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|bottom"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:src="@drawable/caret_double_down"
|
||||||
|
android:contentDescription="@string/content_description_chat_scroll_to_bottom_or_first_unread"
|
||||||
|
android:visibility="@{viewModel.isUserScrollingUp ? View.VISIBLE : View.GONE}"
|
||||||
|
app:tint="?attr/color_on_main"
|
||||||
|
app:backgroundTint="?attr/color_main1_500"
|
||||||
|
app:shapeAppearanceOverlay="@style/rounded"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/send_area" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/default_text_style"
|
||||||
|
android:id="@+id/unread_messages"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginTop="-13dp"
|
||||||
|
android:layout_marginStart="-11dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/shape_red_round"
|
||||||
|
android:text="@{String.valueOf(viewModel.unreadMessagesCount), default=`1`}"
|
||||||
|
android:textColor="?attr/color_on_main"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:visibility="@{viewModel.isUserScrollingUp && viewModel.unreadMessagesCount > 0 ? View.VISIBLE : View.GONE}"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/scroll_to_bottom"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/scroll_to_bottom"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/secured_event"
|
android:id="@+id/message_bottom_sheet"
|
||||||
android:onClick="@{endToEndEncryptedEventClickListener}"
|
layout="@layout/chat_message_bottom_sheet" />
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="@{viewModel.isEmpty && viewModel.isEndToEndEncrypted ? View.VISIBLE : View.GONE}"
|
|
||||||
layout="@layout/chat_conversation_secured_first_event"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/events_list"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/events_list"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/events_list" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
style="@style/default_text_style_800"
|
|
||||||
android:id="@+id/no_result"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/list_filter_no_result_found"
|
|
||||||
android:textColor="?attr/color_main2_600"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:visibility="@{viewModel.noMatchingResultForFilter ? View.VISIBLE : View.GONE}"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/search"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/send_area"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
style="@style/default_text_style_300"
|
|
||||||
android:id="@+id/composing"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:paddingBottom="5dp"
|
|
||||||
android:background="?attr/color_main2_000"
|
|
||||||
android:text="@{viewModel.composingLabel, default=`John Doe is composing...`}"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textColor="?attr/color_main2_400"
|
|
||||||
android:visibility="@{viewModel.composingLabel.length() == 0 ? View.GONE : View.VISIBLE}"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/warning_disabled_not_secured"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
style="@style/default_text_style"
|
|
||||||
android:id="@+id/warning_disabled_not_secured"
|
|
||||||
android:onClick="@{warningConversationDisabledClickListener}"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="@{viewModel.isDisabledBecauseNotSecured ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
layout="@layout/chat_conversation_send_area_disabled_unsecured_warning"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/send_area"/>
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/send_area"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="@{viewModel.isReadOnly || viewModel.isDisabledBecauseNotSecured ? View.GONE : View.VISIBLE}"
|
|
||||||
layout="@layout/chat_conversation_send_area"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
bind:openFilePickerClickListener="@{openFilePickerClickListener}"
|
|
||||||
bind:openCameraClickListener="@{openCameraClickListener}"
|
|
||||||
bind:viewModel="@{sendMessageViewModel}"/>
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/scroll_to_bottom"
|
|
||||||
android:onClick="@{scrollToBottomClickListener}"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|bottom"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:src="@drawable/caret_double_down"
|
|
||||||
android:contentDescription="@string/content_description_chat_scroll_to_bottom_or_first_unread"
|
|
||||||
android:visibility="@{viewModel.isUserScrollingUp ? View.VISIBLE : View.GONE}"
|
|
||||||
app:tint="?attr/color_on_main"
|
|
||||||
app:backgroundTint="?attr/color_main1_500"
|
|
||||||
app:shapeAppearanceOverlay="@style/rounded"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/send_area" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
style="@style/default_text_style"
|
|
||||||
android:id="@+id/unread_messages"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginTop="-13dp"
|
|
||||||
android:layout_marginStart="-11dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:background="@drawable/shape_red_round"
|
|
||||||
android:text="@{String.valueOf(viewModel.unreadMessagesCount), default=`1`}"
|
|
||||||
android:textColor="?attr/color_on_main"
|
|
||||||
android:textSize="13sp"
|
|
||||||
android:visibility="@{viewModel.isUserScrollingUp && viewModel.unreadMessagesCount > 0 ? View.VISIBLE : View.GONE}"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/scroll_to_bottom"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/scroll_to_bottom"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/message_bottom_sheet"
|
android:id="@+id/long_press_menu"
|
||||||
layout="@layout/chat_message_bottom_sheet" />
|
android:visibility="@{messageLongPressViewModel.visible ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
bind:viewModel="@{messageLongPressViewModel}"
|
||||||
|
layout="@layout/chat_bubble_long_press_menu" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</layout>
|
</layout>
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
<color name="gray_200">#EDEDED</color>
|
<color name="gray_200">#EDEDED</color>
|
||||||
<color name="gray_200_night">#1F1F1F</color>
|
<color name="gray_200_night">#1F1F1F</color>
|
||||||
<color name="gray_300">#C9C9C9</color>
|
<color name="gray_300">#C9C9C9</color>
|
||||||
|
<color name="gray_300_alpha_40">#66C9C9C9</color>
|
||||||
<color name="gray_400">#949494</color>
|
<color name="gray_400">#949494</color>
|
||||||
<color name="gray_500">#4E4E4E</color>
|
<color name="gray_500">#4E4E4E</color>
|
||||||
<color name="gray_600">#2E3030</color>
|
<color name="gray_600">#2E3030</color>
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,26 @@
|
||||||
<item name="android:drawableTint">?attr/color_danger_500</item>
|
<item name="android:drawableTint">?attr/color_danger_500</item>
|
||||||
<item name="android:drawablePadding">8dp</item>
|
<item name="android:drawablePadding">8dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
<style name="popup_menu_action_label_style">
|
||||||
|
<item name="android:fontFamily">@font/noto_sans</item>
|
||||||
|
<item name="android:textSize">14sp</item>
|
||||||
|
<item name="android:textColor">?attr/color_main2_500</item>
|
||||||
|
<item name="android:maxLines">1</item>
|
||||||
|
<item name="android:ellipsize">end</item>
|
||||||
|
<item name="android:padding">15dp</item>
|
||||||
|
<item name="android:drawableTint">?attr/color_main2_500</item>
|
||||||
|
<item name="android:drawablePadding">8dp</item>
|
||||||
|
</style>
|
||||||
|
<style name="popup_menu_danger_action_label_style">
|
||||||
|
<item name="android:fontFamily">@font/noto_sans</item>
|
||||||
|
<item name="android:textSize">14sp</item>
|
||||||
|
<item name="android:textColor">?attr/color_danger_500</item>
|
||||||
|
<item name="android:maxLines">1</item>
|
||||||
|
<item name="android:ellipsize">end</item>
|
||||||
|
<item name="android:padding">15dp</item>
|
||||||
|
<item name="android:drawableTint">?attr/color_danger_500</item>
|
||||||
|
<item name="android:drawablePadding">8dp</item>
|
||||||
|
</style>
|
||||||
<style name="call_start_numpad_digits_style">
|
<style name="call_start_numpad_digits_style">
|
||||||
<item name="android:fontFamily">@font/noto_sans</item>
|
<item name="android:fontFamily">@font/noto_sans</item>
|
||||||
<item name="android:textColor">@color/gray_main2_600</item>
|
<item name="android:textColor">@color/gray_main2_600</item>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue