From 595ff96d506fddf21ca687c1485809887e2608d9 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 20 Jun 2025 16:03:43 +0200 Subject: [PATCH] Use newly added chat room compose APIs to notify wether text or voice recording is being composed --- .../chat/fragment/ConversationFragment.kt | 8 ++--- .../ui/main/chat/model/ConversationModel.kt | 32 ++++--------------- .../chat/viewmodel/ConversationViewModel.kt | 27 ++++------------ .../SendMessageInConversationViewModel.kt | 11 +++++-- .../java/org/linphone/utils/LinphoneUtils.kt | 32 +++++++++++++++++++ .../main/res/drawable/chat_teardrop_dots.xml | 9 ++++++ .../res/layout/chat_conversation_fragment.xml | 18 +++++++++-- app/src/main/res/layout/chat_list_cell.xml | 12 +++---- app/src/main/res/values-fr/strings.xml | 4 +++ app/src/main/res/values/strings.xml | 4 +++ 10 files changed, 97 insertions(+), 60 deletions(-) create mode 100644 app/src/main/res/drawable/chat_teardrop_dots.xml diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt index 2b161e6a2..7335393b3 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt @@ -280,11 +280,11 @@ open class ConversationFragment : SlidingPaneChildFragment() { override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } - override fun afterTextChanged(p0: Editable?) { + override fun afterTextChanged(editable: Editable?) { if (viewModel.isGroup.value == true) { sendMessageViewModel.closeParticipantsList() - val split = p0.toString().split(" ") + val split = editable.toString().split(" ") for (part in split) { if (part == "@") { Log.i("$TAG '@' found, opening participants list") @@ -293,9 +293,7 @@ open class ConversationFragment : SlidingPaneChildFragment() { } } - if (p0.toString().isNotEmpty()) { - sendMessageViewModel.notifyChatMessageIsBeingComposed() - } + sendMessageViewModel.notifyComposing(editable.toString().isNotEmpty()) } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt b/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt index 1c9e2a3d8..3ac6edc52 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/model/ConversationModel.kt @@ -82,6 +82,8 @@ class ConversationModel val lastMessageContentIcon = MutableLiveData() + val composingIcon = MutableLiveData() + val isLastMessageOutgoing = MutableLiveData() val dateTime = MutableLiveData() @@ -428,30 +430,10 @@ class ConversationModel private fun computeComposingLabel() { val composing = chatRoom.isRemoteComposing isComposing.postValue(composing) - if (!composing) { - composingLabel.postValue("") - return - } - - val composingFriends = arrayListOf() - var label = "" - for (address in chatRoom.composingAddresses) { - val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address) - val name = avatar.name.value ?: LinphoneUtils.getDisplayName(address) - composingFriends.add(name) - label += "$name, " - } - if (composingFriends.isNotEmpty()) { - label = label.dropLast(2) - - val format = AppUtils.getStringWithPlural( - R.plurals.conversation_composing_label, - composingFriends.size, - label - ) - composingLabel.postValue(format) - } else { - composingLabel.postValue("") - } + val pair = LinphoneUtils.getComposingIconAndText(chatRoom) + val icon = pair.first + composingIcon.postValue(icon) + val label = pair.second + composingLabel.postValue(label) } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt index 92e963311..fb9572382 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt @@ -44,7 +44,6 @@ import org.linphone.ui.main.chat.model.EventLogModel import org.linphone.ui.main.chat.model.FileModel import org.linphone.ui.main.chat.model.MessageModel import org.linphone.ui.main.contacts.model.ContactAvatarModel -import org.linphone.utils.AppUtils import org.linphone.utils.Event import org.linphone.utils.FileUtils import org.linphone.utils.LinphoneUtils @@ -89,6 +88,8 @@ class ConversationViewModel val composingLabel = MutableLiveData() + val composingIcon = MutableLiveData() + val searchBarVisible = MutableLiveData() val searchFilter = MutableLiveData() @@ -906,26 +907,12 @@ class ConversationViewModel @WorkerThread private fun computeComposingLabel() { if (!isChatRoomInitialized()) return - val composingFriends = arrayListOf() - var label = "" - for (address in chatRoom.composingAddresses) { - val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address) - val name = avatar.name.value ?: LinphoneUtils.getDisplayName(address) - composingFriends.add(name) - label += "$name, " - } - if (composingFriends.isNotEmpty()) { - label = label.dropLast(2) - val format = AppUtils.getStringWithPlural( - R.plurals.conversation_composing_label, - composingFriends.size, - label - ) - composingLabel.postValue(format) - } else { - composingLabel.postValue("") - } + val pair = LinphoneUtils.getComposingIconAndText(chatRoom) + val icon = pair.first + composingIcon.postValue(icon) + val label = pair.second + composingLabel.postValue(label) } @WorkerThread diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt index ac7025547..7d3a64cf3 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt @@ -344,10 +344,14 @@ class SendMessageInConversationViewModel } @UiThread - fun notifyChatMessageIsBeingComposed() { + fun notifyComposing(composing: Boolean) { coreContext.postOnCoreThread { if (::chatRoom.isInitialized) { - chatRoom.compose() + if (composing) { + chatRoom.composeTextMessage() + } else { + chatRoom.stopComposing() + } } } } @@ -489,6 +493,7 @@ class SendMessageInConversationViewModel @UiThread fun stopVoiceMessageRecording() { coreContext.postOnCoreThread { + chatRoom.stopComposing() stopVoiceRecorder() } } @@ -496,6 +501,7 @@ class SendMessageInConversationViewModel @UiThread fun cancelVoiceMessageRecording() { coreContext.postOnCoreThread { + chatRoom.stopComposing() stopVoiceRecorder() val path = voiceMessageRecorder.file @@ -589,6 +595,7 @@ class SendMessageInConversationViewModel } else -> {} } + chatRoom.composeVoiceMessage() val duration = voiceMessageRecorder.duration val formattedDuration = SimpleDateFormat("mm:ss", Locale.getDefault()).format(duration) // duration is in ms diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt index 83d8421a3..5a5a82fe9 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt @@ -470,6 +470,38 @@ class LinphoneUtils { } } + @WorkerThread + fun getComposingIconAndText(chatRoom: ChatRoom): Pair { + val composing = chatRoom.isRemoteComposing + if (!composing) { + return Pair(0, "") + } + + var icon = R.drawable.chat_teardrop_dots + val composingFriends = arrayListOf() + var label = "" + for (participant in chatRoom.composingParticipants) { + val address = participant.address + val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address) + val name = avatar.name.value ?: getDisplayName(address) + composingFriends.add(name) + label += "$name, " + } + if (composingFriends.isNotEmpty()) { + label = label.dropLast(2) + + // TODO: use voice recording content type to change icon/text + val format = AppUtils.getStringWithPlural( + R.plurals.conversation_composing_label, + composingFriends.size, + label + ) + return Pair(icon, format) + } + + return Pair(icon, label) + } + @AnyThread fun formatEphemeralExpiration(duration: Long): String { return when (duration) { diff --git a/app/src/main/res/drawable/chat_teardrop_dots.xml b/app/src/main/res/drawable/chat_teardrop_dots.xml new file mode 100644 index 000000000..bcb1be980 --- /dev/null +++ b/app/src/main/res/drawable/chat_teardrop_dots.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/chat_conversation_fragment.xml b/app/src/main/res/layout/chat_conversation_fragment.xml index 0de030d66..b64502933 100644 --- a/app/src/main/res/layout/chat_conversation_fragment.xml +++ b/app/src/main/res/layout/chat_conversation_fragment.xml @@ -326,19 +326,33 @@ app:layout_constraintStart_toStartOf="@id/events_list" app:layout_constraintEnd_toEndOf="@id/events_list" /> + + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9846e9996..865c7c3e3 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -490,6 +490,10 @@ %s est en train d\'écrire… %s sont en train d\'écrire… + + %s est en train d\'enregistrer un message vocal… + %s sont en train d\'enregistrer un message vocal… + Ajouter des participants En réponse à : Chercher diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 584c6a32a..b32c97779 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -533,6 +533,10 @@ %s is composing… %s are composing… + + %s is recording a voice message… + %s are recording a voice message… + Add participants Replying to: Search