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>
This commit is contained in:
William Casarin
2022-08-09 09:32:22 -07:00
parent ff6f2a61ac
commit eec8763733
6 changed files with 72 additions and 19 deletions

View File

@@ -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()
}
}

View File

@@ -189,7 +189,9 @@ class ThreadModel: ObservableObject {
}
if done {
loading = false
if (events.contains { ev in ev.id == initial_event.id }) {
loading = false
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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 {

View File

@@ -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)
}
}
}