From 3071c079bae1a22dfbf1a56f14dec166eeb6b449 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 10 Nov 2023 11:18:47 +0100 Subject: [PATCH] Split ConversationViewModel in two --- .../chat/fragment/ConversationFragment.kt | 51 +-- .../chat/viewmodel/ConversationViewModel.kt | 243 -------------- .../SendMessageInConversationViewModel.kt | 312 ++++++++++++++++++ .../chat_conversation_attachments_area.xml | 2 +- .../res/layout/chat_conversation_fragment.xml | 5 +- .../chat_conversation_participants_area.xml | 2 +- .../layout/chat_conversation_reply_area.xml | 2 +- ...at_conversation_send_area_bottom_sheet.xml | 24 +- 8 files changed, 365 insertions(+), 276 deletions(-) create mode 100644 app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt 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 be489321d..a1f5236cb 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 @@ -70,6 +70,7 @@ import org.linphone.ui.main.chat.model.ChatMessageReactionsModel import org.linphone.ui.main.chat.view.RichEditText 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.SendMessageInConversationViewModel import org.linphone.ui.main.fragment.GenericFragment import org.linphone.utils.AppUtils import org.linphone.utils.Event @@ -90,6 +91,8 @@ class ConversationFragment : GenericFragment() { private lateinit var viewModel: ConversationViewModel + private lateinit var sendMessageViewModel: SendMessageInConversationViewModel + private lateinit var adapter: ConversationEventAdapter private lateinit var bottomSheetAdapter: ChatMessageBottomSheetAdapter @@ -107,7 +110,7 @@ class ConversationFragment : GenericFragment() { Log.i("$TAG Picked file [$uri] matching path is [$path]") if (path != null) { withContext(Dispatchers.Main) { - viewModel.addAttachment(path) + sendMessageViewModel.addAttachment(path) } } } @@ -139,12 +142,13 @@ class ConversationFragment : GenericFragment() { } override fun afterTextChanged(p0: Editable?) { - viewModel.isParticipantsListOpen.value = false + sendMessageViewModel.isParticipantsListOpen.value = false val split = p0.toString().split(" ") for (part in split) { if (part == "@") { - viewModel.isParticipantsListOpen.value = true + Log.i("$TAG '@' found, opening participants list") + sendMessageViewModel.isParticipantsListOpen.value = true } } } @@ -182,7 +186,10 @@ class ConversationFragment : GenericFragment() { binding.lifecycleOwner = viewLifecycleOwner viewModel = ViewModelProvider(this)[ConversationViewModel::class.java] + sendMessageViewModel = ViewModelProvider(this)[SendMessageInConversationViewModel::class.java] + binding.viewModel = viewModel + binding.sendMessageViewModel = sendMessageViewModel binding.setBackClickListener { goBack() @@ -212,12 +219,13 @@ class ConversationFragment : GenericFragment() { goBack() // TODO: show toast } + } else { + sendMessageViewModel.configureChatRoom(viewModel.chatRoom) } } } viewModel.events.observe(viewLifecycleOwner) { items -> - val currentCount = adapter.itemCount adapter.submitList(items) Log.i("$TAG Events (messages) list updated with [${items.size}] items") @@ -298,13 +306,13 @@ class ConversationFragment : GenericFragment() { } } - viewModel.emojiToAddEvent.observe(viewLifecycleOwner) { + sendMessageViewModel.emojiToAddEvent.observe(viewLifecycleOwner) { it.consume { emoji -> binding.sendArea.messageToSend.addCharacterAtPosition(emoji) } } - viewModel.participantUsernameToAddEvent.observe(viewLifecycleOwner) { + sendMessageViewModel.participantUsernameToAddEvent.observe(viewLifecycleOwner) { it.consume { username -> Log.i("$TAG Adding username [$username] after '@'") // Also add a space for convenience @@ -312,16 +320,16 @@ class ConversationFragment : GenericFragment() { } } - viewModel.searchFilter.observe(viewLifecycleOwner) { filter -> - viewModel.applyFilter(filter.trim()) - } - - viewModel.requestKeyboardHidingEvent.observe(viewLifecycleOwner) { + sendMessageViewModel.requestKeyboardHidingEvent.observe(viewLifecycleOwner) { it.consume { binding.search.hideKeyboard() } } + viewModel.searchFilter.observe(viewLifecycleOwner) { filter -> + viewModel.applyFilter(filter.trim()) + } + viewModel.focusSearchBarEvent.observe(viewLifecycleOwner) { it.consume { show -> if (show) { @@ -346,6 +354,13 @@ class ConversationFragment : GenericFragment() { } } + viewModel.isGroup.observe(viewLifecycleOwner) { group -> + if (group) { + Log.i("$TAG Adding text observer to chat message sending area") + binding.sendArea.messageToSend.addTextChangedListener(textObserver) + } + } + viewModel.conferenceToJoinEvent.observe(viewLifecycleOwner) { it.consume { conferenceUri -> Log.i("$TAG Requesting to go to waiting room for conference URI [$conferenceUri]") @@ -378,7 +393,7 @@ class ConversationFragment : GenericFragment() { Log.i("$TAG Rich content URI [$uri] matching path is [$path]") if (path != null) { withContext(Dispatchers.Main) { - viewModel.addAttachment(path) + sendMessageViewModel.addAttachment(path) } } } @@ -390,7 +405,7 @@ class ConversationFragment : GenericFragment() { if (files.isNotEmpty()) { Log.i("$TAG Found [${files.size}] files to share from intent") for (path in files) { - viewModel.addAttachment(path) + sendMessageViewModel.addAttachment(path) } sharedViewModel.filesToShareFromIntent.value = arrayListOf() @@ -401,13 +416,13 @@ class ConversationFragment : GenericFragment() { RichEditText.RichEditTextSendListener { override fun onControlEnterPressedAndReleased() { Log.i("$TAG Detected left control + enter key presses, sending message") - viewModel.sendMessage() + sendMessageViewModel.sendMessage() } }) binding.root.setKeyboardInsetListener { keyboardVisible -> if (keyboardVisible) { - viewModel.isEmojiPickerOpen.value = false + sendMessageViewModel.isEmojiPickerOpen.value = false } } } @@ -430,10 +445,6 @@ class ConversationFragment : GenericFragment() { } catch (e: IllegalStateException) { Log.e("$TAG Failed to register data observer to adapter: $e") } - - if (viewModel.isGroup.value == true) { - binding.sendArea.messageToSend.addTextChangedListener(textObserver) - } } override fun onPause() { @@ -497,7 +508,7 @@ class ConversationFragment : GenericFragment() { layout.setReplyClickListener { Log.i("$TAG Updating sending area to reply to selected message") - viewModel.replyToMessage(chatMessageModel) + sendMessageViewModel.replyToMessage(chatMessageModel) dialog.dismiss() } 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 c9582d806..a79a1e100 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 @@ -23,12 +23,9 @@ import androidx.annotation.UiThread import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.launch import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.core.Address -import org.linphone.core.ChatMessage import org.linphone.core.ChatRoom import org.linphone.core.ChatRoomListenerStub import org.linphone.core.EventLog @@ -37,12 +34,9 @@ import org.linphone.core.Friend import org.linphone.core.tools.Log import org.linphone.ui.main.chat.model.ChatMessageModel import org.linphone.ui.main.chat.model.EventLogModel -import org.linphone.ui.main.chat.model.FileModel -import org.linphone.ui.main.chat.model.ParticipantModel 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 class ConversationViewModel @UiThread constructor() : ViewModel() { @@ -67,30 +61,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { val composingLabel = MutableLiveData() - val textToSend = MutableLiveData() - val searchBarVisible = MutableLiveData() val searchFilter = MutableLiveData() - val isEmojiPickerOpen = MutableLiveData() - - val isParticipantsListOpen = MutableLiveData() - - val participants = MutableLiveData>() - - val isFileAttachmentsListOpen = MutableLiveData() - - val attachments = MutableLiveData>() - - val isReplying = MutableLiveData() - - val isReplyingTo = MutableLiveData() - - val isReplyingToMessage = MutableLiveData() - - val voiceRecordingInProgress = MutableLiveData() - var scrollingPosition: Int = SCROLLING_POSITION_NOT_SET val requestKeyboardHidingEvent: MutableLiveData> by lazy { @@ -113,20 +87,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { MutableLiveData>() } - val emojiToAddEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - - val participantUsernameToAddEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - val chatRoomFoundEvent = MutableLiveData>() lateinit var chatRoom: ChatRoom - private var chatMessageToReplyTo: ChatMessage? = null - private val chatRoomListener = object : ChatRoomListenerStub() { @WorkerThread override fun onChatMessageSending(chatRoom: ChatRoom, eventLog: EventLog) { @@ -204,32 +168,15 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { events.postValue(list) } - - @WorkerThread - override fun onParticipantAdded(chatRoom: ChatRoom, eventLog: EventLog) { - computeParticipantsList() - } - - @WorkerThread - override fun onParticipantRemoved(chatRoom: ChatRoom, eventLog: EventLog) { - computeParticipantsList() - } } init { searchBarVisible.value = false - isEmojiPickerOpen.value = false } override fun onCleared() { super.onCleared() - viewModelScope.launch { - for (file in attachments.value.orEmpty()) { - file.deleteFile() - } - } - coreContext.postOnCoreThread { if (::chatRoom.isInitialized) { chatRoom.removeListener(chatRoomListener) @@ -319,96 +266,6 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { } } - @UiThread - fun toggleEmojiPickerVisibility() { - isEmojiPickerOpen.value = isEmojiPickerOpen.value == false - if (isEmojiPickerOpen.value == true) { - requestKeyboardHidingEvent.value = Event(true) - } - } - - @UiThread - fun insertEmoji(emoji: String) { - emojiToAddEvent.value = Event(emoji) - } - - @UiThread - fun replyToMessage(model: ChatMessageModel) { - coreContext.postOnCoreThread { - val message = model.chatMessage - Log.i("$TAG Pending reply to chat message [${message.messageId}]") - chatMessageToReplyTo = message - isReplyingTo.postValue(model.avatarModel.friend.name) - isReplyingToMessage.postValue(LinphoneUtils.getTextDescribingMessage(message)) - isReplying.postValue(true) - } - } - - @UiThread - fun cancelReply() { - Log.i("$TAG Cancelling reply") - isReplying.value = false - chatMessageToReplyTo = null - } - - @UiThread - fun sendMessage() { - coreContext.postOnCoreThread { - val messageToReplyTo = chatMessageToReplyTo - val message = if (messageToReplyTo != null) { - Log.i("$TAG Sending message as reply to [${messageToReplyTo.messageId}]") - chatRoom.createReplyMessage(messageToReplyTo) - } else { - chatRoom.createEmptyMessage() - } - - val toSend = textToSend.value.orEmpty().trim() - if (toSend.isNotEmpty()) { - message.addUtf8TextContent(toSend) - } - - for (attachment in attachments.value.orEmpty()) { - val content = Factory.instance().createContent() - - content.type = when (attachment.mimeType) { - FileUtils.MimeType.Image -> "image" - FileUtils.MimeType.Audio -> "audio" - FileUtils.MimeType.Video -> "video" - FileUtils.MimeType.Pdf -> "application" - FileUtils.MimeType.PlainText -> "text" - else -> "file" - } - content.subtype = if (attachment.mimeType == FileUtils.MimeType.PlainText) { - "plain" - } else { - FileUtils.getExtensionFromFileName(attachment.fileName) - } - content.name = attachment.fileName - content.filePath = attachment.file // Let the file body handler take care of the upload - - message.addFileContent(content) - } - - if (message.contents.isNotEmpty()) { - Log.i("$TAG Sending message") - message.send() - } - - Log.i("$TAG Message sent, re-setting defaults") - textToSend.postValue("") - isReplying.postValue(false) - isFileAttachmentsListOpen.postValue(false) - isParticipantsListOpen.postValue(false) - isEmojiPickerOpen.postValue(false) - - // Warning: do not delete files - val attachmentsList = arrayListOf() - attachments.postValue(attachmentsList) - - chatMessageToReplyTo = null - } - } - @UiThread fun deleteChatMessage(chatMessageModel: ChatMessageModel) { coreContext.postOnCoreThread { @@ -428,85 +285,6 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { } } - @UiThread - fun closeParticipantsList() { - isParticipantsListOpen.value = false - } - - @UiThread - fun closeFileAttachmentsList() { - viewModelScope.launch { - for (file in attachments.value.orEmpty()) { - file.deleteFile() - } - } - val list = arrayListOf() - attachments.value = list - - isFileAttachmentsListOpen.value = false - } - - @UiThread - fun addAttachment(file: String) { - val list = arrayListOf() - list.addAll(attachments.value.orEmpty()) - val model = FileModel(file) { file -> - removeAttachment(file) - } - list.add(model) - attachments.value = list - - if (list.isNotEmpty()) { - isFileAttachmentsListOpen.value = true - } - } - - @UiThread - fun removeAttachment(file: String, delete: Boolean = true) { - val list = arrayListOf() - list.addAll(attachments.value.orEmpty()) - val found = list.find { - it.file == file - } - if (found != null) { - if (delete) { - viewModelScope.launch { - found.deleteFile() - } - } - list.remove(found) - } else { - Log.w("$TAG Failed to find file attachment matching [$file]") - } - attachments.value = list - - if (list.isEmpty()) { - isFileAttachmentsListOpen.value = false - } - } - - @UiThread - fun startVoiceMessageRecording() { - voiceRecordingInProgress.value = true - } - - @UiThread - fun stopVoiceMessageRecording() { - } - - @UiThread - fun cancelVoiceMessageRecording() { - voiceRecordingInProgress.value = false - } - - @UiThread - fun playVoiceMessageRecording() { - } - - @UiThread - fun pauseVoiceMessageRecording() { - } - @WorkerThread private fun configureChatRoom() { scrollingPosition = SCROLLING_POSITION_NOT_SET @@ -551,7 +329,6 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { computeEvents() chatRoom.markAsRead() - computeParticipantsList() } @WorkerThread @@ -686,24 +463,4 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { composingLabel.postValue("") } } - - @WorkerThread - private fun computeParticipantsList() { - val participantsList = arrayListOf() - - for (participant in chatRoom.participants) { - val model = ParticipantModel(participant.address, onClicked = { clicked -> - Log.i("$TAG Clicked on participant [${clicked.sipUri}]") - coreContext.postOnCoreThread { - val username = clicked.address.username - if (!username.isNullOrEmpty()) { - participantUsernameToAddEvent.postValue(Event(username)) - } - } - }) - participantsList.add(model) - } - - participants.postValue(participantsList) - } } 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 new file mode 100644 index 000000000..224cc14fc --- /dev/null +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2010-2023 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 . + */ +package org.linphone.ui.main.chat.viewmodel + +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.core.ChatMessage +import org.linphone.core.ChatRoom +import org.linphone.core.ChatRoomListenerStub +import org.linphone.core.EventLog +import org.linphone.core.Factory +import org.linphone.core.tools.Log +import org.linphone.ui.main.chat.model.ChatMessageModel +import org.linphone.ui.main.chat.model.FileModel +import org.linphone.ui.main.chat.model.ParticipantModel +import org.linphone.utils.Event +import org.linphone.utils.FileUtils +import org.linphone.utils.LinphoneUtils + +class SendMessageInConversationViewModel @UiThread constructor() : ViewModel() { + companion object { + private const val TAG = "[Send Message In Conversation ViewModel]" + } + + val textToSend = MutableLiveData() + + val isEmojiPickerOpen = MutableLiveData() + + val isParticipantsListOpen = MutableLiveData() + + val participants = MutableLiveData>() + + val isFileAttachmentsListOpen = MutableLiveData() + + val attachments = MutableLiveData>() + + val isReplying = MutableLiveData() + + val isReplyingTo = MutableLiveData() + + val isReplyingToMessage = MutableLiveData() + + val voiceRecordingInProgress = MutableLiveData() + + val requestKeyboardHidingEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val emojiToAddEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val participantUsernameToAddEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + lateinit var chatRoom: ChatRoom + + private var chatMessageToReplyTo: ChatMessage? = null + + private val chatRoomListener = object : ChatRoomListenerStub() { + @WorkerThread + override fun onParticipantAdded(chatRoom: ChatRoom, eventLog: EventLog) { + computeParticipantsList() + } + + @WorkerThread + override fun onParticipantRemoved(chatRoom: ChatRoom, eventLog: EventLog) { + computeParticipantsList() + } + } + + init { + isEmojiPickerOpen.value = false + } + + override fun onCleared() { + super.onCleared() + + viewModelScope.launch { + for (file in attachments.value.orEmpty()) { + file.deleteFile() + } + } + + coreContext.postOnCoreThread { + if (::chatRoom.isInitialized) { + chatRoom.removeListener(chatRoomListener) + } + } + } + + @UiThread + fun configureChatRoom(room: ChatRoom) { + chatRoom = room + coreContext.postOnCoreThread { + chatRoom.addListener(chatRoomListener) + computeParticipantsList() + } + } + + @UiThread + fun toggleEmojiPickerVisibility() { + isEmojiPickerOpen.value = isEmojiPickerOpen.value == false + if (isEmojiPickerOpen.value == true) { + requestKeyboardHidingEvent.value = Event(true) + } + } + + @UiThread + fun insertEmoji(emoji: String) { + emojiToAddEvent.value = Event(emoji) + } + + @UiThread + fun replyToMessage(model: ChatMessageModel) { + coreContext.postOnCoreThread { + val message = model.chatMessage + Log.i("$TAG Pending reply to chat message [${message.messageId}]") + chatMessageToReplyTo = message + isReplyingTo.postValue(model.avatarModel.friend.name) + isReplyingToMessage.postValue(LinphoneUtils.getTextDescribingMessage(message)) + isReplying.postValue(true) + } + } + + @UiThread + fun cancelReply() { + Log.i("$TAG Cancelling reply") + isReplying.value = false + chatMessageToReplyTo = null + } + + @UiThread + fun sendMessage() { + coreContext.postOnCoreThread { + val messageToReplyTo = chatMessageToReplyTo + val message = if (messageToReplyTo != null) { + Log.i("$TAG Sending message as reply to [${messageToReplyTo.messageId}]") + chatRoom.createReplyMessage(messageToReplyTo) + } else { + chatRoom.createEmptyMessage() + } + + val toSend = textToSend.value.orEmpty().trim() + if (toSend.isNotEmpty()) { + message.addUtf8TextContent(toSend) + } + + for (attachment in attachments.value.orEmpty()) { + val content = Factory.instance().createContent() + + content.type = when (attachment.mimeType) { + FileUtils.MimeType.Image -> "image" + FileUtils.MimeType.Audio -> "audio" + FileUtils.MimeType.Video -> "video" + FileUtils.MimeType.Pdf -> "application" + FileUtils.MimeType.PlainText -> "text" + else -> "file" + } + content.subtype = if (attachment.mimeType == FileUtils.MimeType.PlainText) { + "plain" + } else { + FileUtils.getExtensionFromFileName(attachment.fileName) + } + content.name = attachment.fileName + content.filePath = attachment.file // Let the file body handler take care of the upload + + message.addFileContent(content) + } + + if (message.contents.isNotEmpty()) { + Log.i("$TAG Sending message") + message.send() + } + + Log.i("$TAG Message sent, re-setting defaults") + textToSend.postValue("") + isReplying.postValue(false) + isFileAttachmentsListOpen.postValue(false) + isParticipantsListOpen.postValue(false) + isEmojiPickerOpen.postValue(false) + + // Warning: do not delete files + val attachmentsList = arrayListOf() + attachments.postValue(attachmentsList) + + chatMessageToReplyTo = null + } + } + + @UiThread + fun closeParticipantsList() { + isParticipantsListOpen.value = false + } + + @UiThread + fun closeFileAttachmentsList() { + viewModelScope.launch { + for (file in attachments.value.orEmpty()) { + file.deleteFile() + } + } + val list = arrayListOf() + attachments.value = list + + isFileAttachmentsListOpen.value = false + } + + @UiThread + fun addAttachment(file: String) { + val list = arrayListOf() + list.addAll(attachments.value.orEmpty()) + val model = FileModel(file) { file -> + removeAttachment(file) + } + list.add(model) + attachments.value = list + + if (list.isNotEmpty()) { + isFileAttachmentsListOpen.value = true + } + } + + @UiThread + fun removeAttachment(file: String, delete: Boolean = true) { + val list = arrayListOf() + list.addAll(attachments.value.orEmpty()) + val found = list.find { + it.file == file + } + if (found != null) { + if (delete) { + viewModelScope.launch { + found.deleteFile() + } + } + list.remove(found) + } else { + Log.w("$TAG Failed to find file attachment matching [$file]") + } + attachments.value = list + + if (list.isEmpty()) { + isFileAttachmentsListOpen.value = false + } + } + + @UiThread + fun startVoiceMessageRecording() { + voiceRecordingInProgress.value = true + } + + @UiThread + fun stopVoiceMessageRecording() { + } + + @UiThread + fun cancelVoiceMessageRecording() { + voiceRecordingInProgress.value = false + } + + @UiThread + fun playVoiceMessageRecording() { + } + + @UiThread + fun pauseVoiceMessageRecording() { + } + + @WorkerThread + private fun computeParticipantsList() { + val participantsList = arrayListOf() + + for (participant in chatRoom.participants) { + val model = ParticipantModel(participant.address, onClicked = { clicked -> + Log.i("$TAG Clicked on participant [${clicked.sipUri}]") + coreContext.postOnCoreThread { + val username = clicked.address.username + if (!username.isNullOrEmpty()) { + participantUsernameToAddEvent.postValue(Event(username)) + } + } + }) + participantsList.add(model) + } + + participants.postValue(participantsList) + } +} diff --git a/app/src/main/res/layout/chat_conversation_attachments_area.xml b/app/src/main/res/layout/chat_conversation_attachments_area.xml index a7bfce960..75898138a 100644 --- a/app/src/main/res/layout/chat_conversation_attachments_area.xml +++ b/app/src/main/res/layout/chat_conversation_attachments_area.xml @@ -6,7 +6,7 @@ + type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" /> + diff --git a/app/src/main/res/layout/chat_conversation_participants_area.xml b/app/src/main/res/layout/chat_conversation_participants_area.xml index f4f0a0c4e..9cb102031 100644 --- a/app/src/main/res/layout/chat_conversation_participants_area.xml +++ b/app/src/main/res/layout/chat_conversation_participants_area.xml @@ -6,7 +6,7 @@ + type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" /> + type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" /> + type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" /> + + + +