damus

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

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 }