point based nearBottom

This commit is contained in:
Levitating Pineapple
2024-08-16 22:20:20 +03:00
parent d76b321919
commit 28fc268e7f
3 changed files with 22 additions and 21 deletions
+1 -9
View File
@@ -897,21 +897,14 @@ final class ChatModel: ObservableObject {
func unreadChatItemCounts(itemsInView: Set<String>) -> UnreadChatItemCounts {
var i = 0
var totalBelow = 0
var unreadBelow = 0
while i < im.reversedChatItems.count - 1 && !itemsInView.contains(im.reversedChatItems[i].viewId) {
totalBelow += 1
if im.reversedChatItems[i].isRcvNew {
unreadBelow += 1
}
i += 1
}
return UnreadChatItemCounts(
// TODO these thresholds account for the fact that items are still "visible" while
// covered by compose area, they should be replaced with the actual height in pixels below the screen.
isNearBottom: totalBelow < 15,
unreadBelow: unreadBelow
)
return UnreadChatItemCounts(unreadBelow: unreadBelow)
}
func topItemInView(itemsInView: Set<String>) -> ChatItem? {
@@ -935,7 +928,6 @@ struct NTFContactRequest {
}
struct UnreadChatItemCounts: Equatable {
var isNearBottom: Bool
var unreadBelow: Int
}
+7 -6
View File
@@ -395,7 +395,11 @@ struct ChatView: View {
let cInfo = chat.chatInfo
let mergedItems = filtered(im.reversedChatItems)
return GeometryReader { g in
ReverseList(items: mergedItems, scrollState: $scrollModel.state) { ci in
ReverseList(
items: mergedItems,
scrollState: $scrollModel.state,
isFarFromBottom: $scrollModel.isFarFromBottom
) { ci in
let voiceNoFrame = voiceWithoutFrame(ci)
let maxWidth = cInfo.chatType == .group
? voiceNoFrame
@@ -470,10 +474,7 @@ struct ChatView: View {
private var bag = Set<AnyCancellable>()
init() {
unreadChatItemCounts = UnreadChatItemCounts(
isNearBottom: true,
unreadBelow: 0
)
unreadChatItemCounts = UnreadChatItemCounts(unreadBelow: 0)
events
.receive(on: DispatchQueue.global(qos: .background))
.scan(Set<String>()) { itemsInView, event in
@@ -537,7 +538,7 @@ struct ChatView: View {
.onTapGesture {
scrollModel.scrollToBottom()
}
} else if !counts.isNearBottom {
} else if scrollModel.isFarFromBottom {
circleButton {
Image(systemName: "chevron.down")
.foregroundColor(theme.colors.primary)
+14 -6
View File
@@ -14,6 +14,7 @@ struct ReverseList<Item: Identifiable & Hashable & Sendable, Content: View>: UIV
let items: Array<Item>
@Binding var scrollState: ReverseListScrollModel<Item>.State
@Binding var isFarFromBottom: Bool
/// Closure, that returns user interface for a given item
let content: (Item) -> Content
@@ -175,16 +176,22 @@ struct ReverseList<Item: Identifiable & Hashable & Sendable, Content: View>: UIV
)
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
let adjustedOffset = tableView.contentOffset.y + InvertedTableView.inset
if representer.isFarFromBottom {
if adjustedOffset < 800 {
DispatchQueue.main.async { self.representer.isFarFromBottom = false }
}
} else if adjustedOffset > 1000 {
DispatchQueue.main.async { self.representer.isFarFromBottom = true }
}
}
private var isNearBottom: Bool {
let adjustedOffset = tableView.contentOffset.y + InvertedTableView.inset
return adjustedOffset > 0 && adjustedOffset < 500
}
private var isFarFromBottom: Bool {
let adjustedOffset = tableView.contentOffset.y + InvertedTableView.inset
return adjustedOffset > 1000
}
private var itemId: Item.ID?
private var retainedItems: [Item]?
private var updateInProgress = false
@@ -217,7 +224,7 @@ struct ReverseList<Item: Identifiable & Hashable & Sendable, Content: View>: UIV
itemCount = items.count
}
func _update(items: Array<Item>, animated: Bool, completion: (() -> Void)? = nil) {
private func _update(items: [Item], animated: Bool, completion: (() -> Void)? = nil) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
@@ -281,6 +288,7 @@ class ReverseListScrollModel<Item: Identifiable>: ObservableObject {
}
@Published var state: State = .atDestination
@Published var isFarFromBottom: Bool = false
func scrollToNextPage() {
state = .scrollingTo(.nextPage)