diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 7f666b2861..54104f1b28 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -322,15 +322,15 @@ let loadItemsPerPage = 100 let preloadItem = 25 let idealChatListSize = 300 -func apiGetChat(type: ChatType, id: Int64, search: String = "") async throws -> (Chat, Int?) { +func apiGetChat(type: ChatType, id: Int64, search: String = "") async throws -> Chat { let r = await chatSendCmd(.apiGetChat(type: type, id: id, pagination: .initial(count: loadItemsPerPage), search: search)) - if case let .apiChat(_, chat, gap) = r { return (Chat.init(chat), gap) } + if case let .apiChat(_, chat, _) = r { return Chat.init(chat) } throw r } -func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, search: String = "") async throws -> ([ChatItem], Int?) { +func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, search: String = "") async throws -> [ChatItem] { let r = await chatSendCmd(.apiGetChat(type: type, id: id, pagination: pagination, search: search)) - if case let .apiChat(_, chat, gap) = r { return (chat.chatItems, gap) } + if case let .apiChat(_, chat, _) = r { return chat.chatItems } if case .chatCmdError(_, _) = r { if case .chatError(_, let chatError) = r { if case .errorStore(let storeError) = chatError { @@ -355,14 +355,9 @@ func loadChat(chat: Chat, search: String = "", clearItems: Bool = true) async { im.gap = nil } } - let (chat, gap) = try await apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search) + let chat = try await apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search) await MainActor.run { im.reversedChatItems = chat.chatItems.reversed() - if let gap = gap { - im.gap = ChatGap(index: loadItemsPerPage, size: gap) - } else { - im.gap = nil - } m.updateChatInfo(chat.chatInfo) } } catch let error { diff --git a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift index 82367a21b2..389668a48f 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift @@ -349,7 +349,7 @@ struct FramedItemView: View { let im = ItemsModel.shared var reversedPage = Array() let pagination: ChatPagination = .around(chatItemId: chatItemId, count: loadItemsPerPage * 2) - let (chatItems, gap) = try await apiGetChatItems( + let chatItems = try await apiGetChatItems( type: cInfo.chatType, id: cInfo.apiId, pagination: pagination, @@ -366,18 +366,12 @@ struct FramedItemView: View { } let itemCount = im.reversedChatItems.count - if let size = gap, size - itemCount > 0 { - im.gap = ChatGap(index: itemCount, size: size - itemCount) - } im.reversedChatItems.append(contentsOf: reversedPage) } if (itemsToDrop.count > 0) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { Task { - if let g = im.gap { - im.gap = ChatGap(index: g.index - itemsToDrop.count, size: g.size + itemsToDrop.count) - } im.reversedChatItems.removeAll(where: { itemsToDrop.contains($0.id) }) } } diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 968fa71068..8f994a9db9 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -427,7 +427,7 @@ struct ChatView: View { let cInfo = chat.chatInfo let mergedItems = filtered(im.reversedChatItems) return GeometryReader { g in - ReverseList(items: mergedItems, gap: im.gap, scrollState: $scrollModel.state, initialChatItem: $initialChatItem) { ci in + ReverseList(items: mergedItems, scrollState: $scrollModel.state, initialChatItem: $initialChatItem) { ci in let voiceNoFrame = voiceWithoutFrame(ci) let maxWidth = cInfo.chatType == .group ? voiceNoFrame @@ -485,7 +485,6 @@ struct ChatView: View { scrollModel.scrollToBottom() if let g = im.gap { let sliceSize = min(g.index, idealChatListSize) - im.gap = nil im.reversedChatItems = Array(im.reversedChatItems[..() - var apiGap: Int? = nil var chatItemsAvailable = true // Load additional items until the page is +50 large after merging while chatItemsAvailable && filtered(reversedPage).count < loadItemsPerPage { @@ -906,13 +904,12 @@ struct ChatView: View { case .around(_, _): throw RuntimeError("Unsupported pagination type for loading chat items: \(pagination)") } - let (chatItems, gap) = try await apiGetChatItems( + let chatItems = try await apiGetChatItems( type: cInfo.chatType, id: cInfo.apiId, pagination: chatPagination, search: searchText ) - apiGap = gap chatItemsAvailable = !chatItems.isEmpty reversedPage.append(contentsOf: chatItems.reversed()) } @@ -928,28 +925,12 @@ struct ChatView: View { case .before(_, _): if im.reversedChatItems.count + dedupedreversePage.count > idealChatListSize, dedupedreversePage.count <= loadItemsPerPage { - if let gap = im.gap { - im.gap = ChatGap(index: gap.index, size: gap.size + dedupedreversePage.count) - } else { - im.gap = ChatGap(index: loadItemsPerPage, size: dedupedreversePage.count) - } im.reversedChatItems.removeSubrange(loadItemsPerPage.. 0 { - im.gap = ChatGap(index: gap.index, size: size) - if im.reversedChatItems.count + dedupedreversePage.count - gap.index > idealChatListSize { - im.reversedChatItems.removeLast(dedupedreversePage.count) - } - } else { - im.gap = nil - } - } im.reversedChatItems.insert(contentsOf: dedupedreversePage, at: index) } case .around(_, _): break diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index 67a045ab9a..fd72b5b515 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -340,7 +340,7 @@ struct GroupMemberInfoView: View { InfoViewButton(image: "message.fill", title: "message", width: width) { Task { do { - let (chat, _) = try await apiGetChat(type: .direct, id: contactId) + let chat = try await apiGetChat(type: .direct, id: contactId) chatModel.addChat(chat) ItemsModel.shared.loadOpenChat(chat.id) { dismissAllSheets(animated: true) diff --git a/apps/ios/Shared/Views/Chat/ReverseList.swift b/apps/ios/Shared/Views/Chat/ReverseList.swift index 133740ca77..49212d6d80 100644 --- a/apps/ios/Shared/Views/Chat/ReverseList.swift +++ b/apps/ios/Shared/Views/Chat/ReverseList.swift @@ -13,7 +13,6 @@ import SimpleXChat /// A List, which displays it's items in reverse order - from bottom to top struct ReverseList: UIViewControllerRepresentable { let items: Array - let gap: ChatGap? @Binding var scrollState: ReverseListScrollModel.State @Binding var initialChatItem: ChatItem? @@ -40,7 +39,7 @@ struct ReverseList: UIViewControllerRepresentable { controller.scroll(to: 0, position: .top) } } else { - controller.update(items: items, gap: gap) + controller.update(items: items) } } @@ -52,7 +51,6 @@ struct ReverseList: UIViewControllerRepresentable { private var itemCount: Int = 0 private let updateFloatingButtons = PassthroughSubject() private var bag = Set() - private var renderedItems = Array() init(representer: ReverseList) { self.representer = representer @@ -222,27 +220,15 @@ struct ReverseList: UIViewControllerRepresentable { } } - func update(items: [ChatItem], gap: ChatGap?) { + func update(items: [ChatItem]) { var snapshot = NSDiffableDataSourceSnapshot() - let originalSize = renderedItems.count - if let gap = gap { - var itemsCopy = items - let blanks = (0..<20).map { index in - // Using existing text instead of random rumble or empty text does make long scroll look natural. - let sourceItem = items[index % items.count] - return ChatItem.placeholder(idx: index + 1, text: sourceItem.text, chatDir: sourceItem.chatDir) - } - itemsCopy.insert(contentsOf: blanks, at: gap.index) - renderedItems = itemsCopy - } else { - renderedItems = items - } + let originalSize = tableView.numberOfRows(inSection: 0) snapshot.appendSections([.main]) - snapshot.appendItems(renderedItems) + snapshot.appendItems(items) dataSource.defaultRowAnimation = .none - let countDiff = max(0, renderedItems.count - originalSize) - if tableView.contentOffset.y == 0, originalSize > countDiff { + let countDiff = max(0, items.count - originalSize) + if tableView.contentOffset.y == 100, originalSize < items.count, originalSize > 0 { dataSource.apply( snapshot, animatingDifferences: false @@ -269,7 +255,7 @@ struct ReverseList: UIViewControllerRepresentable { animated: false ) } - itemCount = renderedItems.count + itemCount = items.count updateFloatingButtons.send() } @@ -279,18 +265,18 @@ struct ReverseList: UIViewControllerRepresentable { func getListState() -> ListState? { if let visibleRows = tableView.indexPathsForVisibleRows, - visibleRows.last?.item ?? 0 < renderedItems.count { + visibleRows.last?.item ?? 0 < representer.items.count { let scrollOffset: Double = tableView.contentOffset.y + InvertedTableView.inset let topItemDate: Date? = if let lastVisible = visibleRows.last(where: { isVisible(indexPath: $0) }) { - renderedItems[lastVisible.item].meta.itemTs + representer.items[lastVisible.item].meta.itemTs } else { nil } let bottomItemId: ChatItem.ID? = if let firstVisible = visibleRows.first(where: { isVisible(indexPath: $0) }) { - renderedItems[firstVisible.item].id + representer.items[firstVisible.item].id } else { nil }