mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-24 05:55:39 +03:00
Better Call Started Indicator
- Pinned to MessageInputFragment - Collapsable - Looks cool Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
parent
3e10813ae0
commit
990f6ec3fa
8 changed files with 222 additions and 180 deletions
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* Nextcloud Talk - Android Client
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2023 Julius Linus <julius.linus@nextcloud.com>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
package com.nextcloud.talk.adapters.messages
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.view.View
|
|
||||||
import autodagger.AutoInjector
|
|
||||||
import coil.Coil.imageLoader
|
|
||||||
import coil.request.ImageRequest
|
|
||||||
import coil.target.Target
|
|
||||||
import coil.transform.CircleCropTransformation
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
||||||
import com.nextcloud.talk.databinding.CallStartedMessageBinding
|
|
||||||
import com.nextcloud.talk.chat.data.model.ChatMessage
|
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
|
||||||
import com.nextcloud.talk.users.UserManager
|
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.stfalcon.chatkit.messages.MessageHolders
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class CallStartedViewHolder(incomingView: View, payload: Any) :
|
|
||||||
MessageHolders.BaseIncomingMessageViewHolder<ChatMessage>(incomingView, payload) {
|
|
||||||
private val binding: CallStartedMessageBinding = CallStartedMessageBinding.bind(incomingView)
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var context: Context
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var userManager: UserManager
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var viewThemeUtils: ViewThemeUtils
|
|
||||||
|
|
||||||
private lateinit var messageInterface: CallStartedMessageInterface
|
|
||||||
|
|
||||||
override fun onBind(message: ChatMessage) {
|
|
||||||
super.onBind(message)
|
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
|
||||||
themeBackground()
|
|
||||||
setUpAvatarProfile(message)
|
|
||||||
binding.callAuthorChip.text = message.actorDisplayName
|
|
||||||
binding.joinVideoCall.setOnClickListener { messageInterface.joinVideoCall() }
|
|
||||||
binding.joinAudioCall.setOnClickListener { messageInterface.joinAudioCall() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun themeBackground() {
|
|
||||||
binding.callStartedBackground.apply {
|
|
||||||
viewThemeUtils.talk.themeOutgoingMessageBubble(this, grouped = true, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.callAuthorChip.apply {
|
|
||||||
viewThemeUtils.material.colorChipBackground(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpAvatarProfile(message: ChatMessage) {
|
|
||||||
val user = userManager.currentUser.blockingGet()
|
|
||||||
val url: String = if (message.actorType == "guests" || message.actorType == "guest") {
|
|
||||||
ApiUtils.getUrlForGuestAvatar(
|
|
||||||
user!!.baseUrl!!,
|
|
||||||
message.actorDisplayName,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
ApiUtils.getUrlForAvatar(user!!.baseUrl!!, message.actorDisplayName, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
val imageRequest: ImageRequest = ImageRequest.Builder(context)
|
|
||||||
.data(url)
|
|
||||||
.crossfade(true)
|
|
||||||
.transformations(CircleCropTransformation())
|
|
||||||
.target(object : Target {
|
|
||||||
override fun onStart(placeholder: Drawable?) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(error: Drawable?) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSuccess(result: Drawable) {
|
|
||||||
binding.callAuthorChip.chipIcon = result
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build()
|
|
||||||
|
|
||||||
imageLoader(context).enqueue(imageRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun assignCallStartedMessageInterface(inf: CallStartedMessageInterface) {
|
|
||||||
messageInterface = inf
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun viewDetached() {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun viewAttached() {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun viewRecycled() {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val TAG: String? = CallStartedViewHolder::class.simpleName
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -68,9 +68,6 @@ public class TalkMessagesListAdapter<M extends IMessage> extends MessagesListAda
|
||||||
} else if (holder instanceof SystemMessageViewHolder holderInstance) {
|
} else if (holder instanceof SystemMessageViewHolder holderInstance) {
|
||||||
holderInstance.assignSystemMessageInterface(chatActivity);
|
holderInstance.assignSystemMessageInterface(chatActivity);
|
||||||
|
|
||||||
} else if (holder instanceof CallStartedViewHolder holderInstance) {
|
|
||||||
holderInstance.assignCallStartedMessageInterface(chatActivity);
|
|
||||||
|
|
||||||
} else if (holder instanceof TemporaryMessageViewHolder holderInstance) {
|
} else if (holder instanceof TemporaryMessageViewHolder holderInstance) {
|
||||||
holderInstance.assignTemporaryMessageInterface(chatActivity);
|
holderInstance.assignTemporaryMessageInterface(chatActivity);
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,6 @@ import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.activities.CallActivity
|
import com.nextcloud.talk.activities.CallActivity
|
||||||
import com.nextcloud.talk.activities.TakePhotoActivity
|
import com.nextcloud.talk.activities.TakePhotoActivity
|
||||||
import com.nextcloud.talk.adapters.messages.CallStartedMessageInterface
|
import com.nextcloud.talk.adapters.messages.CallStartedMessageInterface
|
||||||
import com.nextcloud.talk.adapters.messages.CallStartedViewHolder
|
|
||||||
import com.nextcloud.talk.adapters.messages.CommonMessageInterface
|
import com.nextcloud.talk.adapters.messages.CommonMessageInterface
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingDeckCardViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingDeckCardViewHolder
|
||||||
import com.nextcloud.talk.adapters.messages.IncomingLinkPreviewMessageViewHolder
|
import com.nextcloud.talk.adapters.messages.IncomingLinkPreviewMessageViewHolder
|
||||||
|
@ -879,7 +878,7 @@ class ChatActivity :
|
||||||
}
|
}
|
||||||
|
|
||||||
processExpiredMessages()
|
processExpiredMessages()
|
||||||
processCallStartedMessages(chatMessageList)
|
processCallStartedMessages()
|
||||||
|
|
||||||
adapter?.notifyDataSetChanged()
|
adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
@ -1199,17 +1198,6 @@ class ChatActivity :
|
||||||
R.layout.item_custom_outcoming_preview_message
|
R.layout.item_custom_outcoming_preview_message
|
||||||
)
|
)
|
||||||
|
|
||||||
messageHolders.registerContentType(
|
|
||||||
CONTENT_TYPE_CALL_STARTED,
|
|
||||||
CallStartedViewHolder::class.java,
|
|
||||||
payload,
|
|
||||||
R.layout.call_started_message,
|
|
||||||
CallStartedViewHolder::class.java,
|
|
||||||
payload,
|
|
||||||
R.layout.call_started_message,
|
|
||||||
this
|
|
||||||
)
|
|
||||||
|
|
||||||
messageHolders.registerContentType(
|
messageHolders.registerContentType(
|
||||||
CONTENT_TYPE_TEMP,
|
CONTENT_TYPE_TEMP,
|
||||||
TemporaryMessageViewHolder::class.java,
|
TemporaryMessageViewHolder::class.java,
|
||||||
|
@ -2559,7 +2547,7 @@ class ChatActivity :
|
||||||
webSocketInstance?.getSignalingMessageReceiver()?.addListener(conversationMessageListener)
|
webSocketInstance?.getSignalingMessageReceiver()?.addListener(conversationMessageListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processCallStartedMessages(chatMessageList: List<ChatMessage>) {
|
private fun processCallStartedMessages() {
|
||||||
try {
|
try {
|
||||||
val mostRecentCallSystemMessage = adapter?.items?.first {
|
val mostRecentCallSystemMessage = adapter?.items?.first {
|
||||||
it.item is ChatMessage &&
|
it.item is ChatMessage &&
|
||||||
|
@ -2577,8 +2565,7 @@ class ChatActivity :
|
||||||
|
|
||||||
if (mostRecentCallSystemMessage != null) {
|
if (mostRecentCallSystemMessage != null) {
|
||||||
processMostRecentMessage(
|
processMostRecentMessage(
|
||||||
mostRecentCallSystemMessage as ChatMessage,
|
mostRecentCallSystemMessage as ChatMessage
|
||||||
chatMessageList
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: NoSuchElementException) {
|
} catch (e: NoSuchElementException) {
|
||||||
|
@ -3542,29 +3529,21 @@ class ChatActivity :
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processMostRecentMessage(recent: ChatMessage, chatMessageList: List<ChatMessage>) {
|
private fun processMostRecentMessage(recent: ChatMessage) {
|
||||||
when (recent.systemMessageType) {
|
when (recent.systemMessageType) {
|
||||||
ChatMessage.SystemMessageType.CALL_STARTED -> { // add CallStartedMessage with id -2
|
ChatMessage.SystemMessageType.CALL_STARTED -> {
|
||||||
if (!callStarted) {
|
if (!callStarted) {
|
||||||
val callStartedChatMessage = ChatMessage()
|
messageInputViewModel.showCallStartedIndicator(recent, true)
|
||||||
callStartedChatMessage.jsonMessageId = CALL_STARTED_ID
|
|
||||||
callStartedChatMessage.actorId = "-2"
|
|
||||||
val name = if (recent.actorDisplayName.isNullOrEmpty()) "Guest" else recent.actorDisplayName
|
|
||||||
callStartedChatMessage.actorDisplayName = name
|
|
||||||
callStartedChatMessage.actorType = recent.actorType
|
|
||||||
callStartedChatMessage.timestamp = chatMessageList[0].timestamp
|
|
||||||
callStartedChatMessage.message = null
|
|
||||||
adapter?.addToStart(callStartedChatMessage, false)
|
|
||||||
callStarted = true
|
callStarted = true
|
||||||
}
|
}
|
||||||
} // remove CallStartedMessage with id -2
|
}
|
||||||
ChatMessage.SystemMessageType.CALL_ENDED,
|
ChatMessage.SystemMessageType.CALL_ENDED,
|
||||||
ChatMessage.SystemMessageType.CALL_MISSED,
|
ChatMessage.SystemMessageType.CALL_MISSED,
|
||||||
ChatMessage.SystemMessageType.CALL_TRIED,
|
ChatMessage.SystemMessageType.CALL_TRIED,
|
||||||
ChatMessage.SystemMessageType.CALL_ENDED_EVERYONE -> {
|
ChatMessage.SystemMessageType.CALL_ENDED_EVERYONE -> {
|
||||||
adapter?.deleteById("-2")
|
|
||||||
callStarted = false
|
callStarted = false
|
||||||
} // remove message of id -2
|
messageInputViewModel.showCallStartedIndicator(recent, false)
|
||||||
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ package com.nextcloud.talk.chat
|
||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
|
@ -36,6 +37,7 @@ import android.widget.PopupMenu
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
|
@ -43,7 +45,11 @@ import androidx.emoji2.widget.EmojiTextView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
|
import coil.Coil.imageLoader
|
||||||
import coil.load
|
import coil.load
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import coil.target.Target
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
@ -118,6 +124,7 @@ class MessageInputFragment : Fragment() {
|
||||||
private var mentionAutocomplete: Autocomplete<*>? = null
|
private var mentionAutocomplete: Autocomplete<*>? = null
|
||||||
private var xcounter = 0f
|
private var xcounter = 0f
|
||||||
private var ycounter = 0f
|
private var ycounter = 0f
|
||||||
|
private var isCollapsed = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -196,6 +203,49 @@ class MessageInputFragment : Fragment() {
|
||||||
binding.fragmentConnectionLost.text = getString(R.string.connection_lost_sent_messages_are_queued)
|
binding.fragmentConnectionLost.text = getString(R.string.connection_lost_sent_messages_are_queued)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chatActivity.messageInputViewModel.callStartedFlow.observe(viewLifecycleOwner) {
|
||||||
|
val (message, show) = it
|
||||||
|
if (show) {
|
||||||
|
binding.fragmentCallStarted.callAuthorChip.text = message.actorDisplayName
|
||||||
|
binding.fragmentCallStarted.callAuthorChipSecondary.text = message.actorDisplayName
|
||||||
|
val user = userManager.currentUser.blockingGet()
|
||||||
|
val url: String = if (message.actorType == "guests" || message.actorType == "guest") {
|
||||||
|
ApiUtils.getUrlForGuestAvatar(
|
||||||
|
user!!.baseUrl!!,
|
||||||
|
message.actorDisplayName,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ApiUtils.getUrlForAvatar(user!!.baseUrl!!, message.actorId, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val imageRequest: ImageRequest = ImageRequest.Builder(requireContext())
|
||||||
|
.data(url)
|
||||||
|
.crossfade(true)
|
||||||
|
.transformations(CircleCropTransformation())
|
||||||
|
.target(object : Target {
|
||||||
|
override fun onStart(placeholder: Drawable?) {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(error: Drawable?) {
|
||||||
|
// unused atm
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuccess(result: Drawable) {
|
||||||
|
binding.fragmentCallStarted.callAuthorChip.chipIcon = result
|
||||||
|
binding.fragmentCallStarted.callAuthorChipSecondary.chipIcon = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
|
||||||
|
imageLoader(requireContext()).enqueue(imageRequest)
|
||||||
|
binding.fragmentCallStarted.root.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.fragmentCallStarted.root.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleUI(isOnline: Boolean, connectionGained: Boolean) {
|
private fun handleUI(isOnline: Boolean, connectionGained: Boolean) {
|
||||||
|
@ -390,6 +440,41 @@ class MessageInputFragment : Fragment() {
|
||||||
|
|
||||||
binding.fragmentMessageInputView.button?.contentDescription =
|
binding.fragmentMessageInputView.button?.contentDescription =
|
||||||
resources.getString(R.string.nc_description_send_message_button)
|
resources.getString(R.string.nc_description_send_message_button)
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.joinAudioCall.setOnClickListener {
|
||||||
|
chatActivity.joinAudioCall()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.joinVideoCall.setOnClickListener {
|
||||||
|
chatActivity.joinVideoCall()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.callStartedCloseBtn.setOnClickListener {
|
||||||
|
isCollapsed = !isCollapsed
|
||||||
|
if (isCollapsed) {
|
||||||
|
binding.fragmentCallStarted.callAuthorLayout.visibility = View.GONE
|
||||||
|
binding.fragmentCallStarted.callBtnLayout.visibility = View.GONE
|
||||||
|
binding.fragmentCallStarted.callAuthorChipSecondary.visibility = View.VISIBLE
|
||||||
|
binding.fragmentCallStarted.callStartedSecondaryText.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.fragmentCallStarted.callAuthorLayout.visibility = View.VISIBLE
|
||||||
|
binding.fragmentCallStarted.callBtnLayout.visibility = View.VISIBLE
|
||||||
|
binding.fragmentCallStarted.callAuthorChipSecondary.visibility = View.GONE
|
||||||
|
binding.fragmentCallStarted.callStartedSecondaryText.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
setDropDown(isCollapsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setDropDown(collapsed: Boolean) {
|
||||||
|
val drawable = if (collapsed) {
|
||||||
|
AppCompatResources.getDrawable(requireContext(), R.drawable.ic_keyboard_arrow_up)
|
||||||
|
} else {
|
||||||
|
AppCompatResources.getDrawable(requireContext(), R.drawable.ic_keyboard_arrow_down)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.callStartedCloseBtn.setImageDrawable(drawable)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("ClickableViewAccessibility", "CyclomaticComplexMethod", "LongMethod")
|
@Suppress("ClickableViewAccessibility", "CyclomaticComplexMethod", "LongMethod")
|
||||||
|
@ -907,6 +992,22 @@ class MessageInputFragment : Fragment() {
|
||||||
binding.fragmentEditView.clearEdit.let {
|
binding.fragmentEditView.clearEdit.let {
|
||||||
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
|
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.callStartedBackground.apply {
|
||||||
|
viewThemeUtils.talk.themeOutgoingMessageBubble(this, grouped = true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.callAuthorChip.apply {
|
||||||
|
viewThemeUtils.material.colorChipBackground(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.callAuthorChipSecondary.apply {
|
||||||
|
viewThemeUtils.material.colorChipBackground(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.fragmentCallStarted.callStartedCloseBtn.apply {
|
||||||
|
viewThemeUtils.platform.colorImageView(this, ColorRole.PRIMARY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelReply() {
|
private fun cancelReply() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import androidx.lifecycle.asLiveData
|
||||||
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
|
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
|
||||||
import com.nextcloud.talk.chat.data.io.AudioRecorderManager
|
import com.nextcloud.talk.chat.data.io.AudioRecorderManager
|
||||||
import com.nextcloud.talk.chat.data.io.MediaPlayerManager
|
import com.nextcloud.talk.chat.data.io.MediaPlayerManager
|
||||||
|
import com.nextcloud.talk.chat.data.model.ChatMessage
|
||||||
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
|
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
|
||||||
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
|
import com.nextcloud.talk.models.json.chat.ChatOverallSingleMessage
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
|
@ -129,6 +130,10 @@ class MessageInputViewModel @Inject constructor(
|
||||||
val messageQueueFlow: LiveData<List<QueuedMessage>>
|
val messageQueueFlow: LiveData<List<QueuedMessage>>
|
||||||
get() = _messageQueueFlow
|
get() = _messageQueueFlow
|
||||||
|
|
||||||
|
private val _callStartedFlow: MutableLiveData<Pair<ChatMessage, Boolean>> = MutableLiveData()
|
||||||
|
val callStartedFlow: LiveData<Pair<ChatMessage, Boolean>>
|
||||||
|
get() = _callStartedFlow
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
fun sendChatMessage(
|
fun sendChatMessage(
|
||||||
internalId: String,
|
internalId: String,
|
||||||
|
@ -314,6 +319,10 @@ class MessageInputViewModel @Inject constructor(
|
||||||
dataStore.saveMessageQueue(internalId, queue)
|
dataStore.saveMessageQueue(internalId, queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showCallStartedIndicator(recent: ChatMessage, show: Boolean) {
|
||||||
|
_callStartedFlow.postValue(Pair(recent, show))
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = MessageInputViewModel::class.java.simpleName
|
private val TAG = MessageInputViewModel::class.java.simpleName
|
||||||
private const val DELAY_BETWEEN_QUEUED_MESSAGES: Long = 1000
|
private const val DELAY_BETWEEN_QUEUED_MESSAGES: Long = 1000
|
||||||
|
|
21
app/src/main/res/drawable/ic_keyboard_arrow_up.xml
Normal file
21
app/src/main/res/drawable/ic_keyboard_arrow_up.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<!--
|
||||||
|
~ Nextcloud Talk - Android Client
|
||||||
|
~
|
||||||
|
~ SPDX-FileCopyrightText: 2018-2024 Google LLC
|
||||||
|
~ SPDX-License-Identifier: Apache-2.0
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<group
|
||||||
|
android:pivotX="12"
|
||||||
|
android:pivotY="12"
|
||||||
|
android:rotation="180"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M7.41,7.84L12,12.42l4.59,-4.58L18,9.25l-6,6 -6,-6z" />
|
||||||
|
</group>
|
||||||
|
</vector>
|
|
@ -20,7 +20,46 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="@dimen/standard_margin"
|
android:orientation="horizontal"
|
||||||
|
android:gravity="end">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/call_author_chip_secondary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIcon="@drawable/account_circle_48dp"
|
||||||
|
app:chipCornerRadius="@dimen/dialogBorderRadius"
|
||||||
|
tools:text="Julius James Linus"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_started_secondary_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/standard_quarter_margin"
|
||||||
|
android:text="@string/started_a_call"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/call_started_close_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/standard_margin"
|
||||||
|
android:contentDescription="@string/close_icon"
|
||||||
|
android:src="@drawable/ic_keyboard_arrow_down"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/call_author_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/standard_half_margin"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
|
@ -42,6 +81,7 @@
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/call_btn_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/fragment_connection_lost"
|
android:id="@+id/fragment_connection_lost"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -24,6 +25,15 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/fragment_call_started"
|
||||||
|
layout="@layout/call_started_message"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginVertical="@dimen/standard_margin"
|
||||||
|
android:layout_marginHorizontal="@dimen/standard_quarter_margin"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/fragment_editView"
|
android:id="@+id/fragment_editView"
|
||||||
layout="@layout/edit_message_view"
|
layout="@layout/edit_message_view"
|
||||||
|
|
Loading…
Reference in a new issue