RelayView.swift (6853B)
1 // 2 // RelayView.swift 3 // damus 4 // 5 // Created by William Casarin on 2022-10-16. 6 // 7 8 import SwiftUI 9 10 struct RelayView: View { 11 let state: DamusState 12 let relay: RelayURL 13 let recommended: Bool 14 @ObservedObject private var model_cache: RelayModelCache 15 16 @State var relay_state: Bool 17 @Binding var showActionButtons: Bool 18 19 init(state: DamusState, relay: RelayURL, showActionButtons: Binding<Bool>, recommended: Bool) { 20 self.state = state 21 self.relay = relay 22 self.recommended = recommended 23 self.model_cache = state.relay_model_cache 24 _showActionButtons = showActionButtons 25 let relay_state = RelayView.get_relay_state(pool: state.pool, relay: relay) 26 self._relay_state = State(initialValue: relay_state) 27 } 28 29 static func get_relay_state(pool: RelayPool, relay: RelayURL) -> Bool { 30 return pool.get_relay(relay) == nil 31 } 32 33 var body: some View { 34 Group { 35 HStack { 36 if let privkey = state.keypair.privkey { 37 if showActionButtons && !recommended { 38 RemoveButton(privkey: privkey, showText: false) 39 } 40 } 41 42 let meta = model_cache.model(with_relay_id: relay)?.metadata 43 44 RelayPicView(relay: relay, icon: meta?.icon, size: 55, highlight: .none, disable_animation: false) 45 46 VStack(alignment: .leading) { 47 HStack { 48 Text(meta?.name ?? relay.url.host() ?? relay.url.absoluteString) 49 .font(.headline) 50 .padding(.bottom, 2) 51 .lineLimit(1) 52 RelayType(is_paid: state.relay_model_cache.model(with_relay_id: relay)?.metadata.is_paid ?? false) 53 } 54 Text(relay.absoluteString) 55 .font(.subheadline) 56 .foregroundColor(.gray) 57 .lineLimit(1) 58 .contextMenu { 59 CopyAction(relay: relay.absoluteString) 60 61 if let privkey = state.keypair.privkey { 62 RemoveButton(privkey: privkey, showText: true) 63 } 64 } 65 } 66 67 Spacer() 68 69 if recommended { 70 if let keypair = state.keypair.to_full() { 71 VStack(alignment: .center) { 72 if relay_state { 73 AddButton(keypair: keypair) 74 } else { 75 Button(action: { 76 remove_action(privkey: keypair.privkey) 77 }) { 78 Text("Added", comment: "Button to show relay server is already added to list.") 79 .font(.caption) 80 } 81 .buttonStyle(NeutralButtonShape.capsule.style) 82 .opacity(0.5) 83 } 84 } 85 .padding(.horizontal, 5) 86 } 87 } else { 88 if let relay_connection { 89 RelayStatusView(connection: relay_connection) 90 } 91 92 Image("chevron-large-right") 93 .resizable() 94 .frame(width: 15, height: 15) 95 .foregroundColor(.gray) 96 } 97 } 98 .contentShape(Rectangle()) 99 } 100 .onReceive(handle_notify(.relays_changed)) { _ in 101 self.relay_state = RelayView.get_relay_state(pool: state.pool, relay: self.relay) 102 } 103 .onTapGesture { 104 state.nav.push(route: Route.RelayDetail(relay: relay, metadata: model_cache.model(with_relay_id: relay)?.metadata)) 105 } 106 } 107 108 private var relay_connection: RelayConnection? { 109 state.pool.get_relay(relay)?.connection 110 } 111 112 func add_action(keypair: FullKeypair) { 113 guard let ev_before_add = state.contacts.event else { 114 return 115 } 116 guard let ev_after_add = add_relay(ev: ev_before_add, keypair: keypair, current_relays: state.pool.our_descriptors, relay: relay, info: .rw) else { 117 return 118 } 119 process_contact_event(state: state, ev: ev_after_add) 120 state.postbox.send(ev_after_add) 121 122 if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) { 123 state.postbox.send(relay_metadata) 124 } 125 } 126 127 func remove_action(privkey: Privkey) { 128 guard let ev = state.contacts.event else { 129 return 130 } 131 132 let descriptors = state.pool.our_descriptors 133 guard let keypair = state.keypair.to_full(), 134 let new_ev = remove_relay(ev: ev, current_relays: descriptors, keypair: keypair, relay: relay) else { 135 return 136 } 137 138 process_contact_event(state: state, ev: new_ev) 139 state.postbox.send(new_ev) 140 141 if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) { 142 state.postbox.send(relay_metadata) 143 } 144 } 145 146 func AddButton(keypair: FullKeypair) -> some View { 147 Button(action: { 148 add_action(keypair: keypair) 149 }) { 150 Text("Add", comment: "Button to add relay server to list.") 151 .font(.caption) 152 } 153 .buttonStyle(NeutralButtonShape.capsule.style) 154 } 155 156 func CopyAction(relay: String) -> some View { 157 Button { 158 UIPasteboard.general.setValue(relay, forPasteboardType: "public.plain-text") 159 } label: { 160 Label(NSLocalizedString("Copy", comment: "Button to copy a relay server address."), image: "copy2") 161 } 162 } 163 164 func RemoveButton(privkey: Privkey, showText: Bool) -> some View { 165 Button(action: { 166 remove_action(privkey: privkey) 167 }) { 168 if showText { 169 Text("Disconnect", comment: "Button to disconnect from a relay server.") 170 } 171 172 Image("minus-circle") 173 .resizable() 174 .frame(width: 20, height: 20) 175 .foregroundColor(.red) 176 .padding(.leading, 5) 177 } 178 } 179 } 180 181 struct RelayView_Previews: PreviewProvider { 182 static var previews: some View { 183 RelayView(state: test_damus_state, relay: RelayURL("wss://relay.damus.io")!, showActionButtons: .constant(false), recommended: false) 184 } 185 }