diff --git a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt index 4ba10d3cb..97463a99a 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt @@ -36,6 +36,7 @@ import org.linphone.R import org.linphone.activities.main.adapters.SelectionListAdapter import org.linphone.activities.main.chat.data.ChatMessageData import org.linphone.activities.main.chat.data.EventData +import org.linphone.activities.main.chat.data.EventLogData import org.linphone.activities.main.chat.data.OnContentClickedListener import org.linphone.activities.main.viewmodels.ListTopBarViewModel import org.linphone.core.ChatMessage @@ -51,7 +52,7 @@ import org.linphone.utils.Event class ChatMessagesListAdapter( selectionVM: ListTopBarViewModel, private val viewLifecycleOwner: LifecycleOwner -) : SelectionListAdapter(selectionVM, ChatMessageDiffCallback()) { +) : SelectionListAdapter(selectionVM, ChatMessageDiffCallback()) { companion object { const val MAX_TIME_TO_GROUP_MESSAGES = 60 // 1 minute } @@ -127,7 +128,7 @@ class ChatMessagesListAdapter( override fun getItemViewType(position: Int): Int { val eventLog = getItem(position) - return eventLog.type.toInt() + return eventLog.eventLog.type.toInt() } fun disableContextMenu() { @@ -137,12 +138,13 @@ class ChatMessagesListAdapter( inner class ChatMessageViewHolder( val binding: ChatMessageListCellBinding ) : RecyclerView.ViewHolder(binding.root) { - fun bind(eventLog: EventLog) { + fun bind(eventLog: EventLogData) { with(binding) { - if (eventLog.type == EventLog.Type.ConferenceChatMessage) { - val chatMessage = eventLog.chatMessage - chatMessage ?: return - val chatMessageViewModel = ChatMessageData(chatMessage, contentClickedListener) + if (eventLog.eventLog.type == EventLog.Type.ConferenceChatMessage) { + val chatMessageViewModel = eventLog.data as ChatMessageData + chatMessageViewModel.setContentClickListener(contentClickedListener) + + val chatMessage = chatMessageViewModel.chatMessage data = chatMessageViewModel lifecycleOwner = viewLifecycleOwner @@ -165,8 +167,8 @@ class ChatMessagesListAdapter( if (adapterPosition > 0) { val previousItem = getItem(adapterPosition - 1) - if (previousItem.type == EventLog.Type.ConferenceChatMessage) { - val previousMessage = previousItem.chatMessage + if (previousItem.eventLog.type == EventLog.Type.ConferenceChatMessage) { + val previousMessage = previousItem.eventLog.chatMessage if (previousMessage != null && previousMessage.fromAddress.weakEqual(chatMessage.fromAddress)) { if (chatMessage.time - previousMessage.time < MAX_TIME_TO_GROUP_MESSAGES) { hasPrevious = true @@ -177,8 +179,8 @@ class ChatMessagesListAdapter( if (adapterPosition >= 0 && adapterPosition < itemCount - 1) { val nextItem = getItem(adapterPosition + 1) - if (nextItem.type == EventLog.Type.ConferenceChatMessage) { - val nextMessage = nextItem.chatMessage + if (nextItem.eventLog.type == EventLog.Type.ConferenceChatMessage) { + val nextMessage = nextItem.eventLog.chatMessage if (nextMessage != null && nextMessage.fromAddress.weakEqual(chatMessage.fromAddress)) { if (nextMessage.time - chatMessage.time < MAX_TIME_TO_GROUP_MESSAGES) { hasNext = true @@ -319,9 +321,9 @@ class ChatMessagesListAdapter( inner class EventViewHolder( private val binding: ChatEventListCellBinding ) : RecyclerView.ViewHolder(binding.root) { - fun bind(eventLog: EventLog) { + fun bind(eventLog: EventLogData) { with(binding) { - val eventViewModel = EventData(eventLog) + val eventViewModel = eventLog.data as EventData data = eventViewModel binding.lifecycleOwner = viewLifecycleOwner @@ -344,24 +346,24 @@ class ChatMessagesListAdapter( } } -private class ChatMessageDiffCallback : DiffUtil.ItemCallback() { +private class ChatMessageDiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: EventLog, - newItem: EventLog + oldItem: EventLogData, + newItem: EventLogData ): Boolean { - return if (oldItem.type == EventLog.Type.ConferenceChatMessage && - newItem.type == EventLog.Type.ConferenceChatMessage) { - oldItem.chatMessage?.time == newItem.chatMessage?.time && - oldItem.chatMessage?.isOutgoing == newItem.chatMessage?.isOutgoing - } else oldItem.notifyId == newItem.notifyId + return if (oldItem.eventLog.type == EventLog.Type.ConferenceChatMessage && + newItem.eventLog.type == EventLog.Type.ConferenceChatMessage) { + oldItem.eventLog.chatMessage?.time == newItem.eventLog.chatMessage?.time && + oldItem.eventLog.chatMessage?.isOutgoing == newItem.eventLog.chatMessage?.isOutgoing + } else oldItem.eventLog.notifyId == newItem.eventLog.notifyId } override fun areContentsTheSame( - oldItem: EventLog, - newItem: EventLog + oldItem: EventLogData, + newItem: EventLogData ): Boolean { - return if (newItem.type == EventLog.Type.ConferenceChatMessage) { - newItem.chatMessage?.state == ChatMessage.State.Displayed - } else false + return if (newItem.eventLog.type == EventLog.Type.ConferenceChatMessage) { + newItem.eventLog.chatMessage?.state == ChatMessage.State.Displayed + } else true } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt index 1be23adc1..dfd67996a 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt @@ -39,8 +39,10 @@ import org.linphone.utils.ImageUtils class ChatMessageContentData( private val chatMessage: ChatMessage, private val contentIndex: Int, - private val listener: OnContentClickedListener? + ) { + var listener: OnContentClickedListener? = null + val isImage = MutableLiveData() val isVideo = MutableLiveData() val isAudio = MutableLiveData() diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt index b73b4ef4b..cfd7c51a9 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt @@ -31,10 +31,9 @@ import org.linphone.core.ChatMessageListenerStub import org.linphone.utils.AppUtils import org.linphone.utils.TimestampUtils -class ChatMessageData( - val chatMessage: ChatMessage, +class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMessage.fromAddress) { private var contentListener: OnContentClickedListener? = null -) : GenericContactData(chatMessage.fromAddress) { + val sendInProgress = MutableLiveData() val transferInProgress = MutableLiveData() @@ -120,6 +119,14 @@ class ChatMessageData( } } + fun setContentClickListener(listener: OnContentClickedListener) { + contentListener = listener + + for (data in contents.value.orEmpty()) { + data.listener = listener + } + } + private fun updateChatMessageState(state: ChatMessage.State) { transferInProgress.value = state == ChatMessage.State.FileTransferInProgress @@ -145,7 +152,9 @@ class ChatMessageData( for (index in 0 until contentsList.size) { val content = contentsList[index] if (content.isFileTransfer || content.isFile) { - list.add(ChatMessageContentData(chatMessage, index, contentListener)) + val data = ChatMessageContentData(chatMessage, index) + data.listener = contentListener + list.add(data) } else if (content.isText) { val spannable = Spannable.Factory.getInstance().newSpannable(content.utf8Text) LinkifyCompat.addLinks(spannable, Linkify.WEB_URLS) diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/EventData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/EventData.kt index d87e0bbf1..eb0f51f10 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/EventData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/EventData.kt @@ -23,12 +23,19 @@ import android.content.Context import androidx.lifecycle.MutableLiveData import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R -import org.linphone.contact.Contact +import org.linphone.contact.GenericContactData import org.linphone.core.EventLog -import org.linphone.core.tools.Log -import org.linphone.utils.LinphoneUtils -class EventData(private val eventLog: EventLog) { +class EventData(private val eventLog: EventLog) : GenericContactData( + if (eventLog.type == EventLog.Type.ConferenceSecurityEvent) { + eventLog.securityEventFaultyDeviceAddress!! + } else { + if (eventLog.participantAddress == null) { + eventLog.peerAddress!! + } else { + eventLog.participantAddress!! + } + }) { val text = MutableLiveData() val isSecurity: Boolean by lazy { @@ -38,32 +45,12 @@ class EventData(private val eventLog: EventLog) { } } - private val contact: Contact? by lazy { - val address = eventLog.participantAddress ?: eventLog.securityEventFaultyDeviceAddress - if (address != null) { - coreContext.contactsManager.findContactByAddress(address) - } else { - Log.e("[Event ViewModel] Unexpected null address for event $eventLog") - null - } - } - - private val displayName: String by lazy { - val address = eventLog.participantAddress ?: eventLog.securityEventFaultyDeviceAddress - if (address != null) { - LinphoneUtils.getDisplayName(address) - } else { - Log.e("[Event ViewModel] Unexpected null address for event $eventLog") - "" - } - } - init { updateEventText() } private fun getName(): String { - return contact?.fullName ?: displayName + return contact.value?.fullName ?: displayName } private fun updateEventText() { diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/EventLogData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/EventLogData.kt new file mode 100644 index 000000000..be217ad5a --- /dev/null +++ b/app/src/main/java/org/linphone/activities/main/chat/data/EventLogData.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2021 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.activities.main.chat.data + +import org.linphone.contact.GenericContactData +import org.linphone.core.EventLog + +class EventLogData(val eventLog: EventLog) { + val data: GenericContactData = if (eventLog.type == EventLog.Type.ConferenceChatMessage) { + ChatMessageData(eventLog.chatMessage!!) + } else { + EventData(eventLog) + } +} diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt index 37c0a677c..8aee469d5 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt @@ -47,6 +47,7 @@ import org.linphone.activities.* import org.linphone.activities.main.MainActivity import org.linphone.activities.main.chat.ChatScrollListener import org.linphone.activities.main.chat.adapters.ChatMessagesListAdapter +import org.linphone.activities.main.chat.data.EventLogData import org.linphone.activities.main.chat.viewmodels.* import org.linphone.activities.main.fragments.MasterFragment import org.linphone.activities.main.viewmodels.DialogViewModel @@ -345,7 +346,7 @@ class DetailChatRoomFragment : MasterFragment) { - val list = ArrayList() + val list = ArrayList() for (index in indexesOfItemToDelete) { val eventLog = adapter.currentList[index] list.add(eventLog) diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt index bb25d2069..06d9538ef 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessagesListViewModel.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import java.util.* import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.activities.main.chat.data.EventLogData import org.linphone.core.* import org.linphone.core.tools.Log import org.linphone.mediastream.Version @@ -45,7 +46,7 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() { private const val MESSAGES_PER_PAGE = 20 } - val events = MutableLiveData>() + val events = MutableLiveData>() val messageUpdatedEvent: MutableLiveData> by lazy { MutableLiveData>() @@ -67,8 +68,8 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() { chatMessage ?: return chatMessage.userData = events.value.orEmpty().size - val existingEvent = events.value.orEmpty().find { - it.type == EventLog.Type.ConferenceChatMessage && it.chatMessage == chatMessage + val existingEvent = events.value.orEmpty().find { data -> + data.eventLog == eventLog } if (existingEvent != null) { Log.w("[Chat Messages] Found already present chat message, don't add it it's probably the result of an auto download") @@ -165,19 +166,19 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() { LinphoneUtils.deleteFilesAttachedToChatMessage(chatMessage) chatRoom.deleteMessage(chatMessage) - val list = arrayListOf() + val list = arrayListOf() list.addAll(events.value.orEmpty()) list.removeAt(position) events.value = list } - fun deleteEventLogs(listToDelete: ArrayList) { - val list = arrayListOf() + fun deleteEventLogs(listToDelete: ArrayList) { + val list = arrayListOf() list.addAll(events.value.orEmpty()) for (eventLog in listToDelete) { - LinphoneUtils.deleteFilesAttachedToEventLog(eventLog) - eventLog.deleteFromDatabase() + LinphoneUtils.deleteFilesAttachedToEventLog(eventLog.eventLog) + eventLog.eventLog.deleteFromDatabase() list.remove(eventLog) } @@ -195,9 +196,9 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() { } val history: Array = chatRoom.getHistoryRangeEvents(totalItemsCount, upperBound) - val list = arrayListOf() - for (message in history) { - list.add(message) + val list = arrayListOf() + for (eventLog in history) { + list.add(EventLogData(eventLog)) } list.addAll(events.value.orEmpty()) events.value = list @@ -205,19 +206,19 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() { } private fun addEvent(eventLog: EventLog) { - val list = arrayListOf() + val list = arrayListOf() list.addAll(events.value.orEmpty()) if (!list.contains(eventLog)) { - list.add(eventLog) + list.add(EventLogData(eventLog)) } events.value = list } - private fun getEvents(): ArrayList { - val list = arrayListOf() + private fun getEvents(): ArrayList { + val list = arrayListOf() val history = chatRoom.getHistoryEvents(MESSAGES_PER_PAGE) - for (message in history) { - list.add(message) + for (eventLog in history) { + list.add(EventLogData(eventLog)) } return list }