commit 550f09680893543440a396caa52ea34a0cfa2e1a
parent 700a0e2625fb02aea4366476149ff3c88343ea61
Author: William Casarin <jb55@jb55.com>
Date: Sun, 17 Apr 2022 11:11:11 -0700
make note of collapsed events
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
7 files changed, 125 insertions(+), 38 deletions(-)
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -121,7 +121,11 @@ struct ContentView: View {
let privkey = ""
let new_ev = NostrEvent(content: post.content, pubkey: pubkey)
for id in post.references {
- new_ev.tags.append(["e", id])
+ var tag = ["e", id.ref_id]
+ if let relay_id = id.relay_id {
+ tag.append(relay_id)
+ }
+ new_ev.tags.append(tag)
}
new_ev.calculate_id()
new_ev.sign(privkey: privkey)
diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift
@@ -86,9 +86,9 @@ class NostrEvent: Codable, Identifiable {
return false
}
- public func reply_ids() -> [String] {
- var ids = self.referenced_ids.map { $0.ref_id }
- ids.append(self.id)
+ public func reply_ids() -> [ReferencedId] {
+ var ids = self.referenced_ids.first.map { [$0] } ?? []
+ ids.append(ReferencedId(ref_id: self.id, relay_id: nil))
return ids
}
diff --git a/damus/Views/EventActionBar.swift b/damus/Views/EventActionBar.swift
@@ -31,14 +31,18 @@ struct EventActionBar: View {
var body: some View {
HStack {
- EventActionButton(img: "bubble.left") {
- self.sheet = .reply
+ Spacer()
+
+ /*
+ EventActionButton(img: "square.and.arrow.up") {
+ print("share")
}
Spacer()
+ */
- EventActionButton(img: "square.and.arrow.up") {
- print("share")
+ EventActionButton(img: "bubble.left") {
+ self.sheet = .reply
}
}
.sheet(item: $sheet) { sheet in
diff --git a/damus/Views/EventDetailView.swift b/damus/Views/EventDetailView.swift
@@ -7,6 +7,20 @@
import SwiftUI
+enum CollapsedEvent: Identifiable {
+ case event(NostrEvent, Highlight)
+ case collapsed(Int, String)
+
+ var id: String {
+ switch self {
+ case .event(let ev, _):
+ return ev.id
+ case .collapsed(_, let id):
+ return id
+ }
+ }
+}
+
struct EventDetailView: View {
@State var event: NostrEvent
@@ -14,6 +28,7 @@ struct EventDetailView: View {
@State var events: [NostrEvent] = []
@State var has_event: [String: ()] = [:]
+ @State var collapsed: Bool = true
@EnvironmentObject var profiles: Profiles
@@ -39,7 +54,13 @@ struct EventDetailView: View {
pool.register_handler(sub_id: sub_id, handler: handle_event)
pool.send(.subscribe(.init(filters: [ref_events, events], sub_id: sub_id)))
}
-
+
+ func add_event(ev: NostrEvent) {
+ if sub_id != self.sub_id || self.has_event[ev.id] != nil {
+ return
+ }
+ self.add_event(ev)
+ }
func handle_event(relay_id: String, ev: NostrConnectionEvent) {
switch ev {
@@ -48,11 +69,8 @@ struct EventDetailView: View {
case .nostr_event(let res):
switch res {
case .event(let sub_id, let ev):
- if sub_id != self.sub_id || self.has_event[ev.id] != nil {
- return
- }
- self.add_event(ev)
-
+ add_event(ev: ev)
+
case .notice(let note):
if note.contains("Too many subscription filters") {
// TODO: resend filters?
@@ -62,29 +80,54 @@ struct EventDetailView: View {
}
}
}
-
+
+ func toggle_collapse_thread(scroller: ScrollViewProxy, id: String) {
+ self.collapsed = !self.collapsed
+ if !self.collapsed {
+ scroll_to_event(scroller: scroller, id: id, delay: 0.1)
+ }
+ }
+
+ func scroll_to_event(scroller: ScrollViewProxy, id: String, delay: Double) {
+ DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
+ withAnimation {
+ scroller.scrollTo(event.id)
+ }
+ }
+ }
+
+ func OurEventView(proxy: ScrollViewProxy, ev: NostrEvent, highlight: Highlight) -> some View {
+ Group {
+ if ev.id == event.id {
+ EventView(event: ev, highlight: .main, has_action_bar: true)
+ .onAppear() {
+ scroll_to_event(scroller: proxy, id: ev.id, delay: 0.5)
+ }
+ .onTapGesture {
+ toggle_collapse_thread(scroller: proxy, id: ev.id)
+ }
+ } else {
+ if !(self.collapsed && highlight.is_none) {
+ EventView(event: ev, highlight: collapsed ? .none : highlight, has_action_bar: true)
+ .onTapGesture {
+ self.event = ev
+ }
+ }
+ }
+ }
+ }
+
var body: some View {
ScrollViewReader { proxy in
ScrollView {
- ForEach(events, id: \.id) { ev in
- Group {
- let is_active_id = ev.id == event.id
- if is_active_id {
- EventView(event: ev, highlight: .main, has_action_bar: true)
- .onAppear() {
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
- withAnimation {
- proxy.scrollTo(event.id)
- }
- }
- }
- } else {
- let highlight = determine_highlight(current: ev, active: event)
- EventView(event: ev, highlight: highlight, has_action_bar: true)
- .onTapGesture {
- self.event = ev
- }
- }
+ ForEach(calculated_collapsed_events(collapsed: self.collapsed, active: self.event, events: self.events), id: \.id) { cev in
+ switch cev {
+ case .collapsed(let i, _):
+ Text("··· \(i) notes hidden ···")
+ .font(.footnote)
+ .foregroundColor(.gray)
+ case .event(let ev, let highlight):
+ OurEventView(proxy: proxy, ev: ev, highlight: highlight)
}
}
}
@@ -120,6 +163,9 @@ struct EventDetailView_Previews: PreviewProvider {
func determine_highlight(current: NostrEvent, active: NostrEvent) -> Highlight
{
+ if current.id == active.id {
+ return .main
+ }
if active.references(id: current.id, key: "e") {
return .replied_to(active.id)
} else if current.references(id: active.id, key: "e") {
@@ -127,3 +173,37 @@ func determine_highlight(current: NostrEvent, active: NostrEvent) -> Highlight
}
return .none
}
+
+func calculated_collapsed_events(collapsed: Bool, active: NostrEvent, events: [NostrEvent]) -> [CollapsedEvent] {
+ var count: Int = 0
+
+ if !collapsed {
+ return events.reduce(into: []) { acc, ev in
+ let highlight = determine_highlight(current: ev, active: active)
+ return acc.append(.event(ev, highlight))
+ }
+ }
+
+ return events.reduce(into: []) { (acc, ev) in
+ let highlight = determine_highlight(current: ev, active: active)
+
+ switch highlight {
+ case .none:
+ count += 1
+ case .main:
+ if count != 0 {
+ acc.append(.collapsed(count, UUID().description))
+ count = 0
+ }
+ acc.append(.event(ev, .main))
+ case .replied_to:
+ if count != 0 {
+ acc.append(.collapsed(count, UUID().description))
+ count = 0
+ }
+ acc.append(.event(ev, highlight))
+ }
+
+ }
+}
+
diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift
@@ -12,7 +12,6 @@ import CachedAsyncImage
enum Highlight {
case none
case main
- case referenced(String)
case replied_to(String)
var is_none: Bool {
@@ -75,6 +74,7 @@ struct EventView: View {
Divider()
.padding([.top], 4)
}
+ .padding([.leading], 2)
}
.id(event.id)
.frame(minHeight: PFP_SIZE)
diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift
@@ -15,14 +15,14 @@ extension Notification.Name {
struct NostrPost {
let content: String
- let references: [String]
+ let references: [ReferencedId]
}
struct PostView: View {
@State var post: String = ""
@FocusState var focus: Bool
- let references: [String]
+ let references: [ReferencedId]
@Environment(\.presentationMode) var presmode
diff --git a/damus/Views/ProfilePicView.swift b/damus/Views/ProfilePicView.swift
@@ -19,7 +19,6 @@ func highlight_color(_ h: Highlight) -> Color {
switch h {
case .none: return Color.black
case .main: return Color.red
- case .referenced(let id): return Color.blue
case .replied_to: return Color.blue
}
}