damus

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

commit 14a3a352d6e31d6b0143efd3032391fc9c0e44d4
parent 3824e95f296719fd8cf8a266f89e163cfce15cc4
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 29 Dec 2022 16:08:00 -0800

Recommended relay view

Changelog-Changed: Show recommended relays in config. Currently just a fixed set.

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 4++++
Mdamus/ContentView.swift | 1+
Mdamus/Models/Contacts.swift | 6+++---
Mdamus/Models/HomeModel.swift | 23-----------------------
Mdamus/Views/ConfigView.swift | 31+++++++++++++++++++++++++++----
Adamus/Views/RecommendedRelayView.swift | 37+++++++++++++++++++++++++++++++++++++
Mdamus/Views/RelayView.swift | 45+++++++++++++++++++++++++++++----------------
7 files changed, 101 insertions(+), 46 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -109,6 +109,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 */; }; + 4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB55EF2295E5D59007FD187 /* RecommendedRelayView.swift */; }; 4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD7641A28A1641400B6928F /* EndBlock.swift */; }; 4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F8CC281352B30009DFBB /* Notifications.swift */; }; 4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */; }; @@ -288,6 +289,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>"; }; + 4CB55EF2295E5D59007FD187 /* RecommendedRelayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendedRelayView.swift; sourceTree = "<group>"; }; 4CD7641A28A1641400B6928F /* EndBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndBlock.swift; sourceTree = "<group>"; }; 4CE4F8CC281352B30009DFBB /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; }; 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigView.swift; sourceTree = "<group>"; }; @@ -486,6 +488,7 @@ E990020E2955F837003BBC5A /* EditMetadataView.swift */, BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */, E9E4ED0A295867B900DD7078 /* ThreadV2View.swift */, + 4CB55EF2295E5D59007FD187 /* RecommendedRelayView.swift */, ); path = Views; sourceTree = "<group>"; @@ -860,6 +863,7 @@ 4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */, 4C3AC79B28306D7B00E1F516 /* Contacts.swift in Sources */, 4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */, + 4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */, 4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */, 4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */, 4C363A8E28236FE4006E126D /* NoteContentView.swift in Sources */, diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -16,6 +16,7 @@ var BOOTSTRAP_RELAYS = [ "wss://relay.nostr.bg", "wss://nostr.oxtr.dev", "wss://nostr.v0l.io", + "wss://nostr-2.zebedee.cloud", ] struct TimestampedProfile { diff --git a/damus/Models/Contacts.swift b/damus/Models/Contacts.swift @@ -144,6 +144,7 @@ func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], privkey: St relays.removeValue(forKey: relay) + print("remove_relay \(relays)") guard let content = encode_json(relays) else { return nil } @@ -154,10 +155,9 @@ func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], privkey: St return new_ev } -func add_relay(ev: NostrEvent, privkey: String, relay: String, info: RelayInfo) -> NostrEvent? { - let damus_relay = RelayDescriptor(url: URL(string: "wss://relay.damus.io")!, info: .rw) +func add_relay(ev: NostrEvent, privkey: String, current_relays: [RelayDescriptor], relay: String, info: RelayInfo) -> NostrEvent? { + var relays = ensure_relay_info(relays: current_relays, content: ev.content) - var relays = ensure_relay_info(relays: [damus_relay], content: ev.content) guard relays.index(forKey: relay) == nil else { return nil } diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -623,26 +623,3 @@ func load_our_relays(contacts: Contacts, our_pubkey: String, pool: RelayPool, m_ } -func remove_bootstrap_nodes(_ damus_state: DamusState) { - guard let contacts = damus_state.contacts.event else { - return - } - - guard let relays = decode_json_relays(contacts.content) else { - return - } - - let descriptors = relays.reduce(into: []) { arr, kv in - guard let url = URL(string: kv.key) else { - return - } - arr.append(RelayDescriptor(url: url, info: kv.value)) - } - - for relay in BOOTSTRAP_RELAYS { - if !(descriptors.contains { ($0 as! RelayDescriptor).url.absoluteString == relay }) { - damus_state.pool.remove_relay(relay) - } - } -} - diff --git a/damus/Views/ConfigView.swift b/damus/Views/ConfigView.swift @@ -18,11 +18,14 @@ struct ConfigView: View { @State var privkey_copied: Bool = false @State var pubkey_copied: Bool = false + @State var relays: [RelayDescriptor] + let generator = UIImpactFeedbackGenerator(style: .light) init(state: DamusState) { self.state = state _privkey = State(initialValue: self.state.keypair.privkey_bech32 ?? "") + _relays = State(initialValue: state.pool.descriptors) } // TODO: (jb55) could be more general but not gonna worry about it atm @@ -38,12 +41,28 @@ struct ConfigView: View { } } + var recommended: [RelayDescriptor] { + let rs: [RelayDescriptor] = [] + return BOOTSTRAP_RELAYS.reduce(into: rs) { (xs, x) in + if let _ = state.pool.get_relay(x) { + } else { + xs.append(RelayDescriptor(url: URL(string: x)!, info: .rw)) + } + } + } + var body: some View { ZStack(alignment: .leading) { Form { Section("Relays") { - List(Array(state.pool.relays), id: \.descriptor.url) { relay in - RelayView(state: state, relay: relay.descriptor.url.absoluteString) + List(Array(relays), id: \.url) { relay in + RelayView(state: state, relay: relay.url.absoluteString) + } + } + + Section("Recommended Relays") { + List(recommended, id: \.url) { r in + RecommendedRelayView(damus: state, relay: r.url.absoluteString) } } @@ -133,17 +152,21 @@ struct ConfigView: View { state.pool.connect(to: [new_relay]) - guard let new_ev = add_relay(ev: ev, privkey: privkey, relay: new_relay, info: info) else { + guard let new_ev = add_relay(ev: ev, privkey: privkey, current_relays: state.pool.descriptors, relay: new_relay, info: info) else { return } - state.contacts.event = new_ev + process_contact_event(pool: state.pool, contacts: state.contacts, pubkey: state.pubkey, ev: ev) + state.pool.send(.event(new_ev)) } } .onReceive(handle_notify(.switched_timeline)) { _ in dismiss() } + .onReceive(handle_notify(.relays_changed)) { _ in + self.relays = state.pool.descriptors + } } } diff --git a/damus/Views/RecommendedRelayView.swift b/damus/Views/RecommendedRelayView.swift @@ -0,0 +1,37 @@ +// +// RecommendedRelayView.swift +// damus +// +// Created by William Casarin on 2022-12-29. +// + +import SwiftUI + +struct RecommendedRelayView: View { + let damus: DamusState + let relay: String + + var body: some View { + HStack { + Text(relay) + Spacer() + if let ev = damus.contacts.event { + if let privkey = damus.keypair.privkey { + Button("Add") { + guard let ev = add_relay(ev: ev, privkey: privkey, current_relays: damus.pool.descriptors, relay: relay, info: .rw) else { + return + } + process_contact_event(pool: damus.pool, contacts: damus.contacts, pubkey: damus.pubkey, ev: ev) + damus.pool.send(.event(ev)) + } + } + } + } + } +} + +struct RecommendedRelayView_Previews: PreviewProvider { + static var previews: some View { + RecommendedRelayView(damus: test_damus_state(), relay: "wss://relay.damus.io") + } +} diff --git a/damus/Views/RelayView.swift b/damus/Views/RelayView.swift @@ -44,28 +44,41 @@ struct RelayView: View { } .swipeActions { if let privkey = state.keypair.privkey { - Button { - guard let ev = state.contacts.event else { - return - } - - let descriptors = state.pool.descriptors - guard let new_ev = remove_relay( ev: ev, current_relays: descriptors, privkey: privkey, relay: relay) else { - return - } - - state.contacts.event = new_ev - state.pool.send(.event(new_ev)) - } label: { - Label("Delete", systemImage: "trash") - } - .tint(.red) + RemoveAction(privkey: privkey) + } + } + .contextMenu { + if let privkey = state.keypair.privkey { + RemoveAction(privkey: privkey) + } + } + } + + func RemoveAction(privkey: String) -> some View { + Button { + guard let ev = state.contacts.event else { + return + } + + let descriptors = state.pool.descriptors + guard let new_ev = remove_relay( ev: ev, current_relays: descriptors, privkey: privkey, relay: relay) else { + return } + + process_contact_event(pool: state.pool, contacts: state.contacts, pubkey: state.pubkey, ev: new_ev) + state.pool.send(.event(new_ev)) + } label: { + Label("Delete", systemImage: "trash") } + .tint(.red) } } +fileprivate func remove_action() { + +} + struct RelayView_Previews: PreviewProvider { static var previews: some View { RelayView(state: test_damus_state(), relay: "wss://relay.damus.io", conn_color: .red)