@@ -44,12 +44,10 @@ struct ContentView: View {
|
|||||||
@State var status: String = "Not connected"
|
@State var status: String = "Not connected"
|
||||||
@State var active_sheet: Sheets? = nil
|
@State var active_sheet: Sheets? = nil
|
||||||
@State var profiles: Profiles = Profiles()
|
@State var profiles: Profiles = Profiles()
|
||||||
@State var active_profile: ProfileModel = ProfileModel()
|
|
||||||
@State var friends: [String: ()] = [:]
|
@State var friends: [String: ()] = [:]
|
||||||
@State var loading: Bool = true
|
@State var loading: Bool = true
|
||||||
@State var pool: RelayPool? = nil
|
@State var pool: RelayPool? = nil
|
||||||
@State var selected_timeline: Timeline? = .home
|
@State var selected_timeline: Timeline? = .home
|
||||||
@StateObject var thread: ThreadModel = ThreadModel()
|
|
||||||
@State var is_thread_open: Bool = false
|
@State var is_thread_open: Bool = false
|
||||||
@State var is_profile_open: Bool = false
|
@State var is_profile_open: Bool = false
|
||||||
@State var last_event_of_kind: [String: [Int: NostrEvent]] = [:]
|
@State var last_event_of_kind: [String: [Int: NostrEvent]] = [:]
|
||||||
@@ -139,7 +137,6 @@ struct ContentView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
if let pool = self.pool {
|
if let pool = self.pool {
|
||||||
TimelineView(events: $friend_events, pool: pool)
|
TimelineView(events: $friend_events, pool: pool)
|
||||||
.environmentObject(thread)
|
|
||||||
.environmentObject(profiles)
|
.environmentObject(profiles)
|
||||||
}
|
}
|
||||||
PostButtonContainer
|
PostButtonContainer
|
||||||
@@ -169,23 +166,6 @@ struct ContentView: View {
|
|||||||
case .none:
|
case .none:
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
let tv = ThreadView()
|
|
||||||
.environmentObject(thread)
|
|
||||||
.environmentObject(profiles)
|
|
||||||
.padding([.leading, .trailing], 6)
|
|
||||||
|
|
||||||
let pv = ProfileView(pool: pool)
|
|
||||||
.environmentObject(active_profile)
|
|
||||||
.environmentObject(profiles)
|
|
||||||
|
|
||||||
NavigationLink(destination: tv, isActive: $is_thread_open) {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationLink(destination: pv, isActive: $is_profile_open) {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.navigationBarTitle("Damus", displayMode: .inline)
|
.navigationBarTitle("Damus", displayMode: .inline)
|
||||||
}
|
}
|
||||||
@@ -212,7 +192,7 @@ struct ContentView: View {
|
|||||||
case .post:
|
case .post:
|
||||||
PostView(references: [])
|
PostView(references: [])
|
||||||
case .reply(let event):
|
case .reply(let event):
|
||||||
ReplyView(replying_to: event)
|
ReplyView(replying_to: event, pool: pool!)
|
||||||
.environmentObject(profiles)
|
.environmentObject(profiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,10 +202,9 @@ struct ContentView: View {
|
|||||||
self.pool?.send(.event(boost))
|
self.pool?.send(.event(boost))
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.open_thread)) { obj in
|
.onReceive(handle_notify(.open_thread)) { obj in
|
||||||
let ev = obj.object as! NostrEvent
|
//let ev = obj.object as! NostrEvent
|
||||||
thread.reset_events()
|
//thread.set_active_event(ev)
|
||||||
thread.set_active_event(ev)
|
//is_thread_open = true
|
||||||
is_thread_open = true
|
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.reply)) { notif in
|
.onReceive(handle_notify(.reply)) { notif in
|
||||||
let ev = notif.object as! NostrEvent
|
let ev = notif.object as! NostrEvent
|
||||||
@@ -235,11 +214,6 @@ struct ContentView: View {
|
|||||||
let ev = obj.object as! NostrEvent
|
let ev = obj.object as! NostrEvent
|
||||||
self.pool?.send(.event(ev))
|
self.pool?.send(.event(ev))
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.click_profile_pic)) { obj in
|
|
||||||
let pubkey = obj.object as! String
|
|
||||||
self.active_profile.set_pubkey(pubkey)
|
|
||||||
self.is_profile_open = true
|
|
||||||
}
|
|
||||||
.onReceive(handle_notify(.post)) { obj in
|
.onReceive(handle_notify(.post)) { obj in
|
||||||
let post_res = obj.object as! NostrPostResult
|
let post_res = obj.object as! NostrPostResult
|
||||||
switch post_res {
|
switch post_res {
|
||||||
@@ -318,8 +292,6 @@ struct ContentView: View {
|
|||||||
pool.register_handler(sub_id: sub_id, handler: handle_event)
|
pool.register_handler(sub_id: sub_id, handler: handle_event)
|
||||||
|
|
||||||
self.pool = pool
|
self.pool = pool
|
||||||
self.thread.pool = pool
|
|
||||||
self.active_profile.pool = pool
|
|
||||||
pool.connect()
|
pool.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,41 +9,24 @@ import Foundation
|
|||||||
|
|
||||||
class ProfileModel: ObservableObject {
|
class ProfileModel: ObservableObject {
|
||||||
@Published var events: [NostrEvent] = []
|
@Published var events: [NostrEvent] = []
|
||||||
@Published var pubkey: String?
|
let pubkey: String
|
||||||
var seen_event: Set<String> = Set()
|
let pool: RelayPool
|
||||||
|
|
||||||
|
var seen_event: Set<String> = Set()
|
||||||
var sub_id = UUID().description
|
var sub_id = UUID().description
|
||||||
|
|
||||||
var pool: RelayPool? = nil
|
|
||||||
|
|
||||||
deinit {
|
init(pubkey: String, pool: RelayPool) {
|
||||||
unsubscribe()
|
self.pubkey = pubkey
|
||||||
|
self.pool = pool
|
||||||
}
|
}
|
||||||
|
|
||||||
func unsubscribe() {
|
func unsubscribe() {
|
||||||
print("unsubscribing from profile \(pubkey ?? "?") with sub_id \(sub_id)")
|
print("unsubscribing from profile \(pubkey) with sub_id \(sub_id)")
|
||||||
pool?.unsubscribe(sub_id: sub_id)
|
pool.unsubscribe(sub_id: sub_id)
|
||||||
}
|
|
||||||
|
|
||||||
func set_pubkey(_ pk: String) {
|
|
||||||
if pk == self.pubkey {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.events.removeAll()
|
|
||||||
self.seen_event.removeAll()
|
|
||||||
|
|
||||||
unsubscribe()
|
|
||||||
self.sub_id = UUID().description
|
|
||||||
self.pubkey = pk
|
|
||||||
subscribe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func subscribe() {
|
func subscribe() {
|
||||||
guard let pubkey = self.pubkey else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let kinds: [Int] = [
|
let kinds: [Int] = [
|
||||||
NostrKind.text.rawValue,
|
NostrKind.text.rawValue,
|
||||||
NostrKind.delete.rawValue,
|
NostrKind.delete.rawValue,
|
||||||
@@ -54,7 +37,7 @@ class ProfileModel: ObservableObject {
|
|||||||
filter.authors = [pubkey]
|
filter.authors = [pubkey]
|
||||||
|
|
||||||
print("subscribing to profile \(pubkey) with sub_id \(sub_id)")
|
print("subscribing to profile \(pubkey) with sub_id \(sub_id)")
|
||||||
pool?.subscribe(sub_id: sub_id, filters: [filter], handler: handle_event)
|
pool.subscribe(sub_id: sub_id, filters: [filter], handler: handle_event)
|
||||||
}
|
}
|
||||||
|
|
||||||
func add_event(_ ev: NostrEvent) {
|
func add_event(_ ev: NostrEvent) {
|
||||||
|
|||||||
@@ -9,25 +9,27 @@ import Foundation
|
|||||||
|
|
||||||
/// manages the lifetime of a thread
|
/// manages the lifetime of a thread
|
||||||
class ThreadModel: ObservableObject {
|
class ThreadModel: ObservableObject {
|
||||||
@Published var event: NostrEvent? = nil
|
@Published var event: NostrEvent
|
||||||
@Published var events: [NostrEvent] = []
|
@Published var events: [NostrEvent] = []
|
||||||
@Published var event_map: [String: Int] = [:]
|
@Published var event_map: [String: Int] = [:]
|
||||||
var replies: ReplyMap = ReplyMap()
|
var replies: ReplyMap = ReplyMap()
|
||||||
|
|
||||||
var pool: RelayPool? = nil
|
let pool: RelayPool
|
||||||
var sub_id = UUID().description
|
var sub_id = UUID().description
|
||||||
|
|
||||||
|
init(ev: NostrEvent, pool: RelayPool) {
|
||||||
|
self.event = ev
|
||||||
|
self.pool = pool
|
||||||
|
subscribe()
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
func unsubscribe() {
|
func unsubscribe() {
|
||||||
guard let event = self.event else {
|
self.pool.unsubscribe(sub_id: sub_id)
|
||||||
return
|
|
||||||
}
|
|
||||||
print("unsubscribing from thread \(event.id) with sub_id \(sub_id)")
|
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func reset_events() {
|
func reset_events() {
|
||||||
@@ -41,16 +43,13 @@ class ThreadModel: ObservableObject {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let ev_a = self.event else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if ev_b.is_root_event() {
|
if ev_b.is_root_event() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// rough heuristic to save us from resubscribing all the time
|
// rough heuristic to save us from resubscribing all the time
|
||||||
return ev_b.count_ids() != ev_a.count_ids()
|
//return ev_b.count_ids() != self.event.count_ids()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func set_active_event(_ ev: NostrEvent) {
|
func set_active_event(_ ev: NostrEvent) {
|
||||||
@@ -58,7 +57,7 @@ class ThreadModel: ObservableObject {
|
|||||||
unsubscribe()
|
unsubscribe()
|
||||||
self.event = ev
|
self.event = ev
|
||||||
add_event(ev)
|
add_event(ev)
|
||||||
subscribe(ev)
|
subscribe()
|
||||||
} else {
|
} else {
|
||||||
self.event = ev
|
self.event = ev
|
||||||
if events.count == 0 {
|
if events.count == 0 {
|
||||||
@@ -67,20 +66,20 @@ class ThreadModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func subscribe(_ ev: NostrEvent) {
|
func subscribe() {
|
||||||
let kinds: [Int] = [1, 5, 6]
|
let kinds: [Int] = [1, 5, 6]
|
||||||
var ref_events = NostrFilter.filter_kinds(kinds)
|
var ref_events = NostrFilter.filter_kinds(kinds)
|
||||||
var events_filter = NostrFilter.filter_kinds(kinds)
|
var events_filter = NostrFilter.filter_kinds(kinds)
|
||||||
|
|
||||||
// TODO: add referenced relays
|
// TODO: add referenced relays
|
||||||
ref_events.referenced_ids = ev.referenced_ids.map { $0.ref_id }
|
ref_events.referenced_ids = event.referenced_ids.map { $0.ref_id }
|
||||||
ref_events.referenced_ids!.append(ev.id)
|
ref_events.referenced_ids!.append(event.id)
|
||||||
|
|
||||||
events_filter.ids = ref_events.referenced_ids!
|
events_filter.ids = ref_events.referenced_ids!
|
||||||
|
|
||||||
print("subscribing to thread \(ev.id) with sub_id \(sub_id)")
|
print("subscribing to thread \(event.id) with sub_id \(sub_id)")
|
||||||
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_filter], sub_id: sub_id)))
|
pool.send(.subscribe(.init(filters: [ref_events, events_filter], sub_id: sub_id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookup(_ event_id: String) -> NostrEvent? {
|
func lookup(_ event_id: String) -> NostrEvent? {
|
||||||
@@ -122,7 +121,7 @@ class ThreadModel: ObservableObject {
|
|||||||
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?
|
||||||
pool?.reconnect(to: [relay_id])
|
pool.reconnect(to: [relay_id])
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,24 @@ extension Notification.Name {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
|
static var notice: Notification.Name {
|
||||||
|
return Notification.Name("notice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
|
static var like: Notification.Name {
|
||||||
|
return Notification.Name("like note")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
|
static var delete: Notification.Name {
|
||||||
|
return Notification.Name("delete note")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension Notification.Name {
|
extension Notification.Name {
|
||||||
static var post: Notification.Name {
|
static var post: Notification.Name {
|
||||||
return Notification.Name("send post")
|
return Notification.Name("send post")
|
||||||
|
|||||||
@@ -40,10 +40,7 @@ struct ChatView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var is_active: Bool {
|
var is_active: Bool {
|
||||||
guard let ev = thread.event else {
|
return thread.event.id == event.id
|
||||||
return false
|
|
||||||
}
|
|
||||||
return ev.id == event.id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func prev_reply_is_same() -> String? {
|
func prev_reply_is_same() -> String? {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ struct ChatroomView: View {
|
|||||||
next_ev: ind == count-1 ? nil : thread.events[ind+1]
|
next_ev: ind == count-1 ? nil : thread.events[ind+1]
|
||||||
)
|
)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if thread.event!.id == ev.id {
|
if thread.event.id == ev.id {
|
||||||
//dismiss()
|
//dismiss()
|
||||||
toggle_thread_view()
|
toggle_thread_view()
|
||||||
} else {
|
} else {
|
||||||
@@ -35,13 +35,13 @@ struct ChatroomView: View {
|
|||||||
}
|
}
|
||||||
.onReceive(NotificationCenter.default.publisher(for: .select_quote)) { notif in
|
.onReceive(NotificationCenter.default.publisher(for: .select_quote)) { notif in
|
||||||
let ev = notif.object as! NostrEvent
|
let ev = notif.object as! NostrEvent
|
||||||
if ev.id != thread.event!.id {
|
if ev.id != thread.event.id {
|
||||||
thread.set_active_event(ev)
|
thread.set_active_event(ev)
|
||||||
}
|
}
|
||||||
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, anchor: .top)
|
||||||
}
|
}
|
||||||
.onAppear() {
|
.onAppear() {
|
||||||
scroll_to_event(scroller: scroller, id: thread.event!.id, delay: 0.3, animate: true, anchor: .bottom)
|
scroll_to_event(scroller: scroller, id: thread.event.id, delay: 0.3, animate: true, anchor: .bottom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ enum ActionBarSheet: Identifiable {
|
|||||||
|
|
||||||
struct EventActionBar: View {
|
struct EventActionBar: View {
|
||||||
let event: NostrEvent
|
let event: NostrEvent
|
||||||
|
|
||||||
@State var sheet: ActionBarSheet? = nil
|
@State var sheet: ActionBarSheet? = nil
|
||||||
@EnvironmentObject var profiles: Profiles
|
@EnvironmentObject var profiles: Profiles
|
||||||
|
@StateObject var bar: ActionBarModel = ActionBarModel()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
/*
|
/*
|
||||||
@@ -33,13 +33,26 @@ struct EventActionBar: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
EventActionButton(img: "bubble.left") {
|
EventActionButton(img: "bubble.left", col: nil) {
|
||||||
notify(.reply, event)
|
notify(.reply, event)
|
||||||
}
|
}
|
||||||
.padding([.trailing], 40)
|
.padding([.trailing], 40)
|
||||||
|
|
||||||
EventActionButton(img: "arrow.2.squarepath") {
|
EventActionButton(img: bar.liked ? "heart.fill" : "heart", col: bar.liked ? Color.red : nil) {
|
||||||
notify(.boost, event)
|
if bar.liked {
|
||||||
|
notify(.delete, bar.our_like_event)
|
||||||
|
} else {
|
||||||
|
notify(.like, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding([.trailing], 40)
|
||||||
|
|
||||||
|
EventActionButton(img: "arrow.2.squarepath", col: bar.boosted ? Color.green : nil) {
|
||||||
|
if bar.boosted {
|
||||||
|
notify(.delete, bar.our_boost_event)
|
||||||
|
} else {
|
||||||
|
notify(.boost, event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -47,11 +60,11 @@ struct EventActionBar: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func EventActionButton(img: String, action: @escaping () -> ()) -> some View {
|
func EventActionButton(img: String, col: Color?, action: @escaping () -> ()) -> some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
Label("", systemImage: img)
|
Label("", systemImage: img)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(col == nil ? Color.gray : col!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ enum CollapsedEvent: Identifiable {
|
|||||||
|
|
||||||
|
|
||||||
struct EventDetailView: View {
|
struct EventDetailView: View {
|
||||||
|
|
||||||
let sub_id = UUID().description
|
let sub_id = UUID().description
|
||||||
|
let pool: RelayPool
|
||||||
|
|
||||||
@StateObject var thread: ThreadModel
|
@StateObject var thread: ThreadModel
|
||||||
@State var collapsed: Bool = true
|
@State var collapsed: Bool = true
|
||||||
@@ -48,37 +48,6 @@ struct EventDetailView: 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)
|
|
||||||
.onAppear() {
|
|
||||||
scroll_to_event(scroller: proxy, id: ev.id, delay: 0.5, animate: true)
|
|
||||||
}
|
|
||||||
.onTapGesture {
|
|
||||||
print_event(ev)
|
|
||||||
let any = any_collapsed(collapsed_events)
|
|
||||||
if (collapsed && any) || (!collapsed && !any) {
|
|
||||||
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 {
|
|
||||||
print_event(ev)
|
|
||||||
if !collapsed {
|
|
||||||
toggle_collapse_thread(scroller: proxy, id: ev.id)
|
|
||||||
}
|
|
||||||
thread.event = ev
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func uncollapse_section(scroller: ScrollViewProxy, c: CollapsedEvents)
|
func uncollapse_section(scroller: ScrollViewProxy, c: CollapsedEvents)
|
||||||
{
|
{
|
||||||
let ev = thread.events[c.start]
|
let ev = thread.events[c.start]
|
||||||
@@ -101,9 +70,9 @@ struct EventDetailView: View {
|
|||||||
toggle_thread_view()
|
toggle_thread_view()
|
||||||
}
|
}
|
||||||
case .event(let ev, let highlight):
|
case .event(let ev, let highlight):
|
||||||
EventView(event: ev, highlight: highlight, has_action_bar: true)
|
EventView(event: ev, highlight: highlight, has_action_bar: true, pool: pool)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if thread.event!.id == ev.id {
|
if thread.event.id == ev.id {
|
||||||
toggle_thread_view()
|
toggle_thread_view()
|
||||||
} else {
|
} else {
|
||||||
thread.set_active_event(ev)
|
thread.set_active_event(ev)
|
||||||
@@ -324,3 +293,34 @@ func scroll_to_event(scroller: ScrollViewProxy, id: String, delay: Double, anima
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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)
|
||||||
|
.onAppear() {
|
||||||
|
scroll_to_event(scroller: proxy, id: ev.id, delay: 0.5, animate: true)
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
print_event(ev)
|
||||||
|
let any = any_collapsed(collapsed_events)
|
||||||
|
if (collapsed && any) || (!collapsed && !any) {
|
||||||
|
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 {
|
||||||
|
print_event(ev)
|
||||||
|
if !collapsed {
|
||||||
|
toggle_collapse_thread(scroller: proxy, id: ev.id)
|
||||||
|
}
|
||||||
|
thread.event = ev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -40,17 +40,21 @@ struct EventView: View {
|
|||||||
let event: NostrEvent
|
let event: NostrEvent
|
||||||
let highlight: Highlight
|
let highlight: Highlight
|
||||||
let has_action_bar: Bool
|
let has_action_bar: Bool
|
||||||
|
let pool: RelayPool
|
||||||
|
|
||||||
@EnvironmentObject var profiles: Profiles
|
@EnvironmentObject var profiles: Profiles
|
||||||
|
@EnvironmentObject var action_bar: ActionBarModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let profile = profiles.lookup(id: event.pubkey)
|
let profile = profiles.lookup(id: event.pubkey)
|
||||||
HStack {
|
HStack {
|
||||||
VStack {
|
VStack {
|
||||||
ProfilePicView(picture: profile?.picture, size: PFP_SIZE!, highlight: highlight)
|
let pv = ProfileView(pool: pool, profile: ProfileModel(pubkey: event.pubkey, pool: pool))
|
||||||
.onTapGesture {
|
.environmentObject(profiles)
|
||||||
NotificationCenter.default.post(name: .click_profile_pic, object: event.pubkey)
|
|
||||||
}
|
NavigationLink(destination: pv) {
|
||||||
|
ProfilePicView(picture: profile?.picture, size: PFP_SIZE!, highlight: highlight)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,14 @@ enum ProfileTab: Hashable {
|
|||||||
struct ProfileView: View {
|
struct ProfileView: View {
|
||||||
let pool: RelayPool
|
let pool: RelayPool
|
||||||
@State private var selected_tab: ProfileTab = .posts
|
@State private var selected_tab: ProfileTab = .posts
|
||||||
|
@StateObject var profile: ProfileModel
|
||||||
|
|
||||||
@EnvironmentObject var profile: ProfileModel
|
//@EnvironmentObject var profile: ProfileModel
|
||||||
@EnvironmentObject var profiles: Profiles
|
@EnvironmentObject var profiles: Profiles
|
||||||
|
|
||||||
var TopSection: some View {
|
var TopSection: some View {
|
||||||
HStack(alignment: .top) {
|
HStack(alignment: .top) {
|
||||||
let data = profile.pubkey.flatMap { profiles.lookup(id: $0) }
|
let data = profiles.lookup(id: profile.pubkey)
|
||||||
ProfilePicView(picture: data?.picture, size: 64, highlight: .custom(Color.black, 4))
|
ProfilePicView(picture: data?.picture, size: 64, highlight: .custom(Color.black, 4))
|
||||||
//.border(Color.blue)
|
//.border(Color.blue)
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
@@ -64,6 +65,13 @@ struct ProfileView: View {
|
|||||||
//.border(Color.white)
|
//.border(Color.white)
|
||||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||||
.navigationBarTitle("Profile")
|
.navigationBarTitle("Profile")
|
||||||
|
.onAppear() {
|
||||||
|
profile.subscribe()
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
profile.unsubscribe()
|
||||||
|
// our profilemodel needs a bit more help
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ func all_referenced_pubkeys(_ ev: NostrEvent) -> [ReferencedId] {
|
|||||||
|
|
||||||
struct ReplyView: View {
|
struct ReplyView: View {
|
||||||
let replying_to: NostrEvent
|
let replying_to: NostrEvent
|
||||||
|
let pool: RelayPool
|
||||||
|
|
||||||
@EnvironmentObject var profiles: Profiles
|
@EnvironmentObject var profiles: Profiles
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ struct ReplyView: View {
|
|||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
}
|
}
|
||||||
EventView(event: replying_to, highlight: .none, has_action_bar: false)
|
EventView(event: replying_to, highlight: .none, has_action_bar: false, pool: pool)
|
||||||
PostView(references: replying_to.reply_ids())
|
PostView(references: replying_to.reply_ids())
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import SwiftUI
|
|||||||
|
|
||||||
struct ThreadView: View {
|
struct ThreadView: View {
|
||||||
@State var is_chatroom: Bool = false
|
@State var is_chatroom: Bool = false
|
||||||
|
@StateObject var thread: ThreadModel
|
||||||
|
let pool: RelayPool
|
||||||
|
|
||||||
@EnvironmentObject var profiles: Profiles
|
@EnvironmentObject var profiles: Profiles
|
||||||
@EnvironmentObject var thread: ThreadModel
|
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -23,13 +24,12 @@ struct ThreadView: View {
|
|||||||
.environmentObject(profiles)
|
.environmentObject(profiles)
|
||||||
.environmentObject(thread)
|
.environmentObject(thread)
|
||||||
} else {
|
} else {
|
||||||
EventDetailView(thread: thread)
|
EventDetailView(pool: pool, thread: thread)
|
||||||
.navigationBarTitle("Thread")
|
.navigationBarTitle("Thread")
|
||||||
.environmentObject(profiles)
|
.environmentObject(profiles)
|
||||||
.environmentObject(thread)
|
.environmentObject(thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NavigationLink(destination: edv, isActive: $is_chatroom) {
|
NavigationLink(destination: edv, isActive: $is_chatroom) {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
|
|||||||
@@ -37,10 +37,16 @@ struct TimelineView: View {
|
|||||||
.environmentObject(profiles)
|
.environmentObject(profiles)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
EventView(event: ev, highlight: .none, has_action_bar: true)
|
let tv = ThreadView(thread: ThreadModel(ev: ev, pool: pool), pool: pool)
|
||||||
.onTapGesture {
|
.environmentObject(profiles)
|
||||||
NotificationCenter.default.post(name: .open_thread, object: ev)
|
|
||||||
}
|
NavigationLink(destination: tv) {
|
||||||
|
EventView(event: ev, highlight: .none, has_action_bar: true, pool: pool)
|
||||||
|
}
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
//.onTapGesture {
|
||||||
|
//NotificationCenter.default.post(name: .open_thread, object: ev)
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user