commit 97fbee85c061b410b7d0d6ad58a53aa6dae53d97
parent 967c4639763473240c59d520b04286ab5f981d3a
Author: William Casarin <jb55@jb55.com>
Date: Wed, 13 Apr 2022 12:18:01 -0700
posting, global timeline
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
6 files changed, 91 insertions(+), 23 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -29,6 +29,7 @@
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DF1527F8DEBF00C66700 /* RelayConnection.swift */; };
4CEE2AEB2805AEA300AB5EEF /* secp256k1 in Frameworks */ = {isa = PBXBuildFile; productRef = 4CEE2AEA2805AEA300AB5EEF /* secp256k1 */; };
4CEE2AED2805B22500AB5EEF /* NostrRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AEC2805B22500AB5EEF /* NostrRequest.swift */; };
+ 4CEE2AEF2805BE2500AB5EEF /* NostrTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AEE2805BE2500AB5EEF /* NostrTimeline.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -73,6 +74,7 @@
4CE6DF1527F8DEBF00C66700 /* RelayConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayConnection.swift; sourceTree = "<group>"; };
4CEE2AE72804F57C00AB5EEF /* libsecp256k1.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsecp256k1.a; sourceTree = "<group>"; };
4CEE2AEC2805B22500AB5EEF /* NostrRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrRequest.swift; sourceTree = "<group>"; };
+ 4CEE2AEE2805BE2500AB5EEF /* NostrTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrTimeline.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -125,6 +127,7 @@
4C75EFB628049D990006080F /* RelayPool.swift */,
4C75EFBA2804A34C0006080F /* ProofOfWork.swift */,
4CEE2AEC2805B22500AB5EEF /* NostrRequest.swift */,
+ 4CEE2AEE2805BE2500AB5EEF /* NostrTimeline.swift */,
);
path = Nostr;
sourceTree = "<group>";
@@ -344,6 +347,7 @@
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
4C75EFB328049D640006080F /* NostrEvent.swift in Sources */,
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
+ 4CEE2AEF2805BE2500AB5EEF /* NostrTimeline.swift in Sources */,
4C75EFAF28049D350006080F /* NostrFilter.swift in Sources */,
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */,
4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */,
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -27,37 +27,66 @@ enum Sheets: Identifiable {
}
}
+enum Timeline {
+ case friends
+ case global
+}
+
struct ContentView: View {
@State var status: String = "Not connected"
- @State var sub_id: String? = nil
@State var active_sheet: Sheets? = nil
@State var events: [NostrEvent] = []
@State var profiles: [String: TimestampedProfile] = [:]
+ @State var friends: [String: ()] = [:]
@State var has_events: [String: ()] = [:]
@State var profile_count: Int = 0
@State var last_event_of_kind: [Int: NostrEvent] = [:]
@State var loading: Bool = true
+ @State var timeline: Timeline = .friends
@State var pool: RelayPool? = nil
+ let pubkey = "fd3fdb0d0d8d6f9a7667b53211de8ae3c5246b79bdaf64ebac849d5148b5615f"
+
var MainContent: some View {
ScrollView {
ForEach(events, id: \.id) {
- EventView(event: $0, profile: profiles[$0.pubkey]?.profile)
+ if timeline == .global || (timeline == .friends && is_friend($0.pubkey)) {
+ EventView(event: $0, profile: profiles[$0.pubkey]?.profile)
+ }
}
}
}
- var body: some View {
- ZStack {
- MainContent
- .padding()
- VStack {
- Spacer()
+ var TopBar: some View {
+ HStack {
+ Button(action: {switch_timeline(.friends)}) {
+ Label("", systemImage: "person.2")
+ }
+ .padding([.trailing], 50.0)
+ .foregroundColor(self.timeline == .global ? .gray : .primary)
- HStack {
+ Button(action: {switch_timeline(.global)}) {
+ Label("", systemImage: "globe.americas")
+ }
+ .padding([.leading], 50.0)
+ .foregroundColor(self.timeline == .friends ? .gray : .primary)
+ }
+ }
+
+ var body: some View {
+ VStack {
+ TopBar
+ ZStack {
+ MainContent
+ .padding()
+ VStack {
Spacer()
- PostButton() {
- self.active_sheet = .post
+
+ HStack {
+ Spacer()
+ PostButton() {
+ self.active_sheet = .post
+ }
}
}
}
@@ -74,7 +103,6 @@ struct ContentView: View {
.onReceive(NotificationCenter.default.publisher(for: .post)) { obj in
let post = obj.object as! NostrPost
print("post \(post.content)")
- let pubkey = ""
let privkey = ""
let new_ev = NostrEvent(content: post.content, pubkey: pubkey)
new_ev.sign(privkey: privkey)
@@ -82,6 +110,14 @@ struct ContentView: View {
}
}
+ func is_friend(_ pubkey: String) -> Bool {
+ return pubkey == self.pubkey || self.friends[pubkey] != nil
+ }
+
+ func switch_timeline(_ timeline: Timeline) {
+ self.timeline = timeline
+ }
+
func connect() {
let pool = RelayPool(handle_event: handle_event)
@@ -94,6 +130,14 @@ struct ContentView: View {
}
func handle_contact_event(_ ev: NostrEvent) {
+ if ev.pubkey == self.pubkey {
+ // our contacts
+ for tag in ev.tags {
+ if tag.count > 1 && tag[0] == "p" {
+ self.friends[tag[1]] = ()
+ }
+ }
+ }
}
func handle_metadata_event(_ ev: NostrEvent) {
@@ -127,12 +171,12 @@ struct ContentView: View {
profile_filter.since = prof_since
}
- let filters = [since_filter, profile_filter]
+ var contacts_filter = NostrFilter.filter_contacts
+ contacts_filter.authors = [self.pubkey]
+
+ let filters = [since_filter, profile_filter, contacts_filter]
print("connected to \(relay_id), refreshing from \(since)")
- let sub_id = self.sub_id ?? UUID().description
- if self.sub_id != sub_id {
- self.sub_id = sub_id
- }
+ let sub_id = UUID().description
print("subscribing to \(sub_id)")
self.pool?.send(.subscribe(.init(filters: filters, sub_id: sub_id)))
}
@@ -161,7 +205,6 @@ struct ContentView: View {
if self.loading {
self.loading = false
}
- self.sub_id = sub_id
if has_events[ev.id] == nil {
has_events[ev.id] = ()
@@ -213,7 +256,7 @@ func get_metadata_since_time(_ metadata_event: NostrEvent?) -> Int64? {
func get_since_time(last_event: NostrEvent?) -> Int64 {
if last_event == nil {
- return Int64(Date().timeIntervalSince1970) - (24 * 60 * 60 * 3)
+ return Int64(Date().timeIntervalSince1970) - (24 * 60 * 60 * 4)
}
return last_event!.created_at - 60 * 10
diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift
@@ -115,7 +115,10 @@ func decode_data<T: Decodable>(_ data: Data) -> T? {
}
func event_commitment(ev: NostrEvent, tags: String) -> String {
- return "[0,\"\(ev.pubkey)\",\(ev.created_at),\(ev.kind),\(tags),\"\(ev.content)\"]"
+ let encoder = JSONEncoder()
+ let str_data = try! encoder.encode(ev.content)
+ let content = String(decoding: str_data, as: UTF8.self)
+ return "[0,\"\(ev.pubkey)\",\(ev.created_at),\(ev.kind),\(tags),\(content)]"
}
func calculate_event_id(ev: NostrEvent) -> String {
diff --git a/damus/Nostr/NostrFilter.swift b/damus/Nostr/NostrFilter.swift
@@ -27,11 +27,19 @@ struct NostrFilter: Codable {
}
public static var filter_text: NostrFilter {
- NostrFilter(ids: nil, kinds: [1], referenced_ids: nil, pubkeys: nil, since: nil, until: nil, authors: nil)
+ return filter_kinds([1])
}
public static var filter_profiles: NostrFilter {
- return NostrFilter(ids: nil, kinds: [0], referenced_ids: nil, pubkeys: nil, since: nil, until: nil, authors: nil)
+ return filter_kinds([0])
+ }
+
+ public static var filter_contacts: NostrFilter {
+ return filter_kinds([3])
+ }
+
+ public static func filter_kinds(_ kinds: [Int]) -> NostrFilter {
+ return NostrFilter(ids: nil, kinds: kinds, referenced_ids: nil, pubkeys: nil, since: nil, until: nil, authors: nil)
}
public static func filter_since(_ val: Int64) -> NostrFilter {
diff --git a/damus/Nostr/NostrTimeline.swift b/damus/Nostr/NostrTimeline.swift
@@ -0,0 +1,8 @@
+//
+// NostrTimeline.swift
+// damus
+//
+// Created by William Casarin on 2022-04-12.
+//
+
+import Foundation
diff --git a/damus/Nostr/RelayConnection.swift b/damus/Nostr/RelayConnection.swift
@@ -84,7 +84,9 @@ func make_nostr_push_event(ev: NostrEvent) -> String? {
let encoder = JSONEncoder()
let event_data = try! encoder.encode(ev)
let event = String(decoding: event_data, as: UTF8.self)
- return "[\"EVENT\",\(event)]"
+ let encoded = "[\"EVENT\",\(event)]"
+ print(encoded)
+ return encoded
}
func make_nostr_subscription_req(_ filters: [NostrFilter], sub_id: String) -> String? {