mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Re-order conversations list when needed + scroll to bottom when a new message is sent or received in a conversation
This commit is contained in:
parent
8cbe832a67
commit
1c7fe3fd3e
6 changed files with 100 additions and 19 deletions
|
|
@ -43,6 +43,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
|
|
@ -99,6 +100,18 @@ class ConversationFragment : GenericFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private val dataObserver = object : AdapterDataObserver() {
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0 && adapter.itemCount == itemCount) {
|
||||
// First time we fill the list with messages
|
||||
Log.i("$TAG [$itemCount] events have been loaded")
|
||||
} else {
|
||||
Log.i("$TAG [$itemCount] new events have been loaded, scrolling to bottom")
|
||||
binding.eventsList.smoothScrollToPosition(adapter.itemCount - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
|
|
@ -302,9 +315,20 @@ class ConversationFragment : GenericFragment() {
|
|||
if (viewModel.scrollingPosition != SCROLLING_POSITION_NOT_SET) {
|
||||
binding.eventsList.scrollToPosition(viewModel.scrollingPosition)
|
||||
}
|
||||
|
||||
try {
|
||||
adapter.registerAdapterDataObserver(dataObserver)
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.e("$TAG Failed to register data observer to adapter: $e")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
try {
|
||||
adapter.unregisterAdapterDataObserver(dataObserver)
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.e("$TAG Failed to unregister data observer to adapter: $e")
|
||||
}
|
||||
coreContext.notificationsManager.resetCurrentlyDisplayedChatRoomId()
|
||||
|
||||
val layoutManager = binding.eventsList.layoutManager as LinearLayoutManager
|
||||
|
|
|
|||
|
|
@ -129,6 +129,13 @@ class ConversationsListFragment : AbstractTopBarFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
listViewModel.chatRoomsReOrderedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
Log.i("$TAG Conversations list have been re-ordered, scrolling to top")
|
||||
binding.conversationsList.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
|
||||
// TopBarFragment related
|
||||
|
||||
setViewModelAndTitle(
|
||||
|
|
|
|||
|
|
@ -92,17 +92,24 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) {
|
|||
@WorkerThread
|
||||
override fun onMessagesReceived(chatRoom: ChatRoom, chatMessages: Array<out ChatMessage>) {
|
||||
updateLastMessage()
|
||||
updateLastUpdatedTime()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onChatMessageSending(chatRoom: ChatRoom, eventLog: EventLog) {
|
||||
updateLastMessage()
|
||||
updateLastUpdatedTime()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onChatRoomRead(chatRoom: ChatRoom) {
|
||||
unreadMessageCount.postValue(chatRoom.unreadMessagesCount)
|
||||
}
|
||||
|
||||
override fun onSubjectChanged(chatRoom: ChatRoom, eventLog: EventLog) {
|
||||
subject.postValue(chatRoom.subject)
|
||||
updateLastUpdatedTime()
|
||||
}
|
||||
}
|
||||
|
||||
private val chatMessageListener = object : ChatMessageListenerStub() {
|
||||
|
|
@ -159,7 +166,6 @@ class ConversationModel @WorkerThread constructor(val chatRoom: ChatRoom) {
|
|||
isEphemeral.postValue(chatRoom.isEphemeralEnabled)
|
||||
|
||||
updateLastMessage()
|
||||
|
||||
updateLastUpdatedTime()
|
||||
|
||||
unreadMessageCount.postValue(chatRoom.unreadMessagesCount)
|
||||
|
|
|
|||
|
|
@ -135,17 +135,23 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() {
|
|||
return@postOnCoreThread
|
||||
}
|
||||
|
||||
if (room != null && (!::chatRoom.isInitialized || chatRoom != room)) {
|
||||
Log.i("$TAG Chat room object available in sharedViewModel, using it")
|
||||
chatRoom = room
|
||||
chatRoom.addListener(chatRoomListener)
|
||||
configureChatRoom()
|
||||
chatRoomFoundEvent.postValue(Event(true))
|
||||
return@postOnCoreThread
|
||||
}
|
||||
|
||||
val localAddress = Factory.instance().createAddress(localSipUri)
|
||||
val remoteAddress = Factory.instance().createAddress(remoteSipUri)
|
||||
|
||||
if (room != null && (!::chatRoom.isInitialized || chatRoom != room)) {
|
||||
if (localAddress?.weakEqual(room.localAddress) == true && remoteAddress?.weakEqual(
|
||||
room.peerAddress
|
||||
) == true
|
||||
) {
|
||||
Log.i("$TAG Chat room object available in sharedViewModel, using it")
|
||||
chatRoom = room
|
||||
chatRoom.addListener(chatRoomListener)
|
||||
configureChatRoom()
|
||||
chatRoomFoundEvent.postValue(Event(true))
|
||||
return@postOnCoreThread
|
||||
}
|
||||
}
|
||||
|
||||
if (localAddress != null && remoteAddress != null) {
|
||||
Log.i("$TAG Searching for chat room in Core using local & peer SIP addresses")
|
||||
val found = core.searchChatRoom(
|
||||
|
|
|
|||
|
|
@ -222,17 +222,23 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
|
|||
return@postOnCoreThread
|
||||
}
|
||||
|
||||
if (room != null && (!::chatRoom.isInitialized || chatRoom != room)) {
|
||||
Log.i("$TAG Chat room object available in sharedViewModel, using it")
|
||||
chatRoom = room
|
||||
chatRoom.addListener(chatRoomListener)
|
||||
configureChatRoom()
|
||||
chatRoomFoundEvent.postValue(Event(true))
|
||||
return@postOnCoreThread
|
||||
}
|
||||
|
||||
val localAddress = Factory.instance().createAddress(localSipUri)
|
||||
val remoteAddress = Factory.instance().createAddress(remoteSipUri)
|
||||
|
||||
if (room != null && (!::chatRoom.isInitialized || chatRoom != room)) {
|
||||
if (localAddress?.weakEqual(room.localAddress) == true && remoteAddress?.weakEqual(
|
||||
room.peerAddress
|
||||
) == true
|
||||
) {
|
||||
Log.i("$TAG Chat room object available in sharedViewModel, using it")
|
||||
chatRoom = room
|
||||
chatRoom.addListener(chatRoomListener)
|
||||
configureChatRoom()
|
||||
chatRoomFoundEvent.postValue(Event(true))
|
||||
return@postOnCoreThread
|
||||
}
|
||||
}
|
||||
|
||||
if (localAddress != null && remoteAddress != null) {
|
||||
Log.i("$TAG Searching for chat room in Core using local & peer SIP addresses")
|
||||
val found = core.searchChatRoom(
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import androidx.annotation.WorkerThread
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.contacts.ContactsManager
|
||||
import org.linphone.core.ChatMessage
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.ChatRoom.Capabilities
|
||||
import org.linphone.core.Core
|
||||
|
|
@ -32,6 +33,7 @@ import org.linphone.core.tools.Log
|
|||
import org.linphone.ui.main.chat.model.ConversationModel
|
||||
import org.linphone.ui.main.model.isInSecureMode
|
||||
import org.linphone.ui.main.viewmodel.AbstractTopBarViewModel
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
class ConversationsListViewModel @UiThread constructor() : AbstractTopBarViewModel() {
|
||||
|
|
@ -43,6 +45,10 @@ class ConversationsListViewModel @UiThread constructor() : AbstractTopBarViewMod
|
|||
|
||||
val fetchInProgress = MutableLiveData<Boolean>()
|
||||
|
||||
val chatRoomsReOrderedEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onChatRoomStateChanged(
|
||||
|
|
@ -61,6 +67,20 @@ class ConversationsListViewModel @UiThread constructor() : AbstractTopBarViewMod
|
|||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onMessageSent(core: Core, chatRoom: ChatRoom, message: ChatMessage) {
|
||||
reorderChatRooms()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onMessagesReceived(
|
||||
core: Core,
|
||||
chatRoom: ChatRoom,
|
||||
messages: Array<out ChatMessage>
|
||||
) {
|
||||
reorderChatRooms()
|
||||
}
|
||||
}
|
||||
|
||||
private val contactsListener = object : ContactsManager.ContactsListener {
|
||||
|
|
@ -145,4 +165,16 @@ class ConversationsListViewModel @UiThread constructor() : AbstractTopBarViewMod
|
|||
conversations.postValue(list)
|
||||
fetchInProgress.postValue(false)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun reorderChatRooms() {
|
||||
Log.i("$TAG Re-ordering chat rooms")
|
||||
val sortedList = arrayListOf<ConversationModel>()
|
||||
sortedList.addAll(conversations.value.orEmpty())
|
||||
sortedList.sortBy {
|
||||
it.lastUpdateTime.value
|
||||
}
|
||||
conversations.postValue(sortedList)
|
||||
chatRoomsReOrderedEvent.postValue(Event(true))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue