diff --git a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatRoomsListAdapter.kt b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatRoomsListAdapter.kt index 4b8e396a2..5c01c344f 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatRoomsListAdapter.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatRoomsListAdapter.kt @@ -33,12 +33,11 @@ import org.linphone.activities.main.viewmodels.ListTopBarViewModel import org.linphone.core.ChatRoom import org.linphone.databinding.ChatRoomListCellBinding import org.linphone.utils.Event -import org.linphone.utils.LinphoneUtils class ChatRoomsListAdapter( selectionVM: ListTopBarViewModel, private val viewLifecycleOwner: LifecycleOwner -) : SelectionListAdapter(selectionVM, ChatRoomDiffCallback()) { +) : SelectionListAdapter(selectionVM, ChatRoomDiffCallback()) { val selectedChatRoomEvent: MutableLiveData> by lazy { MutableLiveData>() } @@ -57,11 +56,6 @@ class ChatRoomsListAdapter( (holder as ViewHolder).bind(getItem(position)) } - override fun getItemId(position: Int): Long { - val room = getItem(position) - return LinphoneUtils.getChatRoomId(room).hashCode().toLong() - } - fun forwardPending(pending: Boolean) { isForwardPending = pending notifyItemRangeChanged(0, itemCount) @@ -70,9 +64,10 @@ class ChatRoomsListAdapter( inner class ViewHolder( private val binding: ChatRoomListCellBinding ) : RecyclerView.ViewHolder(binding.root) { - fun bind(chatRoom: ChatRoom) { + fun bind(chatRoomData: ChatRoomData) { with(binding) { - data = ChatRoomData(chatRoom) + chatRoomData.update() + data = chatRoomData lifecycleOwner = viewLifecycleOwner @@ -90,7 +85,7 @@ class ChatRoomsListAdapter( if (selectionViewModel.isEditionEnabled.value == true) { selectionViewModel.onToggleSelect(bindingAdapterPosition) } else { - selectedChatRoomEvent.value = Event(chatRoom) + selectedChatRoomEvent.value = Event(chatRoomData.chatRoom) } } @@ -109,17 +104,17 @@ class ChatRoomsListAdapter( } } -private class ChatRoomDiffCallback : DiffUtil.ItemCallback() { +private class ChatRoomDiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: ChatRoom, - newItem: ChatRoom + oldItem: ChatRoomData, + newItem: ChatRoomData ): Boolean { - return oldItem == newItem + return oldItem.id == newItem.id } override fun areContentsTheSame( - oldItem: ChatRoom, - newItem: ChatRoom + oldItem: ChatRoomData, + newItem: ChatRoomData ): Boolean { return false // To force redraw } diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/ChatRoomData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/ChatRoomData.kt index b9e2b01fb..85be29bf7 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/ChatRoomData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/ChatRoomData.kt @@ -31,13 +31,14 @@ import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.contact.ContactDataInterface +import org.linphone.contact.ContactsUpdatedListenerStub import org.linphone.core.* import org.linphone.core.tools.Log import org.linphone.utils.AppUtils import org.linphone.utils.LinphoneUtils import org.linphone.utils.TimestampUtils -class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface { +class ChatRoomData(val chatRoom: ChatRoom) : ContactDataInterface { override val contact: MutableLiveData = MutableLiveData() override val displayName: MutableLiveData = MutableLiveData() override val securityLevel: MutableLiveData = MutableLiveData() @@ -46,6 +47,8 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface { override val presenceStatus: MutableLiveData = MutableLiveData() override val coroutineScope: CoroutineScope = coreContext.coroutineScope + val id = LinphoneUtils.getChatRoomId(chatRoom) + val unreadMessagesCount = MutableLiveData() val subject = MutableLiveData() @@ -82,7 +85,26 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface { chatRoom.hasCapability(ChatRoomCapabilities.Encrypted.toInt()) } + private val contactsListener = object : ContactsUpdatedListenerStub() { + override fun onContactsUpdated() { + if (oneToOneChatRoom && contact.value == null) { + searchMatchingContact() + if (contact.value != null) { + formatLastMessage(chatRoom.lastMessageInHistory) + } + } + } + } + init { + coreContext.contactsManager.addListener(contactsListener) + } + + fun destroy() { + coreContext.contactsManager.removeListener(contactsListener) + } + + fun update() { unreadMessagesCount.value = chatRoom.unreadMessagesCount presenceStatus.value = ConsolidatedPresence.Offline @@ -96,6 +118,11 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface { notificationsMuted.value = areNotificationsMuted() } + fun markAsRead() { + chatRoom.markAsRead() + unreadMessagesCount.value = 0 + } + private fun updateSecurityIcon() { val level = chatRoom.securityLevel securityLevel.value = level @@ -133,8 +160,9 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface { val remoteAddress = if (basicChatRoom) { chatRoom.peerAddress } else { - if (chatRoom.participants.isNotEmpty()) { - chatRoom.participants[0].address + val participants = chatRoom.participants + if (participants.isNotEmpty()) { + participants.first().address } else { Log.e("[Chat Room] ${chatRoom.peerAddress} doesn't have any participant (state ${chatRoom.state})!") null diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt index b7d749e9e..c215500e7 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt @@ -156,7 +156,6 @@ class MasterChatRoomsFragment : MasterFragment= adapter.currentList.size) { Log.e("[Chat] Index is out of bound, can't mark chat room as read") } else { - val chatRoom = adapter.currentList[viewHolder.bindingAdapterPosition] - chatRoom.markAsRead() - adapter.notifyItemChanged(viewHolder.bindingAdapterPosition) + val data = adapter.currentList[viewHolder.bindingAdapterPosition] + data.markAsRead() } } @@ -209,7 +207,7 @@ class MasterChatRoomsFragment : MasterFragment() var closeSlidingPane = false for (index in indexesOfItemToDelete) { - val chatRoom = adapter.currentList[index] + val chatRoom = adapter.currentList[index].chatRoom list.add(chatRoom) if (chatRoom == sharedViewModel.selectedChatRoom.value) { diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomsListViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomsListViewModel.kt index d0953d0a5..664e4e125 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomsListViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatRoomsListViewModel.kt @@ -22,16 +22,16 @@ package org.linphone.activities.main.chat.viewmodels import androidx.lifecycle.MutableLiveData import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R +import org.linphone.activities.main.chat.data.ChatRoomData import org.linphone.activities.main.viewmodels.MessageNotifierViewModel import org.linphone.compatibility.Compatibility -import org.linphone.contact.ContactsUpdatedListenerStub import org.linphone.core.* import org.linphone.core.tools.Log import org.linphone.utils.Event import org.linphone.utils.LinphoneUtils class ChatRoomsListViewModel : MessageNotifierViewModel() { - val chatRooms = MutableLiveData>() + val chatRooms = MutableLiveData>() val fileSharingPending = MutableLiveData() @@ -45,10 +45,31 @@ class ChatRoomsListViewModel : MessageNotifierViewModel() { MutableLiveData>() } + private val chatRoomListener = object : ChatRoomListenerStub() { + override fun onStateChanged(chatRoom: ChatRoom, newState: ChatRoom.State) { + if (newState == ChatRoom.State.Deleted) { + Log.i("[Chat Rooms] Chat room [${LinphoneUtils.getChatRoomId(chatRoom)}] is in Deleted state, removing it from list") + val list = arrayListOf() + val id = LinphoneUtils.getChatRoomId(chatRoom) + for (data in chatRooms.value.orEmpty()) { + if (data.id != id) { + list.add(data) + } + } + chatRooms.value = list + } + } + } + private val listener: CoreListenerStub = object : CoreListenerStub() { override fun onChatRoomStateChanged(core: Core, chatRoom: ChatRoom, state: ChatRoom.State) { if (state == ChatRoom.State.Created) { - updateChatRooms() + Log.i("[Chat Rooms] Chat room [${LinphoneUtils.getChatRoomId(chatRoom)}] is in Created state, adding it to list") + val data = ChatRoomData(chatRoom) + val list = arrayListOf() + list.add(data) + list.addAll(chatRooms.value.orEmpty()) + chatRooms.value = list } else if (state == ChatRoom.State.TerminationFailed) { Log.e("[Chat Rooms] Group chat room removal for address ${chatRoom.peerAddress.asStringUriOnly()} has failed !") onMessageToNotifyEvent.value = Event(R.string.chat_room_removal_failed_snack) @@ -80,31 +101,15 @@ class ChatRoomsListViewModel : MessageNotifierViewModel() { } } - private val chatRoomListener = object : ChatRoomListenerStub() { - override fun onStateChanged(chatRoom: ChatRoom, newState: ChatRoom.State) { - if (newState == ChatRoom.State.Deleted) { - updateChatRooms() - } - } - } - - private val contactsListener = object : ContactsUpdatedListenerStub() { - override fun onContactsUpdated() { - updateChatRooms() - } - } - private var chatRoomsToDeleteCount = 0 init { groupChatAvailable.value = LinphoneUtils.isGroupChatAvailable() updateChatRooms() coreContext.core.addListener(listener) - coreContext.contactsManager.addListener(contactsListener) } override fun onCleared() { - coreContext.contactsManager.removeListener(contactsListener) coreContext.core.removeListener(listener) super.onCleared() @@ -139,8 +144,12 @@ class ChatRoomsListViewModel : MessageNotifierViewModel() { } fun updateChatRooms() { - val list = arrayListOf() - list.addAll(coreContext.core.chatRooms) + chatRooms.value.orEmpty().forEach(ChatRoomData::destroy) + + val list = arrayListOf() + for (chatRoom in coreContext.core.chatRooms) { + list.add(ChatRoomData(chatRoom)) + } chatRooms.value = list } @@ -151,15 +160,16 @@ class ChatRoomsListViewModel : MessageNotifierViewModel() { } private fun reorderChatRooms() { - val list = arrayListOf() + val list = arrayListOf() list.addAll(chatRooms.value.orEmpty()) - list.sortByDescending { chatRoom -> chatRoom.lastUpdateTime } + list.sortByDescending { data -> data.chatRoom.lastUpdateTime } chatRooms.value = list } private fun findChatRoomIndex(chatRoom: ChatRoom): Int { - for ((index, cr) in chatRooms.value.orEmpty().withIndex()) { - if (LinphoneUtils.areChatRoomsTheSame(cr, chatRoom)) { + val id = LinphoneUtils.getChatRoomId(chatRoom) + for ((index, data) in chatRooms.value.orEmpty().withIndex()) { + if (id == data.id) { return index } } diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt index a6a1b7244..88924b738 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt @@ -224,11 +224,6 @@ class LinphoneUtils { ) } - fun areChatRoomsTheSame(chatRoom1: ChatRoom, chatRoom2: ChatRoom): Boolean { - return chatRoom1.localAddress.weakEqual(chatRoom2.localAddress) && - chatRoom1.peerAddress.weakEqual(chatRoom2.peerAddress) - } - fun getChatRoomId(room: ChatRoom): String { return getChatRoomId(room.localAddress, room.peerAddress) }