Fixed chat room scroll freeze + system overlay on some launchers + reduce multi contents in chat bubble size

This commit is contained in:
Sylvain Berfini 2021-06-07 00:13:52 +02:00
parent 153932ba54
commit 0415629299
6 changed files with 78 additions and 62 deletions

View file

@ -37,7 +37,7 @@ import org.linphone.utils.Event
class ChatRoomsListAdapter( class ChatRoomsListAdapter(
selectionVM: ListTopBarViewModel, selectionVM: ListTopBarViewModel,
private val viewLifecycleOwner: LifecycleOwner private val viewLifecycleOwner: LifecycleOwner
) : SelectionListAdapter<ChatRoom, RecyclerView.ViewHolder>(selectionVM, ChatRoomDiffCallback()) { ) : SelectionListAdapter<ChatRoomViewModel, RecyclerView.ViewHolder>(selectionVM, ChatRoomDiffCallback()) {
val selectedChatRoomEvent: MutableLiveData<Event<ChatRoom>> by lazy { val selectedChatRoomEvent: MutableLiveData<Event<ChatRoom>> by lazy {
MutableLiveData<Event<ChatRoom>>() MutableLiveData<Event<ChatRoom>>()
} }
@ -64,9 +64,8 @@ class ChatRoomsListAdapter(
inner class ViewHolder( inner class ViewHolder(
private val binding: ChatRoomListCellBinding private val binding: ChatRoomListCellBinding
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
fun bind(chatRoom: ChatRoom) { fun bind(chatRoomViewModel: ChatRoomViewModel) {
with(binding) { with(binding) {
val chatRoomViewModel = ChatRoomViewModel(chatRoom)
viewModel = chatRoomViewModel viewModel = chatRoomViewModel
lifecycleOwner = viewLifecycleOwner lifecycleOwner = viewLifecycleOwner
@ -83,8 +82,8 @@ class ChatRoomsListAdapter(
if (selectionViewModel.isEditionEnabled.value == true) { if (selectionViewModel.isEditionEnabled.value == true) {
selectionViewModel.onToggleSelect(adapterPosition) selectionViewModel.onToggleSelect(adapterPosition)
} else { } else {
selectedChatRoomEvent.value = Event(chatRoom) selectedChatRoomEvent.value = Event(chatRoomViewModel.chatRoom)
chatRoom.markAsRead() chatRoomViewModel.chatRoom.markAsRead()
} }
} }
@ -103,19 +102,18 @@ class ChatRoomsListAdapter(
} }
} }
private class ChatRoomDiffCallback : DiffUtil.ItemCallback<ChatRoom>() { private class ChatRoomDiffCallback : DiffUtil.ItemCallback<ChatRoomViewModel>() {
override fun areItemsTheSame( override fun areItemsTheSame(
oldItem: ChatRoom, oldItem: ChatRoomViewModel,
newItem: ChatRoom newItem: ChatRoomViewModel
): Boolean { ): Boolean {
return oldItem.localAddress.weakEqual(newItem.localAddress) && return oldItem.chatRoom == newItem.chatRoom
oldItem.peerAddress.weakEqual(newItem.peerAddress)
} }
override fun areContentsTheSame( override fun areContentsTheSame(
oldItem: ChatRoom, oldItem: ChatRoomViewModel,
newItem: ChatRoom newItem: ChatRoomViewModel
): Boolean { ): Boolean {
return newItem.unreadMessagesCount == 0 return newItem.unreadMessagesCount.value == 0
} }
} }

View file

@ -110,10 +110,10 @@ class MasterChatRoomsFragment : MasterFragment<ChatRoomMasterFragmentBinding, Ch
) )
val swipeListener = object : RecyclerViewSwipeListener { val swipeListener = object : RecyclerViewSwipeListener {
override fun onLeftToRightSwipe(viewHolder: RecyclerView.ViewHolder) { override fun onLeftToRightSwipe(viewHolder: RecyclerView.ViewHolder) {
val chatRoomViewModel = adapter.currentList[viewHolder.adapterPosition]
chatRoomViewModel.chatRoom.markAsRead()
coreContext.notificationsManager.dismissChatNotification(chatRoomViewModel.chatRoom)
adapter.notifyItemChanged(viewHolder.adapterPosition) adapter.notifyItemChanged(viewHolder.adapterPosition)
val chatRoom = adapter.currentList[viewHolder.adapterPosition]
chatRoom.markAsRead()
coreContext.notificationsManager.dismissChatNotification(chatRoom)
} }
override fun onRightToLeftSwipe(viewHolder: RecyclerView.ViewHolder) { override fun onRightToLeftSwipe(viewHolder: RecyclerView.ViewHolder) {
@ -126,7 +126,7 @@ class MasterChatRoomsFragment : MasterFragment<ChatRoomMasterFragmentBinding, Ch
} }
viewModel.showDeleteButton({ viewModel.showDeleteButton({
listViewModel.deleteChatRoom(adapter.currentList[viewHolder.adapterPosition]) listViewModel.deleteChatRoom(adapter.currentList[viewHolder.adapterPosition].chatRoom)
dialog.dismiss() dialog.dismiss()
}, getString(R.string.dialog_delete)) }, getString(R.string.dialog_delete))
@ -145,10 +145,6 @@ class MasterChatRoomsFragment : MasterFragment<ChatRoomMasterFragmentBinding, Ch
adapter.submitList(chatRooms) adapter.submitList(chatRooms)
}) })
listViewModel.latestUpdatedChatRoomId.observe(viewLifecycleOwner, { position ->
adapter.notifyItemChanged(position)
})
listViewModel.contactsUpdatedEvent.observe(viewLifecycleOwner, { listViewModel.contactsUpdatedEvent.observe(viewLifecycleOwner, {
it.consume { it.consume {
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
@ -268,8 +264,8 @@ class MasterChatRoomsFragment : MasterFragment<ChatRoomMasterFragmentBinding, Ch
override fun deleteItems(indexesOfItemToDelete: ArrayList<Int>) { override fun deleteItems(indexesOfItemToDelete: ArrayList<Int>) {
val list = ArrayList<ChatRoom>() val list = ArrayList<ChatRoom>()
for (index in indexesOfItemToDelete) { for (index in indexesOfItemToDelete) {
val chatRoom = adapter.currentList[index] val chatRoomViewModel = adapter.currentList[index]
list.add(chatRoom) list.add(chatRoomViewModel.chatRoom)
} }
listViewModel.deleteChatRooms(list) listViewModel.deleteChatRooms(list)
} }

View file

@ -130,6 +130,12 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
) { ) {
callInProgress.value = core.callsNb > 0 callInProgress.value = core.callsNb > 0
} }
override fun onChatRoomRead(core: Core, room: ChatRoom) {
if (room == chatRoom) {
unreadMessagesCount.value = 0
}
}
} }
private val chatRoomListener: ChatRoomListenerStub = object : ChatRoomListenerStub() { private val chatRoomListener: ChatRoomListenerStub = object : ChatRoomListenerStub() {
@ -216,11 +222,14 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
} }
override fun onCleared() { override fun onCleared() {
destroy()
super.onCleared()
}
fun destroy() {
coreContext.contactsManager.removeListener(contactsUpdatedListener) coreContext.contactsManager.removeListener(contactsUpdatedListener)
chatRoom.removeListener(chatRoomListener) chatRoom.removeListener(chatRoomListener)
chatRoom.core.removeListener(coreListener) chatRoom.core.removeListener(coreListener)
super.onCleared()
} }
fun contactLookup() { fun contactLookup() {

View file

@ -31,9 +31,7 @@ import org.linphone.utils.Event
import org.linphone.utils.LinphoneUtils import org.linphone.utils.LinphoneUtils
class ChatRoomsListViewModel : ErrorReportingViewModel() { class ChatRoomsListViewModel : ErrorReportingViewModel() {
val chatRooms = MutableLiveData<ArrayList<ChatRoom>>() val chatRooms = MutableLiveData<ArrayList<ChatRoomViewModel>>()
val latestUpdatedChatRoomId = MutableLiveData<Int>()
val contactsUpdatedEvent: MutableLiveData<Event<Boolean>> by lazy { val contactsUpdatedEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>() MutableLiveData<Event<Boolean>>()
@ -57,46 +55,33 @@ class ChatRoomsListViewModel : ErrorReportingViewModel() {
private val listener: CoreListenerStub = object : CoreListenerStub() { private val listener: CoreListenerStub = object : CoreListenerStub() {
override fun onChatRoomStateChanged(core: Core, chatRoom: ChatRoom, state: ChatRoom.State) { override fun onChatRoomStateChanged(core: Core, chatRoom: ChatRoom, state: ChatRoom.State) {
if (state == ChatRoom.State.Created) { if (state == ChatRoom.State.Created) {
updateChatRooms() addChatRoom(chatRoom)
} else if (state == ChatRoom.State.TerminationFailed) { } else if (state == ChatRoom.State.TerminationFailed) {
Log.e("[Chat Rooms] Group chat room removal for address ${chatRoom.peerAddress.asStringUriOnly()} has failed !") Log.e("[Chat Rooms] Group chat room removal for address ${chatRoom.peerAddress.asStringUriOnly()} has failed !")
onErrorEvent.value = Event(R.string.chat_room_removal_failed_snack) onErrorEvent.value = Event(R.string.chat_room_removal_failed_snack)
} }
} }
override fun onChatRoomSubjectChanged(core: Core, chatRoom: ChatRoom) {
updateChatRoom(chatRoom)
}
override fun onChatRoomRead(core: Core, chatRoom: ChatRoom) {
updateChatRoom(chatRoom)
}
override fun onMessageSent(core: Core, chatRoom: ChatRoom, message: ChatMessage) { override fun onMessageSent(core: Core, chatRoom: ChatRoom, message: ChatMessage) {
if (chatRooms.value?.indexOf(chatRoom) == 0) updateChatRoom(chatRoom) if (findChatRoomIndex(chatRoom) != 0) reorderChatRooms()
else updateChatRooms()
} }
override fun onMessageReceived(core: Core, chatRoom: ChatRoom, message: ChatMessage) { override fun onMessageReceived(core: Core, chatRoom: ChatRoom, message: ChatMessage) {
if (chatRooms.value?.indexOf(chatRoom) == 0) updateChatRoom(chatRoom) if (findChatRoomIndex(chatRoom) != 0) reorderChatRooms()
else updateChatRooms()
}
override fun onMessageReceivedUnableDecrypt(
core: Core,
chatRoom: ChatRoom,
message: ChatMessage
) {
updateChatRooms()
} }
} }
private val chatRoomListener = object : ChatRoomListenerStub() { private val chatRoomListener = object : ChatRoomListenerStub() {
override fun onStateChanged(chatRoom: ChatRoom, newState: ChatRoom.State) { override fun onStateChanged(chatRoom: ChatRoom, newState: ChatRoom.State) {
if (newState == ChatRoom.State.Deleted) { if (newState == ChatRoom.State.Deleted) {
val list = arrayListOf<ChatRoom>() val list = arrayListOf<ChatRoomViewModel>()
list.addAll(chatRooms.value.orEmpty()) for (chatRoomViewModel in chatRooms.value.orEmpty()) {
list.remove(chatRoom) if (chatRoomViewModel.chatRoom != chatRoom) {
list.add(chatRoomViewModel)
} else {
chatRoomViewModel.destroy()
}
}
chatRooms.value = list chatRooms.value = list
} }
} }
@ -145,15 +130,42 @@ class ChatRoomsListViewModel : ErrorReportingViewModel() {
} }
} }
private fun updateChatRoom(chatRoom: ChatRoom) {
latestUpdatedChatRoomId.value = chatRooms.value?.indexOf(chatRoom)
}
private fun updateChatRooms() { private fun updateChatRooms() {
val list = arrayListOf<ChatRoom>() for (chatRoomViewModel in chatRooms.value.orEmpty()) {
chatRoomViewModel.destroy()
list.addAll(coreContext.core.chatRooms) }
val list = arrayListOf<ChatRoomViewModel>()
for (chatRoom in coreContext.core.chatRooms) {
val viewModel = ChatRoomViewModel(chatRoom)
list.add(viewModel)
}
chatRooms.value = list chatRooms.value = list
} }
private fun addChatRoom(chatRoom: ChatRoom) {
val list = arrayListOf<ChatRoomViewModel>()
val viewModel = ChatRoomViewModel(chatRoom)
list.add(viewModel)
list.addAll(chatRooms.value.orEmpty())
chatRooms.value = list
}
private fun reorderChatRooms() {
val list = arrayListOf<ChatRoomViewModel>()
list.addAll(chatRooms.value.orEmpty())
list.sortByDescending { chatRoomViewModel -> chatRoomViewModel.chatRoom.lastUpdateTime }
chatRooms.value = list
}
private fun findChatRoomIndex(chatRoom: ChatRoom): Int {
var index = 0
for (chatRoomViewModel in chatRooms.value.orEmpty()) {
if (chatRoomViewModel.chatRoom == chatRoom) {
return index
}
index++
}
return -1
}
} }

View file

@ -552,9 +552,10 @@ class CoreContext(val context: Context, coreConfig: Config) {
if (overlayY == 0f) overlayY = AppUtils.pixelsToDp(40f) if (overlayY == 0f) overlayY = AppUtils.pixelsToDp(40f)
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
// WRAP_CONTENT doesn't work well on some launchers...
val params: WindowManager.LayoutParams = WindowManager.LayoutParams( val params: WindowManager.LayoutParams = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, AppUtils.getDimension(R.dimen.call_overlay_size).toInt(),
WindowManager.LayoutParams.WRAP_CONTENT, AppUtils.getDimension(R.dimen.call_overlay_size).toInt(),
Compatibility.getOverlayType(), Compatibility.getOverlayType(),
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT PixelFormat.TRANSLUCENT

View file

@ -7,7 +7,7 @@
<dimen name="outgoing_chat_message_bubble_right_margin">3dp</dimen> <dimen name="outgoing_chat_message_bubble_right_margin">3dp</dimen>
<dimen name="chat_message_bubble_image_height_big">200dp</dimen> <dimen name="chat_message_bubble_image_height_big">200dp</dimen>
<dimen name="chat_message_bubble_image_height_small">100dp</dimen> <dimen name="chat_message_bubble_image_height_small">100dp</dimen>
<dimen name="chat_message_bubble_file_size">150dp</dimen> <dimen name="chat_message_bubble_file_size">120dp</dimen>
<dimen name="chat_message_bubble_file_icon_size">30dp</dimen> <dimen name="chat_message_bubble_file_icon_size">30dp</dimen>
<dimen name="chat_message_bubble_desired_height">600dp</dimen> <dimen name="chat_message_bubble_desired_height">600dp</dimen>
<dimen name="video_preview_max_size">200dp</dimen> <dimen name="video_preview_max_size">200dp</dimen>