damus

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

CreateAccountView.swift (6701B)


      1 //
      2 //  CreateAccountView.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2022-05-20.
      6 //
      7 
      8 import SwiftUI
      9 
     10 struct CreateAccountView: View {
     11     @StateObject var account: CreateAccountModel = CreateAccountModel()
     12     @StateObject var profileUploadObserver = ImageUploadingObserver()
     13     var nav: NavigationCoordinator
     14     
     15     func SignupForm<FormContent: View>(@ViewBuilder content: () -> FormContent) -> some View {
     16         return VStack(alignment: .leading, spacing: 10.0, content: content)
     17     }
     18     
     19     func regen_key() {
     20         let keypair = generate_new_keypair()
     21         self.account.pubkey = keypair.pubkey
     22         self.account.privkey = keypair.privkey
     23     }
     24     
     25     var body: some View {
     26         ZStack(alignment: .top) {
     27             VStack {
     28                 VStack(alignment: .center) {
     29                     EditPictureControl(uploader: .nostrBuild, pubkey: account.pubkey, image_url: $account.profile_image , uploadObserver: profileUploadObserver, callback: uploadedProfilePicture)
     30 
     31                     Text(NSLocalizedString("Public Key", comment: "Label to indicate the public key of the account."))
     32                         .bold()
     33                         .padding()
     34                         .onTapGesture {
     35                             regen_key()
     36                         }
     37 
     38                     KeyText($account.pubkey)
     39                         .padding(.horizontal, 20)
     40                         .onTapGesture {
     41                             regen_key()
     42                         }
     43                 }
     44                 .frame(minWidth: 300, maxWidth: .infinity, minHeight: 250, alignment: .center)
     45                 .background {
     46                     RoundedRectangle(cornerRadius: 12)
     47                         .fill(DamusColors.adaptableGrey, strokeBorder: .gray.opacity(0.5), lineWidth: 1)
     48                 }
     49                 
     50                 SignupForm {
     51                     FormLabel(NSLocalizedString("Display name", comment: "Label to prompt display name entry."), optional: true)
     52                     FormTextInput(NSLocalizedString("Satoshi Nakamoto", comment: "Name of Bitcoin creator(s)."), text: $account.real_name)
     53                         .textInputAutocapitalization(.words)
     54 
     55                     FormLabel(NSLocalizedString("About", comment: "Label to prompt for about text entry for user to describe about themself."), optional: true)
     56                     FormTextInput(NSLocalizedString("Creator(s) of Bitcoin. Absolute legend.", comment: "Example description about Bitcoin creator(s), Satoshi Nakamoto."), text: $account.about)
     57                 }
     58                 .padding(.top, 10)
     59 
     60                 Button(action: {
     61                     nav.push(route: Route.SaveKeys(account: account))
     62                 }) {
     63                     HStack {
     64                         Text("Create account now", comment: "Button to create account.")
     65                             .fontWeight(.semibold)
     66                     }
     67                     .frame(minWidth: 300, maxWidth: .infinity, maxHeight: 12, alignment: .center)
     68                 }
     69                 .buttonStyle(GradientButtonStyle())
     70                 .disabled(profileUploadObserver.isLoading)
     71                 .opacity(profileUploadObserver.isLoading ? 0.5 : 1)
     72                 .padding(.top, 20)
     73                 
     74                 HStack(spacing: 0) {
     75                     Text("By signing up, you agree to our ", comment: "Ask the user if they already have an account on Nostr")
     76                         .font(.subheadline)
     77                         .foregroundColor(Color("DamusMediumGrey"))
     78 
     79                     Button(action: {
     80                         nav.push(route: Route.EULA)
     81                     }, label: {
     82                         Text("EULA")
     83                             .font(.subheadline)
     84                     })
     85                     .padding(.vertical, 5)
     86 
     87                     Spacer()
     88                 }
     89 
     90                 LoginPrompt()
     91                     .padding(.top)
     92                 
     93                 Spacer()
     94             }
     95             .padding()
     96         }
     97         .dismissKeyboardOnTap()
     98         .navigationTitle("Create account")
     99         .navigationBarTitleDisplayMode(.inline)
    100         .navigationBarBackButtonHidden(true)
    101         .navigationBarItems(leading: BackNav())
    102     }
    103     
    104     func uploadedProfilePicture(image_url: URL?) {
    105         account.profile_image = image_url
    106     }
    107 }
    108 
    109 struct LoginPrompt: View {
    110     @Environment(\.dismiss) var dismiss
    111     var body: some View {
    112         HStack {
    113             Text("Already on Nostr?", comment: "Ask the user if they already have an account on Nostr")
    114                 .foregroundColor(Color("DamusMediumGrey"))
    115 
    116             Button(NSLocalizedString("Login", comment: "Button to navigate to login view.")) {
    117                 self.dismiss()
    118             }
    119 
    120             Spacer()
    121         }
    122     }
    123 }
    124 
    125 struct BackNav: View {
    126     @Environment(\.dismiss) var dismiss
    127     var body: some View {
    128         Image("chevron-left")
    129             .foregroundColor(DamusColors.adaptableBlack)
    130         .onTapGesture {
    131             self.dismiss()
    132         }
    133     }
    134 }
    135 
    136 extension View {
    137     func placeholder<Content: View>(
    138         when shouldShow: Bool,
    139         alignment: Alignment = .leading,
    140         @ViewBuilder placeholder: () -> Content) -> some View {
    141 
    142         ZStack(alignment: alignment) {
    143             placeholder().opacity(shouldShow ? 1 : 0)
    144             self
    145         }
    146     }
    147 }
    148 
    149 struct CreateAccountView_Previews: PreviewProvider {
    150     static var previews: some View {
    151         let model = CreateAccountModel(real: "", nick: "jb55", about: "")
    152         return CreateAccountView(account: model, nav: .init())
    153     }
    154 }
    155 
    156 func KeyText(_ pubkey: Binding<Pubkey>) -> some View {
    157     let bechkey = bech32_encode(hrp: PUBKEY_HRP, pubkey.wrappedValue.bytes)
    158     return Text(bechkey)
    159         .textSelection(.enabled)
    160         .multilineTextAlignment(.center)
    161         .font(.callout.monospaced())
    162         .foregroundStyle(DamusLogoGradient.gradient)
    163 }
    164 
    165 func FormTextInput(_ title: String, text: Binding<String>) -> some View {
    166     return TextField("", text: text)
    167         .placeholder(when: text.wrappedValue.isEmpty) {
    168             Text(title).foregroundColor(.gray.opacity(0.5))
    169         }
    170         .padding(15)
    171         .background {
    172             RoundedRectangle(cornerRadius: 12)
    173                 .stroke(.gray.opacity(0.5), lineWidth: 1)
    174         }
    175         .font(.body.bold())
    176 }
    177 
    178 func FormLabel(_ title: String, optional: Bool = false) -> some View {
    179     return HStack {
    180         Text(title)
    181                 .bold()
    182         if optional {
    183             Text("optional", comment: "Label indicating that a form input is optional.")
    184                 .font(.callout)
    185                 .foregroundColor(DamusColors.mediumGrey)
    186         }
    187     }
    188 }
    189