damus

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

commit 4de2ce402eff8363a8d0557e94c1695731cf1a70
parent 0c63433f8edac8b96ba9cf02b1474879cf6d1267
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 23 Apr 2022 12:41:36 -0700

fix broken nagivation

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 4++++
Mdamus/ContentView.swift | 67+++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mdamus/Models/ThreadModel.swift | 50++++++++++++++++++++++++++++++++------------------
Mdamus/Nostr/RelayConnection.swift | 2+-
Adamus/Notifications.swift | 38++++++++++++++++++++++++++++++++++++++
Mdamus/Views/ChatView.swift | 27++++++++-------------------
Mdamus/Views/ChatroomView.swift | 17+++++++++++++++--
Mdamus/Views/EventActionBar.swift | 15+++++++++------
Mdamus/Views/EventDetailView.swift | 66++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mdamus/Views/EventView.swift | 24+++++++++++++++++++++---
Mdamus/Views/PostView.swift | 24++++++++++++++----------
Mdamus/Views/ProfilePicView.swift | 8+++++---
Mdamus/Views/ReplyQuoteView.swift | 13++++++++-----
Mdamus/Views/ThreadView.swift | 35+++++++++++++++++++++--------------
Mdamus/Views/TimelineView.swift | 38+++++++++++++++++++++++++++-----------
15 files changed, 300 insertions(+), 128 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -26,6 +26,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 */; }; + 4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F8CC281352B30009DFBB /* Notifications.swift */; }; 4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE627F7A08100C66700 /* damusApp.swift */; }; 4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE827F7A08100C66700 /* ContentView.swift */; }; 4CE6DEEB27F7A08200C66700 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */; }; @@ -83,6 +84,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>"; }; + 4CE4F8CC281352B30009DFBB /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; }; 4CE6DEE327F7A08100C66700 /* damus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = damus.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CE6DEE627F7A08100C66700 /* damusApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = damusApp.swift; sourceTree = "<group>"; }; 4CE6DEE827F7A08100C66700 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; @@ -211,6 +213,7 @@ 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */, 4CE6DEEC27F7A08200C66700 /* Preview Content */, 4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */, + 4CE4F8CC281352B30009DFBB /* Notifications.swift */, ); path = damus; sourceTree = "<group>"; @@ -386,6 +389,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */, 4C75EFB728049D990006080F /* RelayPool.swift in Sources */, 4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */, 4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */, diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -24,6 +24,11 @@ enum Sheets: Identifiable { } } +enum ThreadState { + case event_details + case chatroom +} + enum Timeline: String, CustomStringConvertible { case home case notifications @@ -42,11 +47,13 @@ struct ContentView: View { @State var loading: Bool = true @State var pool: RelayPool? = nil @State var selected_timeline: Timeline? = .home + @StateObject var thread: ThreadModel = ThreadModel() + @State var is_thread_open: Bool = false @State var last_event_of_kind: [String: [Int: NostrEvent]] = [:] @State var has_events: [String: ()] = [:] @State var has_friend_event: [String: ()] = [:] @State var new_notifications: Bool = false - + @State var event: NostrEvent? = nil @State var events: [NostrEvent] = [] @State var friend_events: [NostrEvent] = [] @State var notifications: [NostrEvent] = [] @@ -129,6 +136,7 @@ struct ContentView: View { ZStack { if let pool = self.pool { TimelineView(events: $friend_events, pool: pool) + .environmentObject(thread) .environmentObject(profiles) } PostButtonContainer @@ -138,24 +146,35 @@ struct ContentView: View { func MainContent(pool: RelayPool) -> some View { NavigationView { VStack { - PostingTimelineView - .onAppear() { - switch_timeline(.home) - } + switch selected_timeline { + case .home: + PostingTimelineView + .onAppear() { + switch_timeline(.home) + } + + case .notifications: + TimelineView(events: $notifications, pool: pool) + .environmentObject(profiles) + .navigationTitle("Notifications") - let notif = TimelineView(events: $notifications, pool: pool) - .environmentObject(profiles) - .navigationTitle("Notifications") - .navigationBarBackButtonHidden(true) + case .global: + + TimelineView(events: $events, pool: pool) + .environmentObject(profiles) + .navigationTitle("Global") + case .none: + EmptyView() + } - let global = TimelineView(events: $events, pool: pool) + let tv = ThreadView() + .environmentObject(thread) .environmentObject(profiles) - .navigationTitle("Global") - .navigationBarBackButtonHidden(true) + .padding([.leading, .trailing], 6) - NavigationLink(destination: notif, tag: .notifications, selection: $selected_timeline) { EmptyView() } - - NavigationLink(destination: global, tag: .global, selection: $selected_timeline) { EmptyView() } + NavigationLink(destination: tv, isActive: $is_thread_open) { + EmptyView() + } } .navigationBarTitle("Damus", displayMode: .inline) } @@ -183,6 +202,16 @@ struct ContentView: View { PostView(references: []) } } + .onReceive(NotificationCenter.default.publisher(for: .open_thread)) { obj in + let ev = obj.object as! NostrEvent + thread.reset_events() + thread.set_active_event(ev) + is_thread_open = true + } + .onReceive(NotificationCenter.default.publisher(for: .broadcast_event)) { obj in + let ev = obj.object as! NostrEvent + self.pool?.send(.event(ev)) + } .onReceive(NotificationCenter.default.publisher(for: .post)) { obj in let post_res = obj.object as! NostrPostResult @@ -253,11 +282,10 @@ struct ContentView: View { add_relay(pool, "wss://nostr-relay.freeberty.net") add_relay(pool, "wss://nostr-relay.untethr.me") - pool.register_handler(sub_id: sub_id) { (relay_id, ev) in - self.handle_event(relay_id: relay_id, conn_event: ev) - } + pool.register_handler(sub_id: sub_id, handler: handle_event) self.pool = pool + self.thread.pool = pool pool.connect() } @@ -439,11 +467,13 @@ struct ContentView: View { } } +/* struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } + */ func get_metadata_since_time(_ metadata_event: NostrEvent?) -> Int64? { @@ -547,3 +577,4 @@ func save_last_notified(_ ev: NostrEvent) { UserDefaults.standard.set(ev.id, forKey: "last_notification") UserDefaults.standard.set(String(ev.created_at), forKey: "last_notification_time") } + diff --git a/damus/Models/ThreadModel.swift b/damus/Models/ThreadModel.swift @@ -9,39 +9,53 @@ import Foundation /// manages the lifetime of a thread class ThreadModel: ObservableObject { - @Published var event: NostrEvent + @Published var event: NostrEvent? = nil @Published var events: [NostrEvent] = [] @Published var event_map: [String: Int] = [:] var replies: ReplyMap = ReplyMap() - let pool: RelayPool - let sub_id = UUID().description + var pool: RelayPool? = nil + var sub_id = UUID().description - init(event: NostrEvent, pool: RelayPool) { - self.event = event - self.pool = pool - add_event(event) + deinit { + unsubscribe() } func unsubscribe() { + guard let event = self.event else { + return + } print("unsubscribing from thread \(event.id) with sub_id \(sub_id)") - self.pool.remove_handler(sub_id: sub_id) - self.pool.send(.unsubscribe(sub_id)) + self.pool?.remove_handler(sub_id: sub_id) + self.pool?.send(.unsubscribe(sub_id)) + } + + func reset_events() { + self.events.removeAll() + self.event_map.removeAll() + self.replies.replies.removeAll() + } + + func set_active_event(_ ev: NostrEvent) { + unsubscribe() + self.event = ev + add_event(ev) + subscribe(ev) } - func subscribe() { + private func subscribe(_ ev: NostrEvent) { var ref_events = NostrFilter.filter_text - var events = NostrFilter.filter_text + var events_filter = NostrFilter.filter_text // TODO: add referenced relays - ref_events.referenced_ids = event.referenced_ids.map { $0.ref_id } - ref_events.referenced_ids!.append(event.id) + ref_events.referenced_ids = ev.referenced_ids.map { $0.ref_id } + ref_events.referenced_ids!.append(ev.id) - events.ids = ref_events.referenced_ids! + events_filter.ids = ref_events.referenced_ids! - print("subscribing to thread \(event.id) with sub_id \(sub_id)") - pool.register_handler(sub_id: sub_id, handler: handle_event) - pool.send(.subscribe(.init(filters: [ref_events, events], sub_id: sub_id))) + print("subscribing to thread \(ev.id) with sub_id \(sub_id)") + pool?.register_handler(sub_id: sub_id, handler: handle_event) + pool?.send(.subscribe(.init(filters: [ref_events, events_filter], sub_id: sub_id))) } func lookup(_ event_id: String) -> NostrEvent? { @@ -83,7 +97,7 @@ class ThreadModel: ObservableObject { case .notice(let note): if note.contains("Too many subscription filters") { // TODO: resend filters? - pool.reconnect(to: [relay_id]) + pool?.reconnect(to: [relay_id]) } break } diff --git a/damus/Nostr/RelayConnection.swift b/damus/Nostr/RelayConnection.swift @@ -148,7 +148,7 @@ func make_nostr_subscription_req(_ filters: [NostrFilter], sub_id: String) -> St } func make_websocket(url: URL) -> WebSocket { - var req = URLRequest(url: url) + let req = URLRequest(url: url) //req.setValue("chat,superchat", forHTTPHeaderField: "Sec-WebSocket-Protocol") return WebSocket(request: req, compressionHandler: .none) } diff --git a/damus/Notifications.swift b/damus/Notifications.swift @@ -0,0 +1,38 @@ +// +// Notifications.swift +// damus +// +// Created by William Casarin on 2022-04-22. +// + +import Foundation + +extension Notification.Name { + static var thread_focus: Notification.Name { + return Notification.Name("thread focus") + } +} + +extension Notification.Name { + static var select_event: Notification.Name { + return Notification.Name("select_event") + } +} + +extension Notification.Name { + static var broadcast_event: Notification.Name { + return Notification.Name("broadcast event") + } +} + +extension Notification.Name { + static var open_thread: Notification.Name { + return Notification.Name("open thread") + } +} + +extension Notification.Name { + static var post: Notification.Name { + return Notification.Name("send post") + } +} diff --git a/damus/Views/ChatView.swift b/damus/Views/ChatView.swift @@ -20,7 +20,10 @@ struct ChatView: View { } var is_active: Bool { - thread.event.id == event.id + guard let ev = thread.event else { + return false + } + return ev.id == event.id } func prev_reply_is_same() -> String? { @@ -98,7 +101,7 @@ struct ChatView: View { .frame(maxWidth: .infinity, alignment: .leading) .textSelection(.enabled) - if next_ev == nil || next_ev!.pubkey != event.pubkey { + if is_active || next_ev == nil || next_ev!.pubkey != event.pubkey { EventActionBar(event: event) .environmentObject(profiles) } @@ -112,30 +115,14 @@ struct ChatView: View { .id(event.id) .frame(minHeight: just_started ? PFP_SIZE : 0) .padding([.bottom], next_ev == nil ? 4 : 0) - .onTapGesture { - if is_active { - convert_to_thread() - } else { - thread.event = event - } - } //.border(Color.green) } - @Environment(\.presentationMode) var presmode - - func dismiss() { - presmode.wrappedValue.dismiss() - } - - func convert_to_thread() { - NotificationCenter.default.post(name: .convert_to_thread, object: nil) - } } extension Notification.Name { - static var convert_to_thread: Notification.Name { + static var toggle_thread_view: Notification.Name { return Notification.Name("convert_to_thread") } } @@ -149,3 +136,5 @@ struct ChatView_Previews: PreviewProvider { } */ + + diff --git a/damus/Views/ChatroomView.swift b/damus/Views/ChatroomView.swift @@ -9,26 +9,39 @@ import SwiftUI struct ChatroomView: View { @EnvironmentObject var thread: ThreadModel + @Environment(\.dismiss) var dismiss var body: some View { ScrollViewReader { scroller in ScrollView { - VStack { + LazyVStack { let count = thread.events.count ForEach(Array(zip(thread.events, thread.events.indices)), id: \.0.id) { (ev, ind) in ChatView(event: thread.events[ind], prev_ev: ind > 0 ? thread.events[ind-1] : nil, next_ev: ind == count-1 ? nil : thread.events[ind+1] ) + .onTapGesture { + if thread.event!.id == ev.id { + //dismiss() + toggle_thread_view() + } else { + thread.set_active_event(ev) + } + } .environmentObject(thread) } } } .onAppear() { - scroll_to_event(scroller: scroller, id: thread.event.id, delay: 0.5, animate: true, anchor: .center) + scroll_to_event(scroller: scroller, id: thread.event!.id, delay: 0.3, animate: true, anchor: .bottom) } } } + + func toggle_thread_view() { + NotificationCenter.default.post(name: .toggle_thread_view, object: nil) + } } diff --git a/damus/Views/EventActionBar.swift b/damus/Views/EventActionBar.swift @@ -7,12 +7,6 @@ import SwiftUI -extension Notification.Name { - static var thread_focus: Notification.Name { - return Notification.Name("thread focus") - } -} - enum ActionBarSheet: Identifiable { case reply @@ -50,6 +44,15 @@ struct EventActionBar: View { case .reply: ReplyView(replying_to: event) .environmentObject(profiles) + .onReceive(NotificationCenter.default.publisher(for: .post)) { obj in + let res = obj.object as! NostrPostResult + switch res { + case .cancel: + self.sheet = nil + case .post: + self.sheet = nil + } + } } } } diff --git a/damus/Views/EventDetailView.swift b/damus/Views/EventDetailView.swift @@ -47,8 +47,9 @@ struct EventDetailView: View { } } } - - func OurEventView(proxy: ScrollViewProxy, ev: NostrEvent, highlight: Highlight, collapsed_events: [CollapsedEvent]) -> some View { + + /* + func OldEventView(proxy: ScrollViewProxy, ev: NostrEvent, highlight: Highlight, collapsed_events: [CollapsedEvent]) -> some View { Group { if ev.id == thread.event.id { EventView(event: ev, highlight: .main, has_action_bar: true) @@ -76,6 +77,7 @@ struct EventDetailView: View { } } } + */ func uncollapse_section(scroller: ScrollViewProxy, c: CollapsedEvents) { @@ -86,28 +88,52 @@ struct EventDetailView: View { toggle_collapse_thread(scroller: scroller, id: start_id, animate: true, anchor: .top) } + func CollapsedEventView(_ cev: CollapsedEvent, scroller: ScrollViewProxy) -> some View { + Group { + switch cev { + case .collapsed(let c): + Text("··· \(c.count) other replies ···") + .font(.footnote) + .foregroundColor(.gray) + .onTapGesture { + //self.uncollapse_section(scroller: proxy, c: c) + //self.toggle_collapse_thread(scroller: proxy, id: nil) + toggle_thread_view() + } + case .event(let ev, let highlight): + EventView(event: ev, highlight: highlight, has_action_bar: true) + .onTapGesture { + if thread.event!.id == ev.id { + toggle_thread_view() + } else { + thread.set_active_event(ev) + } + } + .onAppear() { + if highlight == .main { + scroll_to_event(scroller: scroller, id: ev.id, delay: 0.5, animate: true) + } + } + } + } + } + var body: some View { ScrollViewReader { proxy in ScrollView { let collapsed_events = calculated_collapsed_events(collapsed: self.collapsed, active: thread.event, events: thread.events) - ForEach(collapsed_events, id: \.id) { cev in - switch cev { - case .collapsed(let c): - Text("··· \(c.count) other replies ···") - .font(.footnote) - .foregroundColor(.gray) - .onTapGesture { - self.uncollapse_section(scroller: proxy, c: c) - //self.toggle_collapse_thread(scroller: proxy, id: nil) - } - case .event(let ev, let highlight): - OurEventView(proxy: proxy, ev: ev, highlight: highlight, collapsed_events: collapsed_events) - } - } + ForEach(collapsed_events, id: \.id) { cev in + CollapsedEventView(cev, scroller: proxy) + } } } + .navigationBarTitle("Thread") } + + func toggle_thread_view() { + NotificationCenter.default.post(name: .toggle_thread_view, object: nil) + } } /* @@ -214,9 +240,13 @@ func determine_highlight(reply_map: [String: ()], current: NostrEvent, active: N */ } -func calculated_collapsed_events(collapsed: Bool, active: NostrEvent, events: [NostrEvent]) -> [CollapsedEvent] { +func calculated_collapsed_events(collapsed: Bool, active: NostrEvent?, events: [NostrEvent]) -> [CollapsedEvent] { var count: Int = 0 - + + guard let active = active else { + return [] + } + let reply_map = make_reply_map(active: active, events: events) if !collapsed { diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift @@ -50,9 +50,6 @@ struct EventView: View { Text("\(format_relative_time(event.created_at))") .foregroundColor(.gray) Spacer() - if (event.pow ?? 0) >= 10 { - PowView(event.pow) - } } if event.is_reply { @@ -82,6 +79,25 @@ struct EventView: View { .id(event.id) .frame(minHeight: PFP_SIZE) .padding([.bottom], 4) + .contextMenu { + Button { + UIPasteboard.general.string = event.content + } label: { + Label("Copy", systemImage: "doc.on.doc") + } + + Button { + UIPasteboard.general.string = event.id + } label: { + Label("Copy ID", systemImage: "tag") + } + + Button { + NotificationCenter.default.post(name: .broadcast_event, object: event) + } label: { + Label("Broadcast", systemImage: "globe") + } + } } } @@ -119,3 +135,5 @@ func reply_others_desc(n: Int, n_pubkeys: Int) -> String { let plural = other == 1 ? "" : "s" return n > 1 ? " & \(other) other\(plural)" : "" } + + diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift @@ -7,10 +7,9 @@ import SwiftUI -extension Notification.Name { - static var post: Notification.Name { - return Notification.Name("send post") - } +enum NostrPostResult { + case post(NostrPost) + case cancel } struct NostrPost { @@ -45,28 +44,33 @@ struct PostView: View { @State var post: String = "" @FocusState var focus: Bool let references: [ReferencedId] - - @Environment(\.presentationMode) var presmode + + @Environment(\.presentationMode) var presentationMode enum FocusField: Hashable { case post } + func cancel() { + NotificationCenter.default.post(name: .post, object: NostrPostResult.cancel) + dismiss() + } + func dismiss() { - presmode.wrappedValue.dismiss() + self.presentationMode.wrappedValue.dismiss() } func send_post() { let new_post = NostrPost(content: self.post, references: references) - NotificationCenter.default.post(name: .post, object: new_post) - dismiss() + NotificationCenter.default.post(name: .post, object: NostrPostResult.post(new_post)) + //dismiss() } var body: some View { VStack { HStack { Button("Cancel") { - self.dismiss() + self.cancel() } .foregroundColor(.primary) diff --git a/damus/Views/ProfilePicView.swift b/damus/Views/ProfilePicView.swift @@ -16,17 +16,19 @@ func id_to_color(_ id: String) -> Color { func highlight_color(_ h: Highlight) -> Color { switch h { + case .reply: fallthrough case .none: return Color.black case .main: return Color.red - case .reply: return Color.blue } } func pfp_line_width(_ h: Highlight) -> CGFloat { - if h.is_none { + switch h { + case .none: fallthrough + case .reply: return 0 + case .main: return 4 } - return 4 } struct ProfilePicView: View { diff --git a/damus/Views/ReplyQuoteView.swift b/damus/Views/ReplyQuoteView.swift @@ -41,12 +41,15 @@ struct ReplyQuoteView: View { var body: some View { Group { if let event = thread.lookup(event_id) { - Group { - MainContent(event: event) - .padding(4) - } - .background(Color.secondary.opacity(0.2)) + MainContent(event: event) + .padding(4) + .frame(maxHeight: 100) + .background(event.id == thread.event!.id ? Color.red.opacity(0.2) : Color.secondary.opacity(0.2)) .cornerRadius(8.0) + .contentShape(Rectangle()) + .onTapGesture { + thread.set_active_event(event) + } } else { ProgressView() .progressViewStyle(.circular) diff --git a/damus/Views/ThreadView.swift b/damus/Views/ThreadView.swift @@ -7,30 +7,37 @@ import SwiftUI + struct ThreadView: View { - @StateObject var thread: ThreadModel - @State var is_thread: Bool = false + @State var is_chatroom: Bool = false @EnvironmentObject var profiles: Profiles + @EnvironmentObject var thread: ThreadModel var body: some View { Group { - ChatroomView() - .environmentObject(thread) - .onReceive(NotificationCenter.default.publisher(for: .convert_to_thread)) { _ in - is_thread = true - } + if is_chatroom { + ChatroomView() + .navigationBarTitle("Chat") + .environmentObject(profiles) + .environmentObject(thread) + } else { + EventDetailView(thread: thread) + .navigationBarTitle("Thread") + .environmentObject(profiles) + .environmentObject(thread) + } - let edv = EventDetailView(thread: thread).environmentObject(profiles) - NavigationLink(destination: edv, isActive: $is_thread) { + + /* + NavigationLink(destination: edv, isActive: $is_chatroom) { EmptyView() } + */ } - .onDisappear() { - thread.unsubscribe() - } - .onAppear() { - thread.subscribe() + .onReceive(NotificationCenter.default.publisher(for: .toggle_thread_view)) { _ in + is_chatroom = !is_chatroom + //print("is_chatroom: \(is_chatroom)") } } } diff --git a/damus/Views/TimelineView.swift b/damus/Views/TimelineView.swift @@ -7,13 +7,25 @@ import SwiftUI +enum TimelineAction { + case chillin + case navigating +} + struct TimelineView: View { @Binding var events: [NostrEvent] + @EnvironmentObject var profiles: Profiles let pool: RelayPool var body: some View { + MainContent + .padding([.leading, .trailing], 6) + .environmentObject(profiles) + } + + var MainContent: some View { ScrollView { LazyVStack { ForEach(events, id: \.id) { (ev: NostrEvent) in @@ -24,20 +36,13 @@ struct TimelineView: View { .environmentObject(profiles) */ - let evdet = ThreadView(thread: ThreadModel(event: ev, pool: pool)) - .navigationBarTitle("Chat") - .padding([.leading, .trailing], 6) - .environmentObject(profiles) - - NavigationLink(destination: evdet) { - EventView(event: ev, highlight: .none, has_action_bar: true) - } - .buttonStyle(PlainButtonStyle()) + EventView(event: ev, highlight: .none, has_action_bar: true) + .onTapGesture { + NotificationCenter.default.post(name: .open_thread, object: ev) + } } } } - .padding([.leading, .trailing], 6) - .environmentObject(profiles) } } @@ -48,3 +53,14 @@ struct TimelineView_Previews: PreviewProvider { } } */ + + +struct NavigationLazyView<Content: View>: View { + let build: () -> Content + init(_ build: @autoclosure @escaping () -> Content) { + self.build = build + } + var body: Content { + build() + } +}