mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-26 01:04:30 +00:00
tracking positions correctly on scroll
This commit is contained in:
+30
-9
@@ -23,7 +23,8 @@ data class ChatSectionAreaBoundary (
|
||||
data class ChatSection (
|
||||
val items: MutableList<SectionItems>,
|
||||
val area: ChatSectionArea,
|
||||
val boundary: ChatSectionAreaBoundary
|
||||
val boundary: ChatSectionAreaBoundary,
|
||||
val itemPositions: MutableMap<Long, Int>
|
||||
)
|
||||
|
||||
data class SectionItems (
|
||||
@@ -31,7 +32,6 @@ data class SectionItems (
|
||||
val items: MutableList<ChatItem>,
|
||||
val revealed: Boolean,
|
||||
val showAvatar: MutableSet<Long>,
|
||||
val itemPositions: MutableMap<Long, Int>
|
||||
)
|
||||
|
||||
data class ChatSectionLoad (
|
||||
@@ -104,8 +104,7 @@ fun List<ChatItem>.putIntoSections(revealedItems: Set<Long>): List<ChatSection>
|
||||
it.add(first.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
itemPositions = mutableMapOf(first.id to 0),
|
||||
}
|
||||
)
|
||||
} else {
|
||||
return emptyList()
|
||||
@@ -117,12 +116,14 @@ fun List<ChatItem>.putIntoSections(revealedItems: Set<Long>): List<ChatSection>
|
||||
ChatSection(
|
||||
items = mutableListOf(recent),
|
||||
area = area,
|
||||
boundary = ChatSectionAreaBoundary(minIndex = 0, maxIndex = 0, area = area)
|
||||
boundary = ChatSectionAreaBoundary(minIndex = 0, maxIndex = 0, area = area),
|
||||
itemPositions = mutableMapOf(recent.items[0].id to 0)
|
||||
)
|
||||
)
|
||||
|
||||
var prev = this[0]
|
||||
var index = 0
|
||||
var positionInList = 0;
|
||||
while (index < size) {
|
||||
if (index == 0) {
|
||||
index++
|
||||
@@ -133,6 +134,7 @@ fun List<ChatItem>.putIntoSections(revealedItems: Set<Long>): List<ChatSection>
|
||||
val existingSection = sections.find { it.area == itemArea }
|
||||
|
||||
if (existingSection == null) {
|
||||
positionInList++
|
||||
val newSection = SectionItems(
|
||||
mergeCategory = item.mergeCategory,
|
||||
items = mutableListOf<ChatItem>().also { it.add(item) },
|
||||
@@ -140,22 +142,30 @@ fun List<ChatItem>.putIntoSections(revealedItems: Set<Long>): List<ChatSection>
|
||||
showAvatar = mutableSetOf<Long>().also {
|
||||
it.add(item.id)
|
||||
},
|
||||
itemPositions = mutableMapOf(item.id to index),
|
||||
)
|
||||
sections.add(
|
||||
ChatSection(items = mutableListOf(newSection), area = itemArea, boundary = ChatSectionAreaBoundary(minIndex = index, maxIndex = index, area = itemArea))
|
||||
ChatSection(
|
||||
items = mutableListOf(newSection),
|
||||
area = itemArea,
|
||||
boundary = ChatSectionAreaBoundary(minIndex = index, maxIndex = index, area = itemArea),
|
||||
itemPositions = mutableMapOf(item.id to positionInList)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
recent = existingSection.items.last()
|
||||
val category = item.mergeCategory
|
||||
if (recent.mergeCategory == category) {
|
||||
if (category == null || recent.revealed || revealedItems.contains(item.id)) {
|
||||
positionInList++
|
||||
}
|
||||
if (item.chatDir is CIDirection.GroupRcv && prev.chatDir is CIDirection.GroupRcv && item.chatDir.groupMember.memberId != (prev.chatDir as CIDirection.GroupRcv).groupMember.memberId) {
|
||||
recent.showAvatar.add(item.id)
|
||||
}
|
||||
|
||||
recent.items.add(item)
|
||||
recent.itemPositions[item.id] = index
|
||||
existingSection.itemPositions[item.id] = positionInList
|
||||
} else {
|
||||
positionInList++
|
||||
val newSectionItems = SectionItems(
|
||||
mergeCategory = item.mergeCategory,
|
||||
items = mutableListOf<ChatItem>().also { it.add(item) },
|
||||
@@ -165,8 +175,8 @@ fun List<ChatItem>.putIntoSections(revealedItems: Set<Long>): List<ChatSection>
|
||||
it.add(item.id)
|
||||
}
|
||||
},
|
||||
itemPositions = mutableMapOf(item.id to index),
|
||||
)
|
||||
existingSection.itemPositions[item.id] = positionInList
|
||||
existingSection.items.add(newSectionItems)
|
||||
}
|
||||
existingSection.boundary.maxIndex = index
|
||||
@@ -178,6 +188,17 @@ fun List<ChatItem>.putIntoSections(revealedItems: Set<Long>): List<ChatSection>
|
||||
return sections
|
||||
}
|
||||
|
||||
fun List<ChatSection>.chatItemPosition(chatItemId: Long): Int? {
|
||||
for (section in this) {
|
||||
val position = section.itemPositions[chatItemId]
|
||||
if (position != null) {
|
||||
return position
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun List<ChatSection>.dropTemporarySections() {
|
||||
val bottomSection = this.find { it.area == ChatSectionArea.Bottom }
|
||||
if (bottomSection != null) {
|
||||
|
||||
+22
-17
@@ -1020,10 +1020,13 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
||||
.collect {
|
||||
revealedItems.value = setOf()
|
||||
preloadItemsEnabled.value = true
|
||||
val firstUnreadItemIndex = reversedChatItems.indexOfLast { it.isRcvNew }
|
||||
if (firstUnreadItemIndex != -1) {
|
||||
listState.scrollToItem(scrollPosition(firstUnreadItemIndex), -maxHeightRounded)
|
||||
val firstUnreadItem = chatModel.chatItems[firstUnreadItemIndex]
|
||||
val firstUnreadItem = reversedChatItems.findLast { it.isRcvNew }
|
||||
if (firstUnreadItem != null) {
|
||||
val firstUnreadItemIndexIdx = sections.find { it.area == ChatSectionArea.Current }?.itemPositions?.get(firstUnreadItem.id)
|
||||
if (firstUnreadItemIndexIdx != null) {
|
||||
listState.scrollToItem(scrollPosition(firstUnreadItemIndexIdx), -maxHeightRounded)
|
||||
}
|
||||
|
||||
if (chatModel.chatItemsSectionArea[firstUnreadItem.id] != ChatSectionArea.Bottom) {
|
||||
withBGApi {
|
||||
val chat = chatController.apiGetChat(rh = remoteHostId, type = chatInfo.chatType, id = chatInfo.apiId)
|
||||
@@ -1052,10 +1055,10 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
||||
}
|
||||
|
||||
val scrollToItem: (Long) -> Unit = { itemId: Long ->
|
||||
val index = reversedChatItems.indexOfFirst { it.id == itemId }
|
||||
val index = sections.chatItemPosition(itemId)
|
||||
preloadItemsEnabled.value = false
|
||||
|
||||
if (index != -1) {
|
||||
if (index != null) {
|
||||
scope.launch {
|
||||
listState.animateScrollToItem(scrollPosition(index), -maxHeightRounded)
|
||||
preloadItemsEnabled.value = true
|
||||
@@ -1072,18 +1075,20 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
||||
}
|
||||
val chatSectionLoad = ChatSectionLoad(0, ChatSectionArea.Destination)
|
||||
apiLoadMessagesAroundItem(rhId = remoteHostId, chatModel = chatModel, chatInfo = chatInfo, aroundItemId = itemId, chatSectionLoad = chatSectionLoad)
|
||||
val idx = reversedChatItems.indexOfFirst { it.id == itemId }
|
||||
|
||||
scope.launch {
|
||||
listState.animateScrollToItem(scrollPosition(idx), -maxHeightRounded)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!itemsToDrop.isNullOrEmpty()) {
|
||||
itemsToDrop.forEach {
|
||||
chatModel.chatItemsSectionArea.remove(it.id)
|
||||
val idx = sections.chatItemPosition(itemId)
|
||||
if (idx != null) {
|
||||
listState.animateScrollToItem(scrollPosition(idx), -maxHeightRounded)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!itemsToDrop.isNullOrEmpty()) {
|
||||
itemsToDrop.forEach {
|
||||
chatModel.chatItemsSectionArea.remove(it.id)
|
||||
}
|
||||
chatModel.chatItems.value.removeIf { chatModel.chatItemsSectionArea[it.id] == null }
|
||||
val newIdx = reversedChatItems.indexOfFirst { it.id == itemId }
|
||||
listState.scrollToItem(scrollPosition(newIdx), -maxHeightRounded)
|
||||
}
|
||||
chatModel.chatItems.value.removeIf { chatModel.chatItemsSectionArea[it.id] == null }
|
||||
val newIdx = reversedChatItems.indexOfFirst { it.id == itemId }
|
||||
listState.scrollToItem(scrollPosition(newIdx), -maxHeightRounded)
|
||||
}
|
||||
}
|
||||
preloadItemsEnabled.value = true
|
||||
@@ -1364,7 +1369,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
||||
// index here is just temporary, should be removed at all or put in the section items
|
||||
val prevItem = area.getPreviousShownItem(sIdx, i)
|
||||
val nextItem = area.getNextShownItem(sIdx, i)
|
||||
ChatViewListItem(section.itemPositions[cItem.id] ?: -1, section, cItem, prevItem, nextItem)
|
||||
ChatViewListItem(area.itemPositions[cItem.id] ?: -1, section, cItem, prevItem, nextItem)
|
||||
}
|
||||
} else {
|
||||
val item = section.items.first()
|
||||
@@ -1372,7 +1377,7 @@ fun BoxWithConstraintsScope.ChatItemsList(
|
||||
// here you make one collapsed item from multiple items (should be already in section items)
|
||||
val prevItem = area.getPreviousShownItem(sIdx, section.items.lastIndex)
|
||||
val nextItem = area.getNextShownItem(sIdx, section.items.lastIndex)
|
||||
ChatViewListItem(section.itemPositions[item.id] ?: -1, section, item, prevItem, nextItem)
|
||||
ChatViewListItem(area.itemPositions[item.id] ?: -1, section, item, prevItem, nextItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user