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