mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Scroll to first unread message in conversation upon entering it
This commit is contained in:
parent
006fa3fa4a
commit
ddc8ba7105
3 changed files with 58 additions and 4 deletions
|
|
@ -28,6 +28,7 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.ChatBubbleIncomingBinding
|
||||
import org.linphone.databinding.ChatBubbleOutgoingBinding
|
||||
import org.linphone.databinding.ChatConversationEventBinding
|
||||
|
|
@ -41,6 +42,8 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
|
|||
EventLogDiffCallback()
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "[Conversation Event Adapter]"
|
||||
|
||||
const val INCOMING_CHAT_MESSAGE = 1
|
||||
const val OUTGOING_CHAT_MESSAGE = 2
|
||||
const val EVENT = 3
|
||||
|
|
@ -76,6 +79,21 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
|
|||
return INCOMING_CHAT_MESSAGE
|
||||
}
|
||||
|
||||
fun getFirstUnreadMessagePosition(): Int {
|
||||
var index = 0
|
||||
for (eventLog in currentList) {
|
||||
if (eventLog.model is MessageModel) {
|
||||
if (!eventLog.model.isRead) {
|
||||
Log.i("$TAG First unread message is [${eventLog.model.id}] at index [$index]")
|
||||
return index
|
||||
}
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
Log.i("$TAG No unread message found in list of [${currentList.size}] events")
|
||||
return -1
|
||||
}
|
||||
|
||||
private fun createIncomingChatBubble(parent: ViewGroup): IncomingBubbleViewHolder {
|
||||
val binding: ChatBubbleIncomingBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
|
|
|
|||
|
|
@ -127,11 +127,15 @@ class ConversationFragment : GenericFragment() {
|
|||
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")
|
||||
binding.eventsList.scrollToPosition(adapter.itemCount - 1)
|
||||
Log.i(
|
||||
"$TAG [$itemCount] events have been loaded, scrolling to first unread message"
|
||||
)
|
||||
scrollToFirstUnreadMessageOrBottom(false)
|
||||
} else {
|
||||
Log.i("$TAG [$itemCount] new events have been loaded, scrolling to bottom")
|
||||
binding.eventsList.smoothScrollToPosition(adapter.itemCount - 1)
|
||||
Log.i(
|
||||
"$TAG [$itemCount] new events have been loaded, scrolling to first unread message"
|
||||
)
|
||||
scrollToFirstUnreadMessageOrBottom(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -565,6 +569,36 @@ class ConversationFragment : GenericFragment() {
|
|||
super.onPause()
|
||||
}
|
||||
|
||||
private fun scrollToFirstUnreadMessageOrBottom(smooth: Boolean): Boolean {
|
||||
if (adapter.itemCount > 0) {
|
||||
val recyclerView = binding.eventsList
|
||||
|
||||
// Scroll to first unread message if any, unless we are already on it
|
||||
val firstUnreadMessagePosition = adapter.getFirstUnreadMessagePosition()
|
||||
val currentPosition = (recyclerView.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()
|
||||
val indexToScrollTo = if (firstUnreadMessagePosition != -1 && firstUnreadMessagePosition != currentPosition) {
|
||||
firstUnreadMessagePosition
|
||||
} else {
|
||||
adapter.itemCount - 1
|
||||
}
|
||||
|
||||
Log.i(
|
||||
"$TAG Scrolling to position $indexToScrollTo, first unread message is at $firstUnreadMessagePosition"
|
||||
)
|
||||
if (smooth) {
|
||||
recyclerView.smoothScrollToPosition(indexToScrollTo)
|
||||
} else {
|
||||
recyclerView.scrollToPosition(indexToScrollTo)
|
||||
}
|
||||
|
||||
if (firstUnreadMessagePosition == 0) {
|
||||
// Return true only if all unread messages don't fit in the recyclerview height
|
||||
return recyclerView.computeVerticalScrollRange() > recyclerView.height
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun showChatMessageLongPressMenu(chatMessageModel: MessageModel) {
|
||||
Compatibility.setBlurRenderEffect(binding.root)
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ class MessageModel @WorkerThread constructor(
|
|||
|
||||
val id = chatMessage.messageId
|
||||
|
||||
val isRead = chatMessage.isRead
|
||||
|
||||
val isOutgoing = chatMessage.isOutgoing
|
||||
|
||||
val isInError = chatMessage.state == ChatMessage.State.NotDelivered
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue