damus

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

BroadcastToRelaysView.swift (5109B)


      1 //
      2 //  BroadcastToRelaysView.swift
      3 //  damus
      4 //
      5 //  Created by devandsev on 2/4/23.
      6 //
      7 
      8 import SwiftUI
      9 
     10 extension BroadcastToRelaysView {
     11     
     12     class ViewState: ObservableObject {
     13         let damusState: DamusState
     14         @Published var relayRows: [RowState] = []
     15         
     16         var hasExcludedRelays: Bool { relayRows.contains { !$0.isSelected } }
     17         var selectedRelays: [RelayDescriptor] { relayRows.filter { $0.isSelected }.map { $0.relay } }
     18         var limitingRelayIds: [String]? {
     19             guard hasExcludedRelays else {
     20                 return nil
     21             }
     22             return selectedRelays.map { get_relay_id($0.url) }
     23         }
     24         
     25         init(state: DamusState) {
     26             damusState = state
     27             relayRows = state.pool.descriptors.map { RowState(relay: $0, isSelected: true) }
     28         }
     29     }
     30     
     31     struct RowState: Equatable {
     32         let relay: RelayDescriptor
     33         var isSelected: Bool
     34     }
     35 }
     36 
     37 /// A list of relays you can select to send your event to
     38 ///
     39 /// Can be presented in 2 modes:
     40 /// - If `broadCastEvent` is nil, user selects relays, goes to the previous screen and the post/reply will be sent to selected relays only. Presented in this mode from `PostView` and `ReplyView` by tapping relays button.
     41 /// - If `broadCastEvent` is not nil, there will be a "Broadcast" button in the navBar to broadcast this event to selected relays. Presented in this mode by long-pressing a post and choosing "Broadcast".
     42 struct BroadcastToRelaysView: View {
     43     @ObservedObject var state: ViewState
     44    
     45     let broadCastEvent: NostrEvent? 
     46     
     47     @Environment(\.presentationMode) var presentationMode
     48     
     49     func selectAll() {
     50         $state.relayRows.forEach { $0.wrappedValue.isSelected = true }
     51     }
     52     
     53     func selectOne() {
     54         guard let firstSelectedRow = $state.relayRows.first(where: { $0.wrappedValue.isSelected }) else {
     55             $state.relayRows.forEach { $0.wrappedValue.isSelected = false }
     56             $state.relayRows.first?.wrappedValue.isSelected = true
     57             return
     58         }
     59         
     60         $state.relayRows.forEach { $0.wrappedValue.isSelected = false }
     61         firstSelectedRow.wrappedValue.isSelected = true
     62     }
     63     
     64     func dismiss() {
     65         self.presentationMode.wrappedValue.dismiss()
     66     }
     67     
     68     var body: some View {
     69         NavigationView {
     70             Form {
     71                 Section {
     72                     List(Array($state.relayRows), id: \.wrappedValue.relay.url) { $relayRow in
     73                         SelectableRowView(isSelected: $relayRow.isSelected,
     74                                           shouldChangeSelection: {
     75                             return !relayRow.isSelected || $state.relayRows.filter { $0.wrappedValue.isSelected }.count > 1
     76                             
     77                         } ) {
     78                             RelayView(state: state.damusState, relay: relayRow.relay.url.absoluteString)
     79                         }
     80                     }
     81                 }
     82                 header: {
     83                     HStack {
     84                         Text("Relays to send to", comment: "Section header text for relay server list. On this screen user can select to which specific relays the post should be sent.")
     85                         Spacer()
     86                         Button(NSLocalizedString("All", comment: "Button to select all relays in the list to which the post will be sent")) {
     87                             self.selectAll()
     88                         }
     89                         .disabled(!state.hasExcludedRelays)
     90                         Button(NSLocalizedString("One", comment: "Button to select only one relay from the list to which the post will be sent")) {
     91                             self.selectOne()
     92                         }
     93                         .disabled(state.selectedRelays.count == 1)
     94                     }
     95                     .buttonStyle(.bordered)
     96                 }
     97             }
     98             .toolbar {
     99                 ToolbarItem(placement: .navigationBarLeading) {
    100                     if broadCastEvent != nil {
    101                         Button(action: {
    102                             dismiss()
    103                         }) {
    104                             Text("Cancel", comment: "Navigation bar button to cancel broadcasting the user's note to all of the user's connected relay servers.")
    105                         }.foregroundColor(.primary)
    106                     }
    107                 }
    108                 ToolbarItem(placement: .navigationBarTrailing) {
    109                     if broadCastEvent != nil {
    110                         Button(action: {
    111                             if let broadCastEvent = broadCastEvent {
    112                                 state.damusState.pool.send(.event(broadCastEvent), to: state.limitingRelayIds)
    113                                 dismiss()
    114                             }
    115                         }) {
    116                             Text("Broadcast", comment: "Navigation bar button to confirm broadcasting the user's note to all of the user's connected relay servers.")
    117                         }
    118                     }
    119                 }
    120             }
    121         }
    122     }
    123 }