mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-30 18:56:23 +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.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.ChatBubbleIncomingBinding
|
import org.linphone.databinding.ChatBubbleIncomingBinding
|
||||||
import org.linphone.databinding.ChatBubbleOutgoingBinding
|
import org.linphone.databinding.ChatBubbleOutgoingBinding
|
||||||
import org.linphone.databinding.ChatConversationEventBinding
|
import org.linphone.databinding.ChatConversationEventBinding
|
||||||
|
|
@ -41,6 +42,8 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
|
||||||
EventLogDiffCallback()
|
EventLogDiffCallback()
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val TAG = "[Conversation Event Adapter]"
|
||||||
|
|
||||||
const val INCOMING_CHAT_MESSAGE = 1
|
const val INCOMING_CHAT_MESSAGE = 1
|
||||||
const val OUTGOING_CHAT_MESSAGE = 2
|
const val OUTGOING_CHAT_MESSAGE = 2
|
||||||
const val EVENT = 3
|
const val EVENT = 3
|
||||||
|
|
@ -76,6 +79,21 @@ class ConversationEventAdapter : ListAdapter<EventLogModel, RecyclerView.ViewHol
|
||||||
return INCOMING_CHAT_MESSAGE
|
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 {
|
private fun createIncomingChatBubble(parent: ViewGroup): IncomingBubbleViewHolder {
|
||||||
val binding: ChatBubbleIncomingBinding = DataBindingUtil.inflate(
|
val binding: ChatBubbleIncomingBinding = DataBindingUtil.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
|
|
|
||||||
|
|
@ -127,11 +127,15 @@ class ConversationFragment : GenericFragment() {
|
||||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||||
if (positionStart == 0 && adapter.itemCount == itemCount) {
|
if (positionStart == 0 && adapter.itemCount == itemCount) {
|
||||||
// First time we fill the list with messages
|
// First time we fill the list with messages
|
||||||
Log.i("$TAG [$itemCount] events have been loaded")
|
Log.i(
|
||||||
binding.eventsList.scrollToPosition(adapter.itemCount - 1)
|
"$TAG [$itemCount] events have been loaded, scrolling to first unread message"
|
||||||
|
)
|
||||||
|
scrollToFirstUnreadMessageOrBottom(false)
|
||||||
} else {
|
} else {
|
||||||
Log.i("$TAG [$itemCount] new events have been loaded, scrolling to bottom")
|
Log.i(
|
||||||
binding.eventsList.smoothScrollToPosition(adapter.itemCount - 1)
|
"$TAG [$itemCount] new events have been loaded, scrolling to first unread message"
|
||||||
|
)
|
||||||
|
scrollToFirstUnreadMessageOrBottom(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -565,6 +569,36 @@ class ConversationFragment : GenericFragment() {
|
||||||
super.onPause()
|
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) {
|
private fun showChatMessageLongPressMenu(chatMessageModel: MessageModel) {
|
||||||
Compatibility.setBlurRenderEffect(binding.root)
|
Compatibility.setBlurRenderEffect(binding.root)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ class MessageModel @WorkerThread constructor(
|
||||||
|
|
||||||
val id = chatMessage.messageId
|
val id = chatMessage.messageId
|
||||||
|
|
||||||
|
val isRead = chatMessage.isRead
|
||||||
|
|
||||||
val isOutgoing = chatMessage.isOutgoing
|
val isOutgoing = chatMessage.isOutgoing
|
||||||
|
|
||||||
val isInError = chatMessage.state == ChatMessage.State.NotDelivered
|
val isInError = chatMessage.state == ChatMessage.State.NotDelivered
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue