mirror of
git://jb55.com/damus
synced 2024-09-19 11:43:44 +00:00
make note of collapsed events
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
parent
700a0e2625
commit
550f096808
@ -121,7 +121,11 @@ struct ContentView: View {
|
|||||||
let privkey = ""
|
let privkey = ""
|
||||||
let new_ev = NostrEvent(content: post.content, pubkey: pubkey)
|
let new_ev = NostrEvent(content: post.content, pubkey: pubkey)
|
||||||
for id in post.references {
|
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.calculate_id()
|
||||||
new_ev.sign(privkey: privkey)
|
new_ev.sign(privkey: privkey)
|
||||||
|
@ -86,9 +86,9 @@ class NostrEvent: Codable, Identifiable {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reply_ids() -> [String] {
|
public func reply_ids() -> [ReferencedId] {
|
||||||
var ids = self.referenced_ids.map { $0.ref_id }
|
var ids = self.referenced_ids.first.map { [$0] } ?? []
|
||||||
ids.append(self.id)
|
ids.append(ReferencedId(ref_id: self.id, relay_id: nil))
|
||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,14 +31,18 @@ struct EventActionBar: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
EventActionButton(img: "bubble.left") {
|
Spacer()
|
||||||
self.sheet = .reply
|
|
||||||
|
/*
|
||||||
|
EventActionButton(img: "square.and.arrow.up") {
|
||||||
|
print("share")
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
*/
|
||||||
|
|
||||||
EventActionButton(img: "square.and.arrow.up") {
|
EventActionButton(img: "bubble.left") {
|
||||||
print("share")
|
self.sheet = .reply
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sheet(item: $sheet) { sheet in
|
.sheet(item: $sheet) { sheet in
|
||||||
|
@ -7,6 +7,20 @@
|
|||||||
|
|
||||||
import SwiftUI
|
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 {
|
struct EventDetailView: View {
|
||||||
@State var event: NostrEvent
|
@State var event: NostrEvent
|
||||||
|
|
||||||
@ -14,6 +28,7 @@ struct EventDetailView: View {
|
|||||||
|
|
||||||
@State var events: [NostrEvent] = []
|
@State var events: [NostrEvent] = []
|
||||||
@State var has_event: [String: ()] = [:]
|
@State var has_event: [String: ()] = [:]
|
||||||
|
@State var collapsed: Bool = true
|
||||||
|
|
||||||
@EnvironmentObject var profiles: Profiles
|
@EnvironmentObject var profiles: Profiles
|
||||||
|
|
||||||
@ -39,7 +54,13 @@ struct EventDetailView: View {
|
|||||||
pool.register_handler(sub_id: sub_id, handler: handle_event)
|
pool.register_handler(sub_id: sub_id, handler: handle_event)
|
||||||
pool.send(.subscribe(.init(filters: [ref_events, events], sub_id: sub_id)))
|
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) {
|
func handle_event(relay_id: String, ev: NostrConnectionEvent) {
|
||||||
switch ev {
|
switch ev {
|
||||||
@ -48,11 +69,8 @@ struct EventDetailView: View {
|
|||||||
case .nostr_event(let res):
|
case .nostr_event(let res):
|
||||||
switch res {
|
switch res {
|
||||||
case .event(let sub_id, let ev):
|
case .event(let sub_id, let ev):
|
||||||
if sub_id != self.sub_id || self.has_event[ev.id] != nil {
|
add_event(ev: ev)
|
||||||
return
|
|
||||||
}
|
|
||||||
self.add_event(ev)
|
|
||||||
|
|
||||||
case .notice(let note):
|
case .notice(let note):
|
||||||
if note.contains("Too many subscription filters") {
|
if note.contains("Too many subscription filters") {
|
||||||
// TODO: resend 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 {
|
var body: some View {
|
||||||
ScrollViewReader { proxy in
|
ScrollViewReader { proxy in
|
||||||
ScrollView {
|
ScrollView {
|
||||||
ForEach(events, id: \.id) { ev in
|
ForEach(calculated_collapsed_events(collapsed: self.collapsed, active: self.event, events: self.events), id: \.id) { cev in
|
||||||
Group {
|
switch cev {
|
||||||
let is_active_id = ev.id == event.id
|
case .collapsed(let i, _):
|
||||||
if is_active_id {
|
Text("··· \(i) notes hidden ···")
|
||||||
EventView(event: ev, highlight: .main, has_action_bar: true)
|
.font(.footnote)
|
||||||
.onAppear() {
|
.foregroundColor(.gray)
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
case .event(let ev, let highlight):
|
||||||
withAnimation {
|
OurEventView(proxy: proxy, ev: ev, highlight: highlight)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,6 +163,9 @@ struct EventDetailView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
func determine_highlight(current: NostrEvent, active: NostrEvent) -> Highlight
|
func determine_highlight(current: NostrEvent, active: NostrEvent) -> Highlight
|
||||||
{
|
{
|
||||||
|
if current.id == active.id {
|
||||||
|
return .main
|
||||||
|
}
|
||||||
if active.references(id: current.id, key: "e") {
|
if active.references(id: current.id, key: "e") {
|
||||||
return .replied_to(active.id)
|
return .replied_to(active.id)
|
||||||
} else if current.references(id: active.id, key: "e") {
|
} else if current.references(id: active.id, key: "e") {
|
||||||
@ -127,3 +173,37 @@ func determine_highlight(current: NostrEvent, active: NostrEvent) -> Highlight
|
|||||||
}
|
}
|
||||||
return .none
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import CachedAsyncImage
|
|||||||
enum Highlight {
|
enum Highlight {
|
||||||
case none
|
case none
|
||||||
case main
|
case main
|
||||||
case referenced(String)
|
|
||||||
case replied_to(String)
|
case replied_to(String)
|
||||||
|
|
||||||
var is_none: Bool {
|
var is_none: Bool {
|
||||||
@ -75,6 +74,7 @@ struct EventView: View {
|
|||||||
Divider()
|
Divider()
|
||||||
.padding([.top], 4)
|
.padding([.top], 4)
|
||||||
}
|
}
|
||||||
|
.padding([.leading], 2)
|
||||||
}
|
}
|
||||||
.id(event.id)
|
.id(event.id)
|
||||||
.frame(minHeight: PFP_SIZE)
|
.frame(minHeight: PFP_SIZE)
|
||||||
|
@ -15,14 +15,14 @@ extension Notification.Name {
|
|||||||
|
|
||||||
struct NostrPost {
|
struct NostrPost {
|
||||||
let content: String
|
let content: String
|
||||||
let references: [String]
|
let references: [ReferencedId]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct PostView: View {
|
struct PostView: View {
|
||||||
@State var post: String = ""
|
@State var post: String = ""
|
||||||
@FocusState var focus: Bool
|
@FocusState var focus: Bool
|
||||||
let references: [String]
|
let references: [ReferencedId]
|
||||||
|
|
||||||
@Environment(\.presentationMode) var presmode
|
@Environment(\.presentationMode) var presmode
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ func highlight_color(_ h: Highlight) -> Color {
|
|||||||
switch h {
|
switch h {
|
||||||
case .none: return Color.black
|
case .none: return Color.black
|
||||||
case .main: return Color.red
|
case .main: return Color.red
|
||||||
case .referenced(let id): return Color.blue
|
|
||||||
case .replied_to: return Color.blue
|
case .replied_to: return Color.blue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user