dual snapshot animation

This commit is contained in:
Levitating Pineapple
2024-08-16 19:11:47 +03:00
parent 4005da2524
commit 5b18da4fe6
3 changed files with 30 additions and 37 deletions
+7 -6
View File
@@ -450,13 +450,14 @@ final class ChatModel: ObservableObject {
}
return false
} else {
var ci = cItem
if let status = chatItemStatuses.removeValue(forKey: ci.id), case .sndNew = ci.meta.itemStatus {
ci.meta.itemStatus = status
withConditionalAnimation(itemAnimation()) {
var ci = cItem
if let status = chatItemStatuses.removeValue(forKey: ci.id), case .sndNew = ci.meta.itemStatus {
ci.meta.itemStatus = status
}
im.reversedChatItems.insert(ci, at: hasLiveDummy ? 1 : 0)
im.itemAdded = true
}
if itemAnimation() != nil { FadeInChatItem.items.insert(ci.id) }
im.reversedChatItems.insert(ci, at: hasLiveDummy ? 1 : 0)
im.itemAdded = true
return true
}
-23
View File
@@ -413,7 +413,6 @@ struct ChatView: View {
revealedChatItem: $revealedChatItem,
selectedChatItems: $selectedChatItems
)
.modifier(FadeInChatItem(id: ci.id))
.onAppear {
floatingButtonModel.appeared(viewId: ci.viewId)
}
@@ -1551,28 +1550,6 @@ private func buildTheme() -> AppTheme {
}
}
struct FadeInChatItem: ViewModifier {
static var items = Set<ChatItem.ID>()
private let chatItemId: ChatItem.ID
@State private var isVisible: Bool
init(id: ChatItem.ID) {
chatItemId = id
isVisible = !Self.items.contains(chatItemId)
}
func body(content: Content) -> some View {
content
.opacity(isVisible ? 1 : 0)
.onAppear {
if !isVisible {
Self.items.remove(chatItemId)
withAnimation(.easeInOut(duration: 0.5)) { isVisible = true }
}
}
}
}
struct ToggleNtfsButton: View {
@ObservedObject var chat: Chat
+23 -8
View File
@@ -171,17 +171,32 @@ struct ReverseList<Item: Identifiable & Hashable & Sendable, Content: View>: UIV
Task { representer.scrollState = .atDestination }
}
func update(items: Array<Item>) {
var updateInProgress = false
func update(items: [Item]) {
if updateInProgress { return }
let itemsAdded = items.count - itemCount
if itemsAdded > 0, itemCount != 0 {
updateInProgress = true
_update(items: Array(items[1...]), animated: false) {
DispatchQueue.main.async {
self._update(items: items, animated: true) {
self.updateInProgress = false
}
}
}
} else {
_update(items: items, animated: false)
}
itemCount = items.count
}
func _update(items: Array<Item>, animated: Bool, completion: (() -> Void)? = nil) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
dataSource.defaultRowAnimation = .none
let countChange = abs(items.count - itemCount)
dataSource.apply(snapshot, animatingDifferences:
countChange > 0 && // Avoid animating initial load
countChange < 5 // Avoid animating page loads
)
itemCount = items.count
dataSource.defaultRowAnimation = animated ? .top : .none
dataSource.apply(snapshot, animatingDifferences: animated, completion: completion)
}
}