TimelineView.swift (2830B)
1 // 2 // TimelineView.swift 3 // damus 4 // 5 // Created by William Casarin on 2022-04-18. 6 // 7 8 import SwiftUI 9 10 struct TimelineView<Content: View>: View { 11 @ObservedObject var events: EventHolder 12 @Binding var loading: Bool 13 14 let damus: DamusState 15 let show_friend_icon: Bool 16 let filter: (NostrEvent) -> Bool 17 let content: Content? 18 let debouncer: Debouncer 19 20 init(events: EventHolder, loading: Binding<Bool>, damus: DamusState, show_friend_icon: Bool, filter: @escaping (NostrEvent) -> Bool, content: (() -> Content)? = nil) { 21 self.events = events 22 self._loading = loading 23 self.damus = damus 24 self.show_friend_icon = show_friend_icon 25 self.filter = filter 26 self.debouncer = Debouncer(interval: 0.5) 27 self.content = content?() 28 } 29 30 var body: some View { 31 MainContent 32 } 33 34 var MainContent: some View { 35 ScrollViewReader { scroller in 36 ScrollView { 37 if let content { 38 content 39 } 40 41 Color.white.opacity(0) 42 .id("startblock") 43 .frame(height: 1) 44 45 InnerTimelineView(events: events, damus: damus, filter: loading ? { _ in true } : filter) 46 .redacted(reason: loading ? .placeholder : []) 47 .shimmer(loading) 48 .disabled(loading) 49 .background(GeometryReader { proxy -> Color in 50 debouncer.debounce_immediate { 51 handle_scroll_queue(proxy, queue: self.events) 52 } 53 return Color.clear 54 }) 55 } 56 //.buttonStyle(BorderlessButtonStyle()) 57 .coordinateSpace(name: "scroll") 58 .onReceive(handle_notify(.scroll_to_top)) { () in 59 events.flush() 60 self.events.should_queue = false 61 scroll_to_event(scroller: scroller, id: "startblock", delay: 0.0, animate: true, anchor: .top) 62 } 63 } 64 .onAppear { 65 events.flush() 66 } 67 } 68 } 69 70 struct TimelineView_Previews: PreviewProvider { 71 @StateObject static var events = test_event_holder 72 static var previews: some View { 73 TimelineView<AnyView>(events: events, loading: .constant(true), damus: test_damus_state, show_friend_icon: true, filter: { _ in true }) 74 } 75 } 76 77 78 protocol ScrollQueue { 79 var should_queue: Bool { get } 80 func set_should_queue(_ val: Bool) 81 } 82 83 func handle_scroll_queue(_ proxy: GeometryProxy, queue: ScrollQueue) { 84 let offset = -proxy.frame(in: .named("scroll")).origin.y 85 guard offset >= 0 else { 86 return 87 } 88 let val = offset > 0 89 if queue.should_queue != val { 90 queue.set_should_queue(val) 91 } 92 }