damus

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

AddRelayView.swift (6268B)


      1 //
      2 //  AddRelayView.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2022-06-09.
      6 //
      7 
      8 import SwiftUI
      9 
     10 struct AddRelayView: View {
     11     let state: DamusState
     12     @State var new_relay: String = ""
     13     @State var relayAddErrorTitle: String? = nil
     14     @State var relayAddErrorMessage: String? = nil
     15     
     16     @Environment(\.dismiss) var dismiss
     17     
     18     var body: some View {
     19         VStack {
     20             Text("Add relay", comment: "Title text to indicate user to an add a relay.")
     21                 .font(.system(size: 20, weight: .bold))
     22                 .padding(.vertical)
     23             
     24             Divider()
     25                 .padding(.bottom)
     26             
     27             HStack {
     28                 Label("", image: "copy2")
     29                     .onTapGesture {
     30                     if let pastedrelay = UIPasteboard.general.string {
     31                         self.new_relay = pastedrelay
     32                     }
     33                 }
     34                 TextField(NSLocalizedString("wss://some.relay.com", comment: "Placeholder example for relay server address."), text: $new_relay)
     35                     .autocorrectionDisabled(true)
     36                     .textInputAutocapitalization(.never)
     37                 
     38                 Label("", image: "close-circle")
     39                     .foregroundColor(.accentColor)
     40                     .opacity((new_relay == "") ? 0.0 : 1.0)
     41                     .onTapGesture {
     42                         self.new_relay = ""
     43                     }
     44             }
     45             .padding(10)
     46             .background(.secondary.opacity(0.2))
     47             .cornerRadius(10)
     48             
     49             if let errorMessage = relayAddErrorMessage {
     50                 VStack(spacing: 0) {
     51                     HStack(alignment: .top) {
     52                         Text(relayAddErrorTitle ?? "Error")
     53                             .bold()
     54                             .foregroundColor(DamusColors.dangerSecondary)
     55                             .padding(.leading)
     56                         Spacer()
     57                         Button(action: {
     58                             relayAddErrorTitle = nil      // Clear error title
     59                             relayAddErrorMessage = nil    // Clear error message
     60                             self.new_relay = ""
     61                         }, label: {
     62                             Image("close")
     63                                 .frame(width: 20, height: 20)
     64                                 .foregroundColor(DamusColors.dangerSecondary)
     65                         })
     66                         .padding(.trailing)
     67                     }
     68                     
     69                     Text(errorMessage)
     70                         .foregroundColor(DamusColors.dangerSecondary)
     71                         .padding(.top, 10)
     72                 }
     73                 .frame(minWidth: 300, maxWidth: .infinity, minHeight: 120, alignment: .center)
     74                 .background {
     75                     RoundedRectangle(cornerRadius: 12)
     76                         .fill(DamusColors.dangerBorder, strokeBorder: .gray.opacity(0.5), lineWidth: 1)
     77                 }
     78             }
     79             
     80             Button(action: {
     81                 if new_relay.starts(with: "wss://") == false && new_relay.starts(with: "ws://") == false {
     82                     new_relay = "wss://" + new_relay
     83                 }
     84 
     85                 guard let url = RelayURL(new_relay),
     86                       let ev = state.contacts.event,
     87                       let keypair = state.keypair.to_full() else {
     88                     return
     89                 }
     90 
     91                 let info = RelayInfo.rw
     92                 let descriptor = RelayDescriptor(url: url, info: info)
     93 
     94                 do {
     95                     try state.pool.add_relay(descriptor)
     96                     relayAddErrorTitle = nil      // Clear error title
     97                     relayAddErrorMessage = nil    // Clear error message
     98                 } catch RelayError.RelayAlreadyExists {
     99                     relayAddErrorTitle = NSLocalizedString("Duplicate relay", comment: "Title of the duplicate relay error message.")
    100                     relayAddErrorMessage = NSLocalizedString("The relay you are trying to add is already added.\nYou're all set!", comment: "An error message that appears when the user attempts to add a relay that has already been added.")
    101                     return
    102                 } catch {
    103                     return
    104                 }
    105 
    106                 state.pool.connect(to: [url])
    107 
    108                 if let new_ev = add_relay(ev: ev, keypair: keypair, current_relays: state.pool.our_descriptors, relay: url, info: info) {
    109                     process_contact_event(state: state, ev: ev)
    110 
    111                     state.pool.send(.event(new_ev))
    112                 }
    113 
    114                 if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) {
    115                     state.postbox.send(relay_metadata)
    116                 }
    117                 new_relay = ""
    118 
    119                 UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    120                 
    121                 dismiss()
    122             }) {
    123                 HStack {
    124                     Text(verbatim: "Add relay")
    125                         .bold()
    126                 }
    127                 .frame(minWidth: 300, maxWidth: .infinity, alignment: .center)
    128             }
    129             .buttonStyle(GradientButtonStyle(padding: 10))
    130             //.disabled(!new_relay.isValidURL) <--- TODO
    131             .padding(.vertical)
    132             
    133             Spacer()
    134         }
    135         .padding()
    136     }
    137 }
    138 
    139 // TODO
    140 // This works sometimes, in certain cases where the relay is valid it won't allow the user to add it
    141 // Needs improvement
    142 extension String {
    143     var isValidURL: Bool {
    144         let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
    145         if let match = detector.firstMatch(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count)) {
    146             // it is a link, if the match covers the whole string
    147             return match.range.length == self.utf16.count
    148         } else {
    149             return false
    150         }
    151     }
    152 }
    153 
    154 struct AddRelayView_Previews: PreviewProvider {
    155     @State static var relay: String = ""
    156     
    157     static var previews: some View {
    158         AddRelayView(state: test_damus_state)
    159     }
    160 }