mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-16 01:56:02 +00:00
changes
This commit is contained in:
@@ -21,6 +21,7 @@ struct MergedItems {
|
||||
return MergedItems(items: [], splits: [], indexInParentItems: [:], snapshot: NSDiffableDataSourceSnapshot())
|
||||
}
|
||||
|
||||
logger.debug("LALAL STEP 0")
|
||||
let unreadAfterItemId = chatState.unreadAfterItemId
|
||||
let itemSplits = chatState.splits
|
||||
var mergedItems: [MergedItem] = []
|
||||
@@ -108,6 +109,7 @@ struct MergedItems {
|
||||
indexInParentItems[item.id] = visibleItemIndexInParent
|
||||
index += 1
|
||||
}
|
||||
logger.debug("LALAL STEP 7")
|
||||
var snapshot = NSDiffableDataSourceSnapshot<ReverseListSection, MergedItem>()
|
||||
snapshot.appendSections([ReverseListSection.main])
|
||||
snapshot.appendItems(mergedItems)
|
||||
@@ -238,8 +240,22 @@ struct ListItem: Hashable {
|
||||
// how many unread items before (older than) this one (excluding this one)
|
||||
let unreadBefore: Int
|
||||
|
||||
private func chatDirHash(_ chatDir: CIDirection?) -> Int {
|
||||
guard let chatDir else { return 0 }
|
||||
return switch chatDir {
|
||||
case .directSnd: 0
|
||||
case .directRcv: 1
|
||||
case .groupSnd: 2
|
||||
case let .groupRcv(mem): "\(mem.groupMemberId) \(mem.displayName) \(mem.memberStatus.rawValue) \(mem.memberRole.rawValue) \(mem.image?.hash ?? 0)".hash
|
||||
case .localSnd: 4
|
||||
case .localRcv: 5
|
||||
}
|
||||
}
|
||||
|
||||
// using meta.hashValue instead of parts of it gives 120ms vs 90ms for MergedItems list generation for 1800 items (+ snapshot time generation for UITableView in MergedItems).
|
||||
// so better to use partial meta here
|
||||
func genHash() -> String {
|
||||
"\(item.meta.itemId) \(item.meta.updatedAt.hashValue) \(item.reactions.count) \(item.meta.isRcvNew) \(item.text.hash) \(unreadBefore) \(prevItem?.id ?? -1) \(nextItem?.id ?? -2)"
|
||||
"\(item.meta.itemId) \(item.meta.updatedAt.hashValue) \(item.meta.itemEdited) \(item.meta.itemDeleted?.hashValue ?? 0) \(item.meta.itemTimed?.hashValue ?? 0) \(item.meta.itemStatus.hashValue) \(item.meta.sentViaProxy ?? false) \(item.mergeCategory?.hashValue ?? 0) \(chatDirHash(item.chatDir)) \(item.reactions.hashValue) \(item.meta.isRcvNew) \(item.text.hash) \(item.file?.hashValue ?? 0) \(item.quotedItem?.itemId ?? 0) \(unreadBefore) \(prevItem?.id ?? 0) \(chatDirHash(prevItem?.chatDir)) \(prevItem?.mergeCategory?.hashValue ?? 0) \(nextItem?.id ?? 0) \(chatDirHash(nextItem?.chatDir)) \(nextItem?.mergeCategory?.hashValue ?? 0)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ struct ChatView: View {
|
||||
@State private var allowToDeleteSelectedMessagesForAll: Bool = false
|
||||
@State private var allowLoadMoreItems: Bool = false
|
||||
@State private var ignoreLoadingRequests: [Int64] = []
|
||||
@State private var updateMergedItemsTask: Task<Void, Never>? = nil
|
||||
|
||||
@AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial
|
||||
|
||||
@@ -473,6 +474,7 @@ struct ChatView: View {
|
||||
forwardedChatItems: $forwardedChatItems,
|
||||
reveal: { reveal in
|
||||
mergedItem.reveal(reveal, $revealedItems)
|
||||
updateMergedItemsTask?.cancel()
|
||||
mergedItems = MergedItems.create(ItemsModel.shared.reversedChatItems, chat.chatStats.unreadCount, revealedItems, ItemsModel.shared.chatState)
|
||||
}
|
||||
)
|
||||
@@ -494,12 +496,23 @@ struct ChatView: View {
|
||||
}
|
||||
}
|
||||
.onChange(of: im.reversedChatItems) { items in
|
||||
mergedItems = MergedItems.create(items, chat.chatStats.unreadCount, revealedItems, ItemsModel.shared.chatState)
|
||||
updateMergedItemsTask?.cancel()
|
||||
updateMergedItemsTask = Task {
|
||||
let items = MergedItems.create(items, chat.chatStats.unreadCount, revealedItems, ItemsModel.shared.chatState)
|
||||
if Task.isCancelled {
|
||||
return
|
||||
}
|
||||
await MainActor.run {
|
||||
mergedItems = items
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: revealedItems) { revealed in
|
||||
updateMergedItemsTask?.cancel()
|
||||
mergedItems = MergedItems.create(im.reversedChatItems, chat.chatStats.unreadCount, revealed, ItemsModel.shared.chatState)
|
||||
}
|
||||
.onChange(of: chat.chatStats.unreadCount) { unreadCount in
|
||||
updateMergedItemsTask?.cancel()
|
||||
mergedItems = MergedItems.create(im.reversedChatItems, unreadCount, revealedItems, ItemsModel.shared.chatState)
|
||||
}
|
||||
.onChange(of: chat.id) { _ in
|
||||
@@ -913,7 +926,9 @@ struct ChatView: View {
|
||||
|
||||
private func loadChatItems(_ cInfo: ChatInfo, _ pagination: ChatPagination, _ visibleItemIndexesNonReversed: @escaping () -> ClosedRange<Int> = { 0 ... 0 }) async -> Bool {
|
||||
if loadingMoreItems { return false }
|
||||
loadingMoreItems = true
|
||||
await MainActor.run {
|
||||
loadingMoreItems = true
|
||||
}
|
||||
var chatItemsAvailable = true
|
||||
var itemsCountChanged = false
|
||||
// Load additional items until the page is +50 large after merging
|
||||
@@ -1049,7 +1064,7 @@ struct ChatView: View {
|
||||
} else {
|
||||
nil
|
||||
}
|
||||
let showAvatar = if case .grouped = merged { shouldShowAvatar(item, listItem.nextItem) } else { true }
|
||||
let showAvatar = shouldShowAvatar(item, listItem.nextItem)
|
||||
let itemSeparation: ItemSeparation
|
||||
let prevItemSeparationLargeGap: Bool
|
||||
let single = switch merged {
|
||||
@@ -1084,7 +1099,8 @@ struct ChatView: View {
|
||||
}
|
||||
.onAppear {
|
||||
// LALAL
|
||||
//return ()
|
||||
return ()
|
||||
|
||||
if markedRead {
|
||||
return
|
||||
} else {
|
||||
|
||||
@@ -61,7 +61,7 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
} else {
|
||||
// when tableView is dragging and new items are added, scroll position cannot be set correctly
|
||||
// so it's better to just wait until dragging ends
|
||||
if !mergedItems.splits.isEmpty && controller.tableView.isDragging/* && !controller.tableView.isDecelerating*/ {
|
||||
if !controller.useSmoothScrolling && !mergedItems.splits.isEmpty && controller.tableView.isDragging/* && !controller.tableView.isDecelerating*/ {
|
||||
controller.runBlockOnEndDecelerating = {
|
||||
Task {
|
||||
let prevSnapshot = controller.dataSource.snapshot()
|
||||
@@ -71,9 +71,9 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
controller.updateFloatingButtons.send()
|
||||
return
|
||||
}
|
||||
await MainActor.run {
|
||||
//await MainActor.run {
|
||||
controller.update(mergedItems.items, mergedItems.snapshot, prevSnapshot)
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -89,7 +89,9 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
controller.updateFloatingButtons.send()
|
||||
return
|
||||
}
|
||||
controller.update(mergedItems.items, mergedItems.snapshot, prevSnapshot)
|
||||
//await MainActor.run {
|
||||
controller.update(mergedItems.items, mergedItems.snapshot, prevSnapshot)
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +116,8 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
|
||||
private var runBlockOnEndScrolling: (() -> Void)? = nil
|
||||
|
||||
private let useSmoothScrolling = false
|
||||
let useSmoothScrolling = false
|
||||
var preloading = false
|
||||
|
||||
init(representer: ReverseList) {
|
||||
self.representer = representer
|
||||
@@ -305,6 +308,7 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
let wasFirstVisibleOffset = listState?.firstVisibleItemOffset ?? 0
|
||||
// Sets content offset on initial load
|
||||
logger.debug("LALAL STEP 4")
|
||||
tableView.panGestureRecognizer.isEnabled = true
|
||||
if wasCount == 0 {
|
||||
dataSource.apply(
|
||||
snapshot,
|
||||
@@ -399,9 +403,11 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
updateFloatingButtons.send()
|
||||
|
||||
if let listState = self.getListState(representer.mergedItems.items) {
|
||||
if runBlockOnEndDecelerating != nil && nearSplit(listState, representer.mergedItems) {
|
||||
stopScrolling()
|
||||
if let block = runBlockOnEndDecelerating, nearSplit(remaining: 40, listState, representer.mergedItems) {
|
||||
tableView.panGestureRecognizer.isEnabled = false
|
||||
block()
|
||||
}
|
||||
logger.debug("LALAL IN SPLIT OR NO \(self.nearSplit(remaining: 40, listState, self.representer.mergedItems)) \(String(describing: self.representer.mergedItems.splits))")
|
||||
preloadIfNeeded(listState)
|
||||
}
|
||||
}
|
||||
@@ -414,14 +420,16 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
}
|
||||
}
|
||||
|
||||
func stopScrolling() {
|
||||
func stopScrolling(disable: Bool = false) {
|
||||
tableView.setContentOffset(self.tableView.contentOffset, animated: false)
|
||||
if disable {
|
||||
tableView.panGestureRecognizer.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
func nearSplit(_ listState: ListState, _ mergedItems: MergedItems) -> Bool {
|
||||
func nearSplit(remaining: Int, _ listState: ListState, _ mergedItems: MergedItems) -> Bool {
|
||||
if mergedItems.splits.isEmpty { return false }
|
||||
|
||||
let remaining = 10
|
||||
let firstVisibleIndex = listState.firstVisibleItemIndex
|
||||
let lastVisibleIndex = listState.lastVisibleItemIndex
|
||||
for split in mergedItems.splits {
|
||||
@@ -435,6 +443,10 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
let containsInRange = split.indexRangeInParentItems.contains(firstVisibleIndex)
|
||||
if containsInRange {
|
||||
if lastVisibleIndex > (split.indexRangeInParentItems.upperBound - remaining) {
|
||||
// situation when there is nothing to load from top
|
||||
if self.representer.ignoreLoadingRequests.contains(where: { $0 == mergedItems.items.last?.oldest().item.id } ) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if firstVisibleIndex < (split.indexRangeInParentItems.lowerBound + remaining) {
|
||||
@@ -543,10 +555,14 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
|
||||
}
|
||||
|
||||
func preloadIfNeeded(_ state: ListState) {
|
||||
if representer.scrollState == .atDestination, prevFirstVisible != state.firstVisibleItemIndex {
|
||||
if representer.scrollState == .atDestination, prevFirstVisible != state.firstVisibleItemIndex, !preloading {
|
||||
logger.debug("LALAL LOADING before \(String(describing: self.representer.scrollState))")
|
||||
prevFirstVisible = state.firstVisibleItemIndex
|
||||
Task {
|
||||
preloading = true
|
||||
defer {
|
||||
preloading = false
|
||||
}
|
||||
let mergedItems = self.representer.mergedItems
|
||||
await preloadItems(mergedItems, self.representer.allowLoadMoreItems, state, self.representer.$ignoreLoadingRequests) { pagination in
|
||||
logger.debug("LALAL LOADING INSIDE")
|
||||
|
||||
Reference in New Issue
Block a user