damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit eec8763733adb99f47d2581cd463f310a13a9522
parent ff6f2a61ac1bc98eead0dc695319d80b6189f92b
Author: William Casarin <jb55@jb55.com>
Date:   Tue,  9 Aug 2022 09:32:22 -0700

scroll: more consistent scrolling behavior

Scrolling will always anchor the active note to the top of the screen

This is less confusing overall

Changelog-Changed: Clicking on a note will now always scroll it to the top
Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 4++++
Adamus/Components/EndBlock.swift | 32++++++++++++++++++++++++++++++++
Mdamus/Models/ThreadModel.swift | 4+++-
Mdamus/Views/ChatroomView.swift | 9++++++---
Mdamus/Views/DMChatView.swift | 4+---
Mdamus/Views/EventDetailView.swift | 38++++++++++++++++++++++++++------------
6 files changed, 72 insertions(+), 19 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -84,6 +84,7 @@ 4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */; }; 4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */; }; 4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CACA9DB280C38C000D9BBE8 /* Profiles.swift */; }; + 4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD7641A28A1641400B6928F /* EndBlock.swift */; }; 4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F8CC281352B30009DFBB /* Notifications.swift */; }; 4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */; }; 4CE4F9E1285287B800C00DD9 /* TextFieldAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F9E0285287B800C00DD9 /* TextFieldAlert.swift */; }; @@ -202,6 +203,7 @@ 4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = "<group>"; }; 4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyView.swift; sourceTree = "<group>"; }; 4CACA9DB280C38C000D9BBE8 /* Profiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Profiles.swift; sourceTree = "<group>"; }; + 4CD7641A28A1641400B6928F /* EndBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndBlock.swift; sourceTree = "<group>"; }; 4CE4F8CC281352B30009DFBB /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; }; 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigView.swift; sourceTree = "<group>"; }; 4CE4F9E0285287B800C00DD9 /* TextFieldAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldAlert.swift; sourceTree = "<group>"; }; @@ -370,6 +372,7 @@ isa = PBXGroup; children = ( 4CE4F9E0285287B800C00DD9 /* TextFieldAlert.swift */, + 4CD7641A28A1641400B6928F /* EndBlock.swift */, ); path = Components; sourceTree = "<group>"; @@ -646,6 +649,7 @@ 4C363A8828236948006E126D /* BlocksView.swift in Sources */, 4C75EFAF28049D350006080F /* NostrFilter.swift in Sources */, 4C363A9C282838B9006E126D /* EventRef.swift in Sources */, + 4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */, 4C8682872814DE470026224F /* ProfileView.swift in Sources */, 4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */, 4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */, diff --git a/damus/Components/EndBlock.swift b/damus/Components/EndBlock.swift @@ -0,0 +1,32 @@ +// +// EndBlock.swift +// damus +// +// Created by William Casarin on 2022-08-08. +// + +import SwiftUI + +struct EndBlock: View { + let height: CGFloat + + init () { + self.height = 80.0 + } + + init (height: Float) { + self.height = CGFloat(height) + } + + var body: some View { + Color.white.opacity(0) + .id("endblock") + .frame(height: height) + } +} + +struct EndBlock_Previews: PreviewProvider { + static var previews: some View { + EndBlock() + } +} diff --git a/damus/Models/ThreadModel.swift b/damus/Models/ThreadModel.swift @@ -189,7 +189,9 @@ class ThreadModel: ObservableObject { } if done { - loading = false + if (events.contains { ev in ev.id == initial_event.id }) { + loading = false + } } } diff --git a/damus/Views/ChatroomView.swift b/damus/Views/ChatroomView.swift @@ -14,7 +14,7 @@ struct ChatroomView: View { var body: some View { ScrollViewReader { scroller in - ScrollView { + ScrollView(.vertical) { LazyVStack(alignment: .leading) { let count = thread.events.count ForEach(Array(zip(thread.events, thread.events.indices)), id: \.0.id) { (ev, ind) in @@ -34,17 +34,20 @@ struct ChatroomView: View { } .environmentObject(thread) } + } + + EndBlock() } .onReceive(NotificationCenter.default.publisher(for: .select_quote)) { notif in let ev = notif.object as! NostrEvent if ev.id != thread.initial_event.id { thread.set_active_event(ev, privkey: damus.keypair.privkey) } - scroll_to_event(scroller: scroller, id: ev.id, delay: 0, animate: true, anchor: .top) + scroll_to_event(scroller: scroller, id: ev.id, delay: 0, animate: true) } .onAppear() { - scroll_to_event(scroller: scroller, id: thread.initial_event.id, delay: 0.3, animate: false, anchor: .bottom) + scroll_to_event(scroller: scroller, id: thread.initial_event.id, delay: 0.1, animate: false) } } } diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift @@ -21,9 +21,7 @@ struct DMChatView: View { DMView(event: dms.events[ind], damus_state: damus_state) .event_context_menu(ev, privkey: damus_state.keypair.privkey) } - Color.white.opacity(0) - .id("endblock") - .frame(height: 80) + EndBlock() } } .onAppear { diff --git a/damus/Views/EventDetailView.swift b/damus/Views/EventDetailView.swift @@ -37,11 +37,11 @@ struct EventDetailView: View { @StateObject var thread: ThreadModel @State var collapsed: Bool = true - func toggle_collapse_thread(scroller: ScrollViewProxy, id mid: String?, animate: Bool = true, anchor: UnitPoint = .center) { + func toggle_collapse_thread(scroller: ScrollViewProxy, id mid: String?, animate: Bool = true) { self.collapsed = !self.collapsed if let id = mid { if !self.collapsed { - scroll_to_event(scroller: scroller, id: id, delay: 0.1, animate: animate, anchor: anchor) + scroll_to_event(scroller: scroller, id: id, delay: 0.1, animate: animate) } } } @@ -52,7 +52,7 @@ struct EventDetailView: View { print("uncollapsing section at \(c.start) '\(ev.content.prefix(12))...'") let start_id = ev.id - toggle_collapse_thread(scroller: scroller, id: start_id, animate: false, anchor: .top) + toggle_collapse_thread(scroller: scroller, id: start_id, animate: false) } func CollapsedEventView(_ cev: CollapsedEvent, scroller: ScrollViewProxy) -> some View { @@ -76,18 +76,17 @@ struct EventDetailView: View { thread.set_active_event(ev, privkey: damus.keypair.privkey) } } - .onAppear() { - if highlight.is_main { - scroll_to_event(scroller: scroller, id: ev.id, delay: 0.5, animate: true) - } - } } } } var body: some View { ScrollViewReader { proxy in - ScrollView { + if thread.loading { + ProgressView().progressViewStyle(.circular) + } + + ScrollView(.vertical) { let collapsed_events = calculated_collapsed_events( privkey: damus.keypair.privkey, collapsed: self.collapsed, @@ -97,11 +96,26 @@ struct EventDetailView: View { ForEach(collapsed_events, id: \.id) { cev in CollapsedEventView(cev, scroller: proxy) } + + EndBlock(height: 600) + } + .onChange(of: thread.loading) { val in + scroll_after_load(proxy) + } + .onAppear() { + scroll_after_load(proxy) } } .navigationBarTitle("Thread") } + + func scroll_after_load(_ proxy: ScrollViewProxy) { + if !thread.loading { + let id = thread.initial_event.id + scroll_to_event(scroller: proxy, id: id, delay: 0.1, animate: false) + } + } func toggle_thread_view() { NotificationCenter.default.post(name: .toggle_thread_view, object: nil) @@ -273,14 +287,14 @@ func print_event(_ ev: NostrEvent) { print(ev.description) } -func scroll_to_event(scroller: ScrollViewProxy, id: String, delay: Double, animate: Bool, anchor: UnitPoint = .center) { +func scroll_to_event(scroller: ScrollViewProxy, id: String, delay: Double, animate: Bool) { DispatchQueue.main.asyncAfter(deadline: .now() + delay) { if animate { withAnimation { - scroller.scrollTo(id, anchor: anchor) + scroller.scrollTo(id, anchor: .top) } } else { - scroller.scrollTo(id, anchor: anchor) + scroller.scrollTo(id, anchor: .top) } } }