RelayDetailView.swift (8598B)
1 // 2 // RelayDetailView.swift 3 // damus 4 // 5 // Created by Joel Klabo on 2/1/23. 6 // 7 8 import SwiftUI 9 10 struct RelayDetailView: View { 11 let state: DamusState 12 let relay: RelayURL 13 let nip11: RelayMetadata? 14 15 @ObservedObject var log: RelayLog 16 17 @Environment(\.dismiss) var dismiss 18 19 init(state: DamusState, relay: RelayURL, nip11: RelayMetadata?) { 20 self.state = state 21 self.relay = relay 22 self.nip11 = nip11 23 24 log = state.relay_model_cache.model(with_relay_id: relay)?.log ?? RelayLog() 25 } 26 27 func check_connection() -> Bool { 28 for relay in state.pool.relays { 29 if relay.id == self.relay { 30 return true 31 } 32 } 33 return false 34 } 35 36 func RemoveRelayButton(_ keypair: FullKeypair) -> some View { 37 Button(action: { 38 guard let ev = state.contacts.event else { 39 return 40 } 41 42 let descriptors = state.pool.our_descriptors 43 guard let new_ev = remove_relay( ev: ev, current_relays: descriptors, keypair: keypair, relay: relay) else { 44 return 45 } 46 47 process_contact_event(state: state, ev: new_ev) 48 state.postbox.send(new_ev) 49 50 if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) { 51 state.postbox.send(relay_metadata) 52 } 53 dismiss() 54 }) { 55 HStack { 56 Text("Disconnect", comment: "Button to disconnect from the relay.") 57 .fontWeight(.semibold) 58 } 59 .frame(minWidth: 300, maxWidth: .infinity, alignment: .center) 60 } 61 .buttonStyle(NeutralButtonShape.rounded.style) 62 } 63 64 func ConnectRelayButton(_ keypair: FullKeypair) -> some View { 65 Button(action: { 66 guard let ev_before_add = state.contacts.event else { 67 return 68 } 69 guard let ev_after_add = add_relay(ev: ev_before_add, keypair: keypair, current_relays: state.pool.our_descriptors, relay: relay, info: .rw) else { 70 return 71 } 72 process_contact_event(state: state, ev: ev_after_add) 73 state.postbox.send(ev_after_add) 74 75 if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) { 76 state.postbox.send(relay_metadata) 77 } 78 dismiss() 79 }) { 80 HStack { 81 Text("Connect", comment: "Button to connect to the relay.") 82 .fontWeight(.semibold) 83 } 84 .frame(minWidth: 300, maxWidth: .infinity, alignment: .center) 85 } 86 .buttonStyle(NeutralButtonShape.rounded.style) 87 } 88 89 var RelayInfo: some View { 90 ScrollView(.horizontal) { 91 Group { 92 HStack(spacing: 15) { 93 94 RelayAdminDetail(state: state, nip11: nip11) 95 96 Divider().frame(width: 1) 97 98 RelaySoftwareDetail(nip11: nip11) 99 100 } 101 } 102 } 103 .scrollIndicators(.hidden) 104 } 105 106 var RelayHeader: some View { 107 HStack(alignment: .top, spacing: 15) { 108 RelayPicView(relay: relay, icon: nip11?.icon, size: 90, highlight: .none, disable_animation: false) 109 110 VStack(alignment: .leading) { 111 Text(nip11?.name ?? relay.absoluteString) 112 .font(.title) 113 .fontWeight(.bold) 114 .lineLimit(1) 115 116 Text(relay.absoluteString) 117 .font(.headline) 118 .fontWeight(.regular) 119 .foregroundColor(.gray) 120 121 HStack { 122 if nip11?.is_paid ?? false { 123 RelayPaidDetail(payments_url: nip11?.payments_url, fees: nip11?.fees) 124 } 125 126 if let authentication_state: RelayAuthenticationState = relay_object?.authentication_state, 127 authentication_state != .none { 128 RelayAuthenticationDetail(state: authentication_state) 129 } 130 } 131 } 132 } 133 } 134 135 136 var body: some View { 137 NavigationView { 138 Group { 139 ScrollView { 140 Divider() 141 VStack(alignment: .leading, spacing: 10) { 142 143 RelayHeader 144 145 Divider() 146 147 Text("Description", comment: "Description of the specific Nostr relay server.") 148 .font(.subheadline) 149 .foregroundColor(DamusColors.mediumGrey) 150 151 if let description = nip11?.description, !description.isEmpty { 152 Text(description) 153 .font(.subheadline) 154 } else { 155 Text("N/A", comment: "Text label indicating that there is no NIP-11 relay description information found. In English, N/A stands for not applicable.") 156 .font(.subheadline) 157 } 158 159 Divider() 160 161 RelayInfo 162 163 Divider() 164 165 if let nip11 { 166 if let nips = nip11.supported_nips, nips.count > 0 { 167 RelayNipList(nips: nips) 168 Divider() 169 } 170 } 171 172 if let keypair = state.keypair.to_full() { 173 if check_connection() { 174 RemoveRelayButton(keypair) 175 .padding(.top) 176 } else { 177 ConnectRelayButton(keypair) 178 .padding(.top) 179 } 180 } 181 182 if state.settings.developer_mode { 183 Text("Relay Logs", comment: "Text label indicating that the text below it are developer mode logs.") 184 .padding(.top) 185 Divider() 186 Text(log.contents ?? NSLocalizedString("No logs to display", comment: "Label to indicate that there are no developer mode logs available to be displayed on the screen")) 187 .font(.system(size: 13)) 188 .lineLimit(nil) 189 .fixedSize(horizontal: false, vertical: true) 190 } 191 } 192 .padding(.horizontal) 193 } 194 } 195 } 196 .onReceive(handle_notify(.switched_timeline)) { notif in 197 dismiss() 198 } 199 .navigationTitle(nip11?.name ?? relay.absoluteString) 200 .navigationBarTitleDisplayMode(.inline) 201 .navigationBarBackButtonHidden(true) 202 .navigationBarItems(leading: BackNav()) 203 .ignoresSafeArea(.all) 204 .toolbar { 205 if let relay_connection { 206 RelayStatusView(connection: relay_connection) 207 } 208 } 209 } 210 211 private var relay_object: Relay? { 212 state.pool.get_relay(relay) 213 } 214 215 private var relay_connection: RelayConnection? { 216 relay_object?.connection 217 } 218 } 219 220 struct RelayDetailView_Previews: PreviewProvider { 221 static var previews: some View { 222 let admission = Admission(amount: 1000000, unit: "msats") 223 let sub = Subscription(amount: 5000000, unit: "msats", period: 2592000) 224 let pub = Publication(kinds: [4], amount: 100, unit: "msats") 225 let fees = Fees(admission: [admission], subscription: [sub], publication: [pub]) 226 let metadata = RelayMetadata(name: "name", description: "Relay description", pubkey: test_pubkey, contact: "contact@mail.com", supported_nips: [1,2,3], software: "software", version: "version", limitation: Limitations.empty, payments_url: "https://jb55.com", icon: "", fees: fees) 227 RelayDetailView(state: test_damus_state, relay: RelayURL("wss://relay.damus.io")!, nip11: metadata) 228 } 229 }