RelayDetailView.swift (8111B)
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") 148 .font(.subheadline) 149 .foregroundColor(DamusColors.mediumGrey) 150 151 Text(nip11?.description ?? "N/A") 152 .font(.subheadline) 153 154 Divider() 155 156 RelayInfo 157 158 Divider() 159 160 if let nip11 { 161 if let nips = nip11.supported_nips, nips.count > 0 { 162 RelayNipList(nips: nips) 163 Divider() 164 } 165 } 166 167 if let keypair = state.keypair.to_full() { 168 if check_connection() { 169 RemoveRelayButton(keypair) 170 .padding(.top) 171 } else { 172 ConnectRelayButton(keypair) 173 .padding(.top) 174 } 175 } 176 177 if state.settings.developer_mode { 178 Text("Relay Logs") 179 .padding(.top) 180 Divider() 181 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")) 182 .font(.system(size: 13)) 183 .lineLimit(nil) 184 .fixedSize(horizontal: false, vertical: true) 185 } 186 } 187 .padding(.horizontal) 188 } 189 } 190 } 191 .onReceive(handle_notify(.switched_timeline)) { notif in 192 dismiss() 193 } 194 .navigationTitle(nip11?.name ?? relay.absoluteString) 195 .navigationBarTitleDisplayMode(.inline) 196 .navigationBarBackButtonHidden(true) 197 .navigationBarItems(leading: BackNav()) 198 .ignoresSafeArea(.all) 199 .toolbar { 200 if let relay_connection { 201 RelayStatusView(connection: relay_connection) 202 } 203 } 204 } 205 206 private var relay_object: Relay? { 207 state.pool.get_relay(relay) 208 } 209 210 private var relay_connection: RelayConnection? { 211 relay_object?.connection 212 } 213 } 214 215 struct RelayDetailView_Previews: PreviewProvider { 216 static var previews: some View { 217 let admission = Admission(amount: 1000000, unit: "msats") 218 let sub = Subscription(amount: 5000000, unit: "msats", period: 2592000) 219 let pub = Publication(kinds: [4], amount: 100, unit: "msats") 220 let fees = Fees(admission: [admission], subscription: [sub], publication: [pub]) 221 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) 222 RelayDetailView(state: test_damus_state, relay: RelayURL("wss://relay.damus.io")!, nip11: metadata) 223 } 224 }