diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index a5b0380a65..6dc88d21cc 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -454,50 +454,55 @@ struct ChatView: View { @Published var date: Date? @Published var isDateVisible: Bool = false var isReallyNearBottom: Bool { scrollOffset.value > 0 && scrollOffset.value < 500 } - let visibleItems = PassthroughSubject<[String], Never>() + let listState = PassthroughSubject() let scrollOffset = CurrentValueSubject(0) + private var bag = Set() + typealias ListState = ( + topItemDate: Date?, + bottomItemId: ChatItem.ID? + ) + + private struct ViewUpdate: Equatable { + let unreadBelow: Int + let date: Date? + } + init() { // Date - visibleItems + listState .receive(on: DispatchQueue.global(qos: .background)) - .map { visibleItems -> Date? in - if let viewId = visibleItems.last { - ItemsModel.shared.reversedChatItems - .first { $0.viewId == viewId } - .map { Calendar.current.startOfDay(for: $0.meta.itemTs) } - } else { nil } + .map { listState -> ViewUpdate in + let im = ItemsModel.shared + return ViewUpdate( + unreadBelow: { + if let id = listState.bottomItemId, + let index = im.reversedChatItems.firstIndex(where: { $0.id == id }) { + im.reversedChatItems[..: UIViewControllerRepresentable { } private func updateVisibleItems() { - let fbm = ChatView.FloatingButtonModel.shared - fbm.scrollOffset.send(tableView.contentOffset.y + InvertedTableView.inset) - fbm.visibleItems.send( - (tableView.indexPathsForVisibleRows ?? []) - .compactMap { indexPath -> String? in - guard let relativeFrame = tableView.superview?.convert( - tableView.rectForRow(at: indexPath), - from: tableView - ) else { return nil } - // Checks that the cell is visible accounting for the added insets - let isVisible = - relativeFrame.maxY > InvertedTableView.inset && - relativeFrame.minY < tableView.frame.height - InvertedTableView.inset - return indexPath.item < representer.items.count && isVisible - ? representer.items[indexPath.item].viewId - : nil - } - ) + if let visibleRows = tableView.indexPathsForVisibleRows, + visibleRows.last?.item ?? 0 < representer.items.count { + let fbm = ChatView.FloatingButtonModel.shared + fbm.scrollOffset.send(tableView.contentOffset.y + InvertedTableView.inset) + fbm.listState.send(( + topItemDate: visibleRows + .last { isVisible(indexPath: $0) } + .map { representer.items[$0.item] }? + .meta.itemTs, + bottomItemId: visibleRows + .first { isVisible(indexPath: $0) } + .map { representer.items[$0.item] }? + .id + )) + } + } + + private func isVisible(indexPath: IndexPath) -> Bool { + if let relativeFrame = tableView.superview?.convert( + tableView.rectForRow(at: indexPath), + from: tableView + ) { + relativeFrame.maxY > InvertedTableView.inset && + relativeFrame.minY < tableView.frame.height - InvertedTableView.inset + } else { false } } }