This patch simplifies the onboarding flow based on Jeroen's suggestions. Setup view: - Removes extra nostr information - Only shows two buttons, create account and sign in. Create Account view: - When a user uploads a photo it is now displayed - Name is now required - Public key is now hidden - Create account model has been updated to match metadata Save Keys view: - Removes the requirement to copy the nsec - Simplified explanation - Only shows two buttons, save and not now Testing —— iPhone 15 Pro Max (17.0) Light Mode: https://v.nostr.build/3P75x.mp4 iPhone SE (3rd generation) (16.4) Dark Mode: https://v.nostr.build/wGBQL.mp4 —— Changelog-Fixed: Create Account model now uses correct metadata Changelog-Changed: Onboarding design
165 lines
5.7 KiB
Swift
165 lines
5.7 KiB
Swift
//
|
|
// CreateAccountView.swift
|
|
// damus
|
|
//
|
|
// Created by William Casarin on 2022-05-20.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct CreateAccountView: View {
|
|
@StateObject var account: CreateAccountModel = CreateAccountModel()
|
|
@StateObject var profileUploadObserver = ImageUploadingObserver()
|
|
var nav: NavigationCoordinator
|
|
|
|
func SignupForm<FormContent: View>(@ViewBuilder content: () -> FormContent) -> some View {
|
|
return VStack(alignment: .leading, spacing: 10.0, content: content)
|
|
}
|
|
|
|
func regen_key() {
|
|
let keypair = generate_new_keypair()
|
|
self.account.pubkey = keypair.pubkey
|
|
self.account.privkey = keypair.privkey
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .top) {
|
|
VStack {
|
|
Spacer()
|
|
VStack(alignment: .center) {
|
|
|
|
EditPictureControl(uploader: .nostrBuild, pubkey: account.pubkey, size: 75, setup: true, image_url: $account.profile_image , uploadObserver: profileUploadObserver, callback: uploadedProfilePicture)
|
|
.shadow(radius: 2)
|
|
.padding(.top, 100)
|
|
|
|
Text("Add Photo", comment: "Label to indicate user can add a photo.")
|
|
.bold()
|
|
.foregroundColor(DamusColors.neutral6)
|
|
}
|
|
|
|
SignupForm {
|
|
FormLabel(NSLocalizedString("Name", comment: "Label to prompt name entry."), optional: false)
|
|
.foregroundColor(DamusColors.neutral6)
|
|
FormTextInput(NSLocalizedString("Satoshi Nakamoto", comment: "Name of Bitcoin creator(s)."), text: $account.name)
|
|
.textInputAutocapitalization(.words)
|
|
|
|
FormLabel(NSLocalizedString("Bio", comment: "Label to prompt bio entry for user to describe themself."), optional: true)
|
|
.foregroundColor(DamusColors.neutral6)
|
|
FormTextInput(NSLocalizedString("Absolute legend.", comment: "Example Bio"), text: $account.about)
|
|
}
|
|
.padding(.top, 25)
|
|
|
|
Button(action: {
|
|
nav.push(route: Route.SaveKeys(account: account))
|
|
}) {
|
|
HStack {
|
|
Text("Next", comment: "Button to continue with account creation.")
|
|
.fontWeight(.semibold)
|
|
}
|
|
.frame(minWidth: 300, maxWidth: .infinity, maxHeight: 12, alignment: .center)
|
|
}
|
|
.buttonStyle(GradientButtonStyle())
|
|
.disabled(profileUploadObserver.isLoading || account.name.isEmpty)
|
|
.opacity(profileUploadObserver.isLoading || account.name.isEmpty ? 0.5 : 1)
|
|
.padding(.top, 20)
|
|
|
|
LoginPrompt()
|
|
.padding(.top)
|
|
|
|
Spacer()
|
|
}
|
|
.padding()
|
|
}
|
|
.background(DamusBackground(maxHeight: UIScreen.main.bounds.size.height/2), alignment: .top)
|
|
.dismissKeyboardOnTap()
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.navigationBarBackButtonHidden(true)
|
|
.navigationBarItems(leading: BackNav())
|
|
}
|
|
|
|
func uploadedProfilePicture(image_url: URL?) {
|
|
account.profile_image = image_url
|
|
}
|
|
}
|
|
|
|
struct LoginPrompt: View {
|
|
@Environment(\.dismiss) var dismiss
|
|
var body: some View {
|
|
HStack {
|
|
Text("Already on Nostr?", comment: "Ask the user if they already have an account on Nostr")
|
|
.foregroundColor(DamusColors.neutral6)
|
|
|
|
Button(NSLocalizedString("Login", comment: "Button to navigate to login view.")) {
|
|
self.dismiss()
|
|
}
|
|
|
|
Spacer()
|
|
}
|
|
}
|
|
}
|
|
|
|
struct BackNav: View {
|
|
@Environment(\.dismiss) var dismiss
|
|
var body: some View {
|
|
Image("chevron-left")
|
|
.foregroundColor(DamusColors.adaptableBlack)
|
|
.onTapGesture {
|
|
self.dismiss()
|
|
}
|
|
}
|
|
}
|
|
|
|
extension View {
|
|
func placeholder<Content: View>(
|
|
when shouldShow: Bool,
|
|
alignment: Alignment = .leading,
|
|
@ViewBuilder placeholder: () -> Content) -> some View {
|
|
|
|
ZStack(alignment: alignment) {
|
|
placeholder().opacity(shouldShow ? 1 : 0)
|
|
self
|
|
}
|
|
}
|
|
}
|
|
|
|
struct CreateAccountView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
let model = CreateAccountModel(display_name: "", name: "jb55", about: "")
|
|
return CreateAccountView(account: model, nav: .init())
|
|
}
|
|
}
|
|
|
|
func FormTextInput(_ title: String, text: Binding<String>) -> some View {
|
|
return TextField("", text: text)
|
|
.placeholder(when: text.wrappedValue.isEmpty) {
|
|
Text(title).foregroundColor(.gray.opacity(0.5))
|
|
}
|
|
.padding(15)
|
|
.background {
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.stroke(.gray.opacity(0.5), lineWidth: 1)
|
|
.background {
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.foregroundColor(.damusAdaptableWhite)
|
|
}
|
|
}
|
|
.font(.body.bold())
|
|
}
|
|
|
|
func FormLabel(_ title: String, optional: Bool = false) -> some View {
|
|
return HStack {
|
|
Text(title)
|
|
.bold()
|
|
if optional {
|
|
Text("optional", comment: "Label indicating that a form input is optional.")
|
|
.font(.callout)
|
|
.foregroundColor(DamusColors.mediumGrey)
|
|
} else {
|
|
Text("required", comment: "Label indicating that a form input is required.")
|
|
.font(.callout)
|
|
.foregroundColor(DamusColors.mediumGrey)
|
|
}
|
|
}
|
|
}
|
|
|