diff --git a/apps/ios/Shared/Views/Chat/ChatItemsLoader.swift b/apps/ios/Shared/Views/Chat/ChatItemsLoader.swift index 4094da0706..0fed8a78af 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemsLoader.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemsLoader.swift @@ -9,7 +9,7 @@ import SimpleXChat import SwiftUI -let TRIM_KEEP_COUNT = 20000 +let TRIM_KEEP_COUNT = 200 func apiLoadMessages( _ chatType: ChatType, @@ -19,6 +19,7 @@ func apiLoadMessages( _ search: String = "", _ visibleItemIndexesNonReversed: @MainActor () -> ClosedRange = { 0 ... 0 } ) async { + //try? await Task.sleep(nanoseconds: 2000_000000) let chat: Chat let navInfo: NavigationInfo do { @@ -209,6 +210,7 @@ private func removeDuplicatesAndModifySplitsOnBeforePagination( index += 1 return (invisibleItemToTrim && prevItemWasTrimmed) || newIds.contains($0.id) }) + logger.debug("LALAL TRIMMED COUNT \(trimmedIds.count) \(visibleItemIndexes) \(trimRange) \(prevItemTrimRange)") // will remove any splits that now becomes obsolete because items were merged newSplits = newSplits.filter { split in !newIds.contains(split) && !trimmedIds.contains(split) } return ModifiedSplits(oldUnreadSplitIndex: oldUnreadSplitIndex, newUnreadSplitIndex: newUnreadSplitIndex, trimmedIds: trimmedIds, newSplits: newSplits) diff --git a/apps/ios/Shared/Views/Chat/ChatItemsMerger.swift b/apps/ios/Shared/Views/Chat/ChatItemsMerger.swift index 173ed1cac9..93d9e1f938 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemsMerger.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemsMerger.swift @@ -135,8 +135,8 @@ enum MergedItem: Hashable, Equatable { var hash: String { switch self { - case .single(_, _, let hash): hash - case .grouped(_, _, _, _, _, _, _, let hash): hash + case .single(_, _, let hash): hash + " 1" + case .grouped(let items, _, _, _, _, _, _, let hash): hash + " \(items.boxedValue.count)" } } diff --git a/apps/ios/Shared/Views/Chat/ChatScrollHelpers.swift b/apps/ios/Shared/Views/Chat/ChatScrollHelpers.swift index e2c295f9ec..ad0580e1d4 100644 --- a/apps/ios/Shared/Views/Chat/ChatScrollHelpers.swift +++ b/apps/ios/Shared/Views/Chat/ChatScrollHelpers.swift @@ -10,7 +10,6 @@ import SwiftUI import SimpleXChat func loadLastItems(_ loadingMoreItems: Binding, _ chatInfo: ChatInfo) { - //return () if ItemsModel.shared.chatState.totalAfter == 0 { return } @@ -124,6 +123,7 @@ private func findLastIndexToLoadFromInSplits(_ firstVisibleIndex: Int, _ lastVis return nil } +// LALAL DELETE? func tryBlockAndSetLoadingMore(_ loadingMoreItems: Binding, _ block: @escaping () async throws -> Void) async { do { await MainActor.run { diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift index 68bf85dfe2..45c9249d9e 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift @@ -577,8 +577,8 @@ struct ComposeView: View { } } .onAppear { - // LALAL -// for i in 301 ... 600 { + //LALAL +// for i in 0 ... 500 { // Task { // await sendMessageAsync("\(i)", live: false, ttl: nil) // } diff --git a/apps/ios/Shared/Views/Chat/ReverseList.swift b/apps/ios/Shared/Views/Chat/ReverseList.swift index 22d2c47853..11ffd8e53e 100644 --- a/apps/ios/Shared/Views/Chat/ReverseList.swift +++ b/apps/ios/Shared/Views/Chat/ReverseList.swift @@ -114,6 +114,7 @@ struct ReverseList: UIViewControllerRepresentable { private var scrollToRowOnAppear = 0 private var prevFirstVisible = -1 + private var prevItemsCount = -1 // it's set when .around call will be executed which requires to insert more items and skip scrolling var scrollToItemInProgress = false @@ -260,7 +261,7 @@ struct ReverseList: UIViewControllerRepresentable { if #available(iOS 16.0, *) { animated = true } - if tableView.numberOfRows(inSection: 0) > index && index >= 0 { + if prevSnapshot.numberOfItems > index && index >= 0 { tableView.scrollToRow( at: IndexPath(row: index, section: 0), at: position, @@ -280,9 +281,7 @@ struct ReverseList: UIViewControllerRepresentable { // in case of listener will not be called await MainActor.run { representer.scrollState = .atDestination - if let listState = self.getListState() { - self.preloadIfNeeded(listState) - } + self.preloadIfNeeded() } } catch {} } @@ -290,9 +289,7 @@ struct ReverseList: UIViewControllerRepresentable { task.cancel() self.representer.scrollState = .atDestination self.runBlockOnEndScrolling = nil - if let listState = self.getListState() { - self.preloadIfNeeded(listState) - } + self.preloadIfNeeded() } } @@ -371,6 +368,9 @@ struct ReverseList: UIViewControllerRepresentable { nil } let nowFirstIndex: Int? = if let wasFirstId { indexInParentItems[wasFirstId] } else { nil } + //logger.debug("LALAL DIFF start") + //let diff = snapshot.itemIdentifiers.difference(from: prevSnapshot.itemIdentifiers) + //logger.debug("LALAL DIFFERENCES \(diff.insertions.count) \(diff.removals.count)") self.prevSnapshot = snapshot self.prevMergedItems = mergedItems dataSource.apply( @@ -381,15 +381,15 @@ struct ReverseList: UIViewControllerRepresentable { nowFirstIndex - wasFirstIndex } else { 0 } - //logger.debug("LALAL NEARSPLIT split lower WAS LISTSTATE \(listState?.firstVisibleItemIndex ?? -3) now \(self.getListState()?.firstVisibleItemIndex ?? -4) countDiff \(countDiff) wasFirstIndex \(wasFirstIndex ?? -5) nowIndex \(nowFirstIndex ?? -1) wasFirstId \(wasFirstId ?? -1) count \(self.prevSnapshot.itemIdentifiers.count)") + logger.debug("LALAL NEARSPLIT split lower WAS LISTSTATE \(listState?.firstVisibleItemIndex ?? -3) now \(self.getListState()?.firstVisibleItemIndex ?? -4) countDiff \(countDiff) wasFirstIndex \(wasFirstIndex ?? -5) nowIndex \(nowFirstIndex ?? -1) wasFirstId \(wasFirstId ?? -1) count \(self.prevSnapshot.itemIdentifiers.count)") - if countDiff <= 0 { + if countDiff == 0 { // added new items to top, nothing to do, scrolling position is correct } else { self.stopScrolling() // added new items to bottom - //logger.debug("LALAL BEFORE SCROLLTOROW \(snapshot.numberOfItems - 1) \(countDiff) \(wasFirstIndex ?? -5) \(self.tableView.contentOffset.y) \(wasFirstVisibleOffset) \(String(describing: self.representer.mergedItems.splits))") - //self.getListState() + logger.debug("LALAL BEFORE SCROLLTOROW \(snapshot.numberOfItems - 1) \(countDiff) \(wasFirstIndex ?? -5) \(self.tableView.contentOffset.y) \(wasFirstVisibleOffset) \(String(describing: self.representer.mergedItems.splits))") + self.getListState() self.tableView.scrollToRow( at: IndexPath(row: max(0, min(snapshot.numberOfItems - 1, countDiff + (wasFirstIndex ?? 0))), section: 0), at: .top, @@ -429,6 +429,8 @@ struct ReverseList: UIViewControllerRepresentable { updatingInProgress = false tableView.panGestureRecognizer.isEnabled = true } + // covered edge case when you open a chat with a lot of groupped items which smaller than screen size + self.preloadIfNeeded() updateFloatingButtons.send() logger.debug("LALAL STEP 6") } @@ -452,7 +454,7 @@ struct ReverseList: UIViewControllerRepresentable { } } } else { - preloadIfNeeded(listState) + preloadIfNeeded() } } } @@ -597,23 +599,28 @@ struct ReverseList: UIViewControllerRepresentable { } } - func preloadIfNeeded(_ state: ListState) { + func preloadIfNeeded() { let mergedItems = self.representer.mergedItems - logger.debug("LALAL LOADING BEFORE ANYTHING \(state.firstVisibleItemIndex) \(self.prevSnapshot.itemIdentifiers[state.firstVisibleItemIndex].newest().item.id) \(self.representer.$mergedItems.wrappedValue.items[state.firstVisibleItemIndex].newest().item.id)") - if representer.scrollState == .atDestination, prevFirstVisible != state.firstVisibleItemIndex, !preloading { - logger.debug("LALAL LOADING before \(mergedItems.indexInParentItems.count) \(ItemsModel.shared.reversedChatItems.count)") - prevFirstVisible = state.firstVisibleItemIndex - preloading = true - Task { - defer { - preloading = false - } - logger.debug("LALAL LOADING BEFORE INSIDE \(state.firstVisibleItemIndex) \(self.prevSnapshot.itemIdentifiers[state.firstVisibleItemIndex].newest().item.id) \(mergedItems.items[state.firstVisibleItemIndex].newest().item.id) \(mergedItems.splits)") - await preloadItems(mergedItems, self.representer.allowLoadMoreItems, state, self.representer.$ignoreLoadingRequests) { pagination in - logger.debug("LALAL LOADING INSIDE \(mergedItems.items[state.firstVisibleItemIndex].newest().item.id) \(mergedItems.splits)") - let triedToLoad = await self.representer.loadItems(false, pagination, { self.visibleItemIndexesNonReversed(self.prevMergedItems) }) - return triedToLoad - } + guard let state = self.getListState(), + representer.scrollState == .atDestination, + prevFirstVisible != state.firstVisibleItemIndex || prevItemsCount != mergedItems.indexInParentItems.count, + !preloading + else { + return + } + //logger.debug("LALAL LOADING BEFORE ANYTHING \(state.firstVisibleItemIndex) \(self.prevSnapshot.itemIdentifiers[state.firstVisibleItemIndex].newest().item.id) \(self.representer.$mergedItems.wrappedValue.items[state.firstVisibleItemIndex].newest().item.id)") + prevFirstVisible = state.firstVisibleItemIndex + prevItemsCount = mergedItems.indexInParentItems.count + preloading = true + Task { + defer { + preloading = false + } + //logger.debug("LALAL LOADING BEFORE INSIDE \(state.firstVisibleItemIndex) \(self.prevSnapshot.itemIdentifiers[state.firstVisibleItemIndex].newest().item.id) \(mergedItems.items[state.firstVisibleItemIndex].newest().item.id) \(mergedItems.splits)") + await preloadItems(mergedItems, self.representer.allowLoadMoreItems, state, self.representer.$ignoreLoadingRequests) { pagination in + let triedToLoad = await self.representer.loadItems(false, pagination, { self.visibleItemIndexesNonReversed(self.prevMergedItems) }) + logger.debug("LALAL LOADING INSIDE \(mergedItems.items[state.firstVisibleItemIndex].newest().item.id) \(mergedItems.splits), triedToLoad: \(triedToLoad)") + return triedToLoad } } }