Browse Source

calculate ancestor reply path

This works really well going back in time because no branching, assuming
the last referenced event id is the only note they are replying to...

Signed-off-by: William Casarin <jb55@jb55.com>
profiles-everywhere
William Casarin 3 years ago
parent
commit
6ce5484d74
  1. 104
      damus/Views/EventDetailView.swift
  2. 4
      damus/Views/EventView.swift
  3. 2
      damus/Views/ProfilePicView.swift

104
damus/Views/EventDetailView.swift

@ -10,7 +10,7 @@ import SwiftUI
enum CollapsedEvent: Identifiable {
case event(NostrEvent, Highlight)
case collapsed(Int, String)
var id: String {
switch self {
case .event(let ev, _):
@ -29,9 +29,9 @@ struct EventDetailView: View {
@State var events: [NostrEvent] = []
@State var has_event: [String: ()] = [:]
@State var collapsed: Bool = true
@EnvironmentObject var profiles: Profiles
let pool: RelayPool
func unsubscribe_to_thread() {
@ -54,7 +54,7 @@ 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
@ -72,7 +72,7 @@ struct EventDetailView: View {
if sub_id == self.sub_id {
add_event(ev: ev)
}
case .notice(let note):
if note.contains("Too many subscription filters") {
// TODO: resend filters?
@ -82,14 +82,14 @@ 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 {
@ -97,7 +97,7 @@ struct EventDetailView: View {
}
}
}
func OurEventView(proxy: ScrollViewProxy, ev: NostrEvent, highlight: Highlight) -> some View {
Group {
if ev.id == event.id {
@ -121,7 +121,7 @@ struct EventDetailView: View {
}
}
}
var body: some View {
ScrollViewReader { proxy in
ScrollView {
@ -143,7 +143,7 @@ struct EventDetailView: View {
.onAppear() {
self.add_event(event)
subscribe_to_thread()
}
}
@ -166,34 +166,100 @@ struct EventDetailView_Previews: PreviewProvider {
}
*/
/// Find the entire reply path for the active event
func make_reply_map(active: NostrEvent, events: [NostrEvent]) -> [String: ()]
{
let event_map: [String: Int] = zip(events,0...events.count).reduce(into: [:]) { (acc, arg1) in
let (ev, i) = arg1
acc[ev.id] = i
}
var is_reply: [String: ()] = [:]
var i: Int = 0
var start: Int = 0
var iterations: Int = 0
if events.count == 0 {
return is_reply
}
for ev in events {
if ev.references(id: active.id, key: "e") {
is_reply[ev.id] = ()
start = i
} else if active.references(id: ev.id, key: "e") {
is_reply[ev.id] = ()
start = i
}
i += 1
}
i = start
while true {
if iterations > 1024 {
// infinite loop? or super large thread
print("breaking from large reply_map... big thread??")
break
}
let ev = events[i]
let ref_ids = ev.referenced_ids
if ref_ids.count == 0 {
break
}
let ref_id = ref_ids[ref_ids.count-1]
let pubkey = ref_id.ref_id
is_reply[pubkey] = ()
if let mi = event_map[pubkey] {
i = mi
} else {
break
}
iterations += 1
}
return is_reply
}
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)
return .reply
} else if current.references(id: active.id, key: "e") {
return .replied_to(current.id)
return .reply
}
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))
}
}
let reply_map = make_reply_map(active: active, events: events)
let nevents = events.count
var i: Int = 0
return events.reduce(into: []) { (acc, ev) in
let highlight = determine_highlight(current: ev, active: active)
var highlight: Highlight = .none
if ev.id == active.id {
highlight = .main
} else if reply_map[ev.id] != nil {
highlight = .reply
}
switch highlight {
case .none:
count += 1
@ -203,21 +269,21 @@ func calculated_collapsed_events(collapsed: Bool, active: NostrEvent, events: [N
count = 0
}
acc.append(.event(ev, .main))
case .replied_to:
case .reply:
if count != 0 {
acc.append(.collapsed(count, UUID().description))
count = 0
}
acc.append(.event(ev, highlight))
}
if i == nevents-1 {
if count != 0 {
acc.append(.collapsed(count, UUID().description))
count = 0
}
}
i += 1
}
}

4
damus/Views/EventView.swift

@ -12,7 +12,7 @@ import CachedAsyncImage
enum Highlight {
case none
case main
case replied_to(String)
case reply
var is_none: Bool {
switch self {
@ -23,7 +23,7 @@ enum Highlight {
var is_replied_to: Bool {
switch self {
case .replied_to: return true
case .reply: return true
default: return false
}
}

2
damus/Views/ProfilePicView.swift

@ -19,7 +19,7 @@ func highlight_color(_ h: Highlight) -> Color {
switch h {
case .none: return Color.black
case .main: return Color.red
case .replied_to: return Color.blue
case .reply: return Color.blue
}
}

Loading…
Cancel
Save