simpler scroll to unread without crazy animations

This commit is contained in:
Diogo
2024-11-07 14:42:32 +00:00
parent 1720c843b1
commit 7168fd9094
2 changed files with 24 additions and 26 deletions
+3 -2
View File
@@ -45,6 +45,7 @@ struct ChatView: View {
@State private var selectedChatItems: Set<Int64>? = nil
@State private var showDeleteSelectedMessages: Bool = false
@State private var allowToDeleteSelectedMessagesForAll: Bool = false
@State private var initialChatItem: ChatItem? = nil
@AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial
@@ -365,7 +366,7 @@ struct ChatView: View {
Task {
DispatchQueue.main.async {
if let firstunreadItem = self.getFirstUnreadItem() {
scrollModel.scrollToUnread(id: firstunreadItem.id)
initialChatItem = firstunreadItem
}
}
}
@@ -424,7 +425,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) { ci in
ReverseList(items: mergedItems, gap: im.gap, scrollState: $scrollModel.state, initialChatItem: $initialChatItem) { ci in
let voiceNoFrame = voiceWithoutFrame(ci)
let maxWidth = cInfo.chatType == .group
? voiceNoFrame
+21 -24
View File
@@ -16,6 +16,7 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
let gap: ChatGap?
@Binding var scrollState: ReverseListScrollModel.State
@Binding var initialChatItem: ChatItem?
/// Closure, that returns user interface for a given item
let content: (ChatItem) -> Content
@@ -37,9 +38,6 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
controller.scrollToItem(to: items.first(where: { $0.id == id }), position: .bottom)
case .bottom:
controller.scroll(to: 0, position: .top)
case let .unread(id):
logger.error("[scrolling] to unread id: (\(id)) size: \(items.count)")
controller.scrollToUnread(to: items.first(where: { $0.id == id }))
}
} else {
logger.error("[scrolling] not scrolling gap: (\(gap?.index ?? -1), \(gap?.size ?? 0))")
@@ -162,6 +160,24 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
tableView.clipsToBounds = false
parent?.viewIfLoaded?.clipsToBounds = false
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let cItem = self.representer.initialChatItem, let indexPath = dataSource.indexPath(for: cItem) {
if !isVisible(indexPath: indexPath) {
if tableView.numberOfRows(inSection: indexPath.section) > indexPath.row {
let cellRect = tableView.rectForRow(at: indexPath)
logger.error("[scrolling] minY: \(cellRect.minY), maxY: \(cellRect.maxY) y: \(cellRect.origin.y)")
tableView.setContentOffset(CGPoint(x: 0, y: cellRect.maxY - tableView.bounds.height), animated: false)
}
}
Task {
DispatchQueue.main.async {
self.representer.initialChatItem = nil
}
}
}
}
/// Scrolls up
func scrollToNextPage() {
@@ -175,21 +191,6 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
Task { representer.scrollState = .atDestination }
}
func scrollToUnread(to cItem: ChatItem?) {
if let it = cItem, let indexPath = dataSource.indexPath(for: it) {
if isVisible(indexPath: indexPath) {
logger.error("[scrolling] unread visible")
self.scroll(to: 0, position: .bottom)
} else {
logger.error("[scrolling] unread not visible and at line index: \(indexPath.row)")
self.scrollToItem(to: cItem, position: .bottom)
}
} else {
logger.error("[scrolling] unread not found")
self.scroll(to: nil, position: .top)
}
}
func scrollToItem(to cItem: ChatItem?, position: UITableView.ScrollPosition) {
if let it = cItem, let indexPath = dataSource.indexPath(for: it) {
self.scroll(to: indexPath.row, position: position)
@@ -263,6 +264,8 @@ struct ReverseList<Content: View>: UIViewControllerRepresentable {
if let visibleRows = tableView.indexPathsForVisibleRows,
visibleRows.last?.item ?? 0 < renderedItems.count {
let scrollOffset: Double = tableView.contentOffset.y + InvertedTableView.inset
logger.error("[scrolling] scroll offset: \(scrollOffset)")
let topItemDate: Date? =
if let lastVisible = visibleRows.last(where: { isVisible(indexPath: $0) }) {
renderedItems[lastVisible.item].meta.itemTs
@@ -407,7 +410,6 @@ class ReverseListScrollModel: ObservableObject {
case nextPage
case item(ChatItem.ID)
case bottom
case unread(ChatItem.ID)
}
case scrollingTo(Destination)
@@ -431,11 +433,6 @@ class ReverseListScrollModel: ObservableObject {
logger.error("[scrolling] to item \(id)")
state = .scrollingTo(.item(id))
}
func scrollToUnread(id: ChatItem.ID) {
logger.error("[scrolling] to unread")
state = .scrollingTo(.unread(id))
}
}
fileprivate let cellReuseId = "hostingCell"