initial CreateAccountView
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
142
damus/Views/CreateAccountView.swift
Normal file
142
damus/Views/CreateAccountView.swift
Normal file
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// CreateAccountView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CreateAccountView: View {
|
||||
@StateObject var account: CreateAccountModel = CreateAccountModel()
|
||||
@State var is_light: Bool = false
|
||||
@State var is_done: Bool = false
|
||||
|
||||
func FormTextInput(_ title: String, text: Binding<String>) -> some View {
|
||||
return TextField("", text: text)
|
||||
.placeholder(when: text.wrappedValue.isEmpty) {
|
||||
Text(title).foregroundColor(.white.opacity(0.4))
|
||||
}
|
||||
.padding()
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 4.0).opacity(0.2)
|
||||
}
|
||||
.foregroundColor(.white)
|
||||
.font(.body.bold())
|
||||
}
|
||||
|
||||
func FormLabel(_ title: String, optional: Bool = false) -> some View {
|
||||
return HStack {
|
||||
Text(title)
|
||||
.bold()
|
||||
.foregroundColor(.white)
|
||||
if optional {
|
||||
Text("optional")
|
||||
.font(.callout)
|
||||
.foregroundColor(.white.opacity(0.5))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
DamusGradient()
|
||||
|
||||
VStack {
|
||||
Text("Create Account")
|
||||
.font(.title.bold())
|
||||
.foregroundColor(.white)
|
||||
|
||||
ProfilePictureSelector(pubkey: account.pubkey)
|
||||
|
||||
HStack(alignment: .top) {
|
||||
VStack {
|
||||
Text(" ")
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
VStack {
|
||||
SignupForm {
|
||||
FormLabel("Username")
|
||||
HStack(spacing: 0.0) {
|
||||
Text("@")
|
||||
.foregroundColor(.white)
|
||||
.padding(.leading, -25.0)
|
||||
|
||||
FormTextInput("satoshi", text: $account.nick_name)
|
||||
.textInputAutocapitalization(.never)
|
||||
|
||||
}
|
||||
|
||||
FormLabel("Display Name", optional: true)
|
||||
FormTextInput("Satoshi Nakamoto", text: $account.real_name)
|
||||
.textInputAutocapitalization(.words)
|
||||
|
||||
FormLabel("About", optional: true)
|
||||
FormTextInput("Creator(s) of Bitcoin. Absolute legend.", text: $account.about)
|
||||
|
||||
FormLabel("Account ID")
|
||||
.onTapGesture {
|
||||
regen_key()
|
||||
}
|
||||
|
||||
KeyInput($account.pubkey)
|
||||
.onTapGesture {
|
||||
regen_key()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NavigationLink(destination: SaveKeysView(account: account), isActive: $is_done) {
|
||||
EmptyView()
|
||||
}
|
||||
DamusWhiteButton("Create") {
|
||||
self.is_done = true
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.padding(.leading, 14.0)
|
||||
.padding(.trailing, 20.0)
|
||||
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
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(real: "", nick: "jb55", about: "")
|
||||
return CreateAccountView(account: model)
|
||||
}
|
||||
}
|
||||
|
||||
func KeyInput(_ text: Binding<String>) -> some View {
|
||||
return Text("\(text.wrappedValue)")
|
||||
.textSelection(.enabled)
|
||||
.font(.callout.monospaced())
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ struct EventView: View {
|
||||
let pv = ProfileView(damus_state: damus, profile: pmodel)
|
||||
|
||||
NavigationLink(destination: pv) {
|
||||
ProfilePicView(pubkey: event.pubkey, size: PFP_SIZE!, highlight: highlight, image_cache: damus.image_cache, profiles: damus.profiles)
|
||||
ProfilePicView(pubkey: event.pubkey, size: PFP_SIZE, highlight: highlight, image_cache: damus.image_cache, profiles: damus.profiles)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
@@ -17,7 +17,7 @@ struct FollowUserView: View {
|
||||
let pv = ProfileView(damus_state: damus_state, profile: pmodel)
|
||||
|
||||
NavigationLink(destination: pv) {
|
||||
ProfilePicView(pubkey: pubkey, size: PFP_SIZE!, highlight: .none, image_cache: damus_state.image_cache, profiles: damus_state.profiles)
|
||||
ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: .none, image_cache: damus_state.image_cache, profiles: damus_state.profiles)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
|
||||
@@ -56,9 +56,6 @@ struct PostView: View {
|
||||
|
||||
HStack(alignment: .top) {
|
||||
ZStack(alignment: .leading) {
|
||||
TextEditor(text: $post)
|
||||
.focused($focus)
|
||||
|
||||
if self.post == "" {
|
||||
VStack {
|
||||
Text("What's happening?")
|
||||
@@ -67,6 +64,9 @@ struct PostView: View {
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
TextEditor(text: $post)
|
||||
.focused($focus)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
let PFP_SIZE: CGFloat? = 52.0
|
||||
let CORNER_RADIUS: CGFloat = 32
|
||||
let PFP_SIZE: CGFloat = 52.0
|
||||
|
||||
func id_to_color(_ id: String) -> Color {
|
||||
return hex_to_rgb(id)
|
||||
@@ -47,9 +46,9 @@ struct ProfilePicView: View {
|
||||
}
|
||||
|
||||
var Placeholder: some View {
|
||||
PlaceholderColor.opacity(0.5)
|
||||
PlaceholderColor
|
||||
.frame(width: size, height: size)
|
||||
.cornerRadius(CORNER_RADIUS)
|
||||
.clipShape(Circle())
|
||||
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
||||
.padding(2)
|
||||
}
|
||||
@@ -100,14 +99,27 @@ struct ProfilePicView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func make_preview_profiles(_ pubkey: String) -> Profiles {
|
||||
let profiles = Profiles()
|
||||
let picture = "http://cdn.jb55.com/img/red-me.jpg"
|
||||
let profile = Profile(name: "Will", about: "It's me", picture: picture)
|
||||
let ts_profile = TimestampedProfile(profile: profile, timestamp: 0)
|
||||
profiles.add(id: pubkey, profile: ts_profile)
|
||||
return profiles
|
||||
}
|
||||
|
||||
struct ProfilePicView_Previews: PreviewProvider {
|
||||
static let pubkey = "ca48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846"
|
||||
|
||||
static var previews: some View {
|
||||
ProfilePicView(picture: "http://cdn.jb55.com/img/red-me.jpg", size: 64, highlight: .none)
|
||||
ProfilePicView(
|
||||
pubkey: pubkey,
|
||||
size: 100,
|
||||
highlight: .none,
|
||||
image_cache: ImageCache(),
|
||||
profiles: make_preview_profiles(pubkey))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
func hex_to_rgb(_ hex: String) -> Color {
|
||||
guard hex.count >= 6 else {
|
||||
|
||||
30
damus/Views/ProfilePictureSelector.swift
Normal file
30
damus/Views/ProfilePictureSelector.swift
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// ProfilePictureSelector.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-20.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ProfilePictureSelector: View {
|
||||
let pubkey: String
|
||||
|
||||
var body: some View {
|
||||
let highlight: Highlight = .custom(Color.white, 2.0)
|
||||
ZStack {
|
||||
ProfilePicView(pubkey: pubkey, size: 80.0, highlight: highlight, image_cache: ImageCache(), profiles: Profiles())
|
||||
|
||||
Image(systemName: "camera")
|
||||
.font(.title)
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ProfilePictureSelector_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let test_pubkey = "ff48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846"
|
||||
ProfilePictureSelector(pubkey: test_pubkey)
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ struct ProfileView: View {
|
||||
VStack(alignment: .leading) {
|
||||
let data = damus_state.profiles.lookup(id: profile.pubkey)
|
||||
HStack(alignment: .top) {
|
||||
ProfilePicView(pubkey: profile.pubkey, size: PFP_SIZE!, highlight: .custom(Color.black, 2), image_cache: damus_state.image_cache, profiles: damus_state.profiles)
|
||||
ProfilePicView(pubkey: profile.pubkey, size: PFP_SIZE, highlight: .custom(Color.black, 2), image_cache: damus_state.image_cache, profiles: damus_state.profiles)
|
||||
|
||||
Spacer()
|
||||
|
||||
|
||||
113
damus/Views/SaveKeysView.swift
Normal file
113
damus/Views/SaveKeysView.swift
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// SaveKeysView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2022-05-21.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SaveKeysView: View {
|
||||
let account: CreateAccountModel
|
||||
@State var is_done: Bool = false
|
||||
@State var pub_copied: Bool = false
|
||||
@State var priv_copied: Bool = false
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .top) {
|
||||
DamusGradient()
|
||||
|
||||
VStack(alignment: .center) {
|
||||
Text("Welcome, \(account.rendered_name)!")
|
||||
.font(.title.bold())
|
||||
.foregroundColor(.white)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Text("Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus.")
|
||||
.foregroundColor(.white)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Text("Public Key")
|
||||
.font(.title2.bold())
|
||||
.foregroundColor(.white)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Text("This is your account ID, you can give this to your friends so that they can follow you")
|
||||
.foregroundColor(.white)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
SaveKeyView(text: account.pubkey, is_copied: $pub_copied)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Text("Private Key")
|
||||
.font(.title2.bold())
|
||||
.foregroundColor(.white)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
Text("This is your secret account key. You need this to access your account. Don't share this with anyone! Save it in a password manager and keep it safe!")
|
||||
.foregroundColor(.white)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
SaveKeyView(text: account.privkey, is_copied: $priv_copied)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
if pub_copied && priv_copied {
|
||||
DamusWhiteButton("Let's go!") {
|
||||
save_keypair(pubkey: account.pubkey, privkey: account.privkey)
|
||||
notify(.login, ())
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SaveKeyView: View {
|
||||
let text: String
|
||||
@Binding var is_copied: Bool
|
||||
|
||||
func copy_text() {
|
||||
UIPasteboard.general.string = text
|
||||
is_copied = true
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Button(action: copy_text) {
|
||||
Label("", systemImage: is_copied ? "checkmark.circle.fill" : "doc.on.doc")
|
||||
.foregroundColor(is_copied ? .green : .white)
|
||||
.background {
|
||||
if is_copied {
|
||||
Circle()
|
||||
.foregroundColor(.white)
|
||||
.frame(width: 25, height: 25, alignment: .center)
|
||||
.padding(.leading, -8)
|
||||
.padding(.top, 1)
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(text)
|
||||
.padding(5)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 4.0).opacity(0.2)
|
||||
}
|
||||
.textSelection(.enabled)
|
||||
.font(.callout.monospaced())
|
||||
.foregroundColor(.white)
|
||||
.onTapGesture {
|
||||
copy_text()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SaveKeysView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let model = CreateAccountModel(real: "William", nick: "jb55", about: "I'm me")
|
||||
SaveKeysView(account: model)
|
||||
}
|
||||
}
|
||||
@@ -20,50 +20,80 @@ let damus_grad_c2 = hex_col(r: 0x7f, g: 0x35, b: 0xab)
|
||||
let damus_grad_c3 = hex_col(r: 0xff, g: 0x0b, b: 0xd6)
|
||||
let damus_grad = [damus_grad_c1, damus_grad_c2, damus_grad_c3]
|
||||
|
||||
struct SetupView: View {
|
||||
enum SetupState {
|
||||
case home
|
||||
case create_account
|
||||
case login
|
||||
}
|
||||
|
||||
struct DamusGradient: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
LinearGradient(colors: damus_grad, startPoint: .bottomLeading, endPoint: .topTrailing)
|
||||
.edgesIgnoringSafeArea([.top,.bottom])
|
||||
|
||||
VStack(alignment: .center) {
|
||||
Image("logo-nobg")
|
||||
.resizable()
|
||||
.frame(width: 128.0, height: 128.0, alignment: .center)
|
||||
.padding([.top], 20.0)
|
||||
Text("Damus")
|
||||
.font(Font.custom("Nunito", size: 50.0))
|
||||
.kerning(-2)
|
||||
.foregroundColor(.white)
|
||||
|
||||
CarouselView()
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("Create Account") {
|
||||
print("Create Account")
|
||||
}
|
||||
.font(.body.bold())
|
||||
.foregroundColor(.white)
|
||||
.frame(width: 300, height: 50)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 4.0)
|
||||
.stroke(Color.white, lineWidth: 2.0)
|
||||
.background(Color.white.opacity(0.15))
|
||||
)
|
||||
|
||||
Button("Login") {
|
||||
notify(.login, ())
|
||||
}
|
||||
.foregroundColor(.white)
|
||||
.padding([.top], 20)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
LinearGradient(colors: damus_grad, startPoint: .bottomLeading, endPoint: .topTrailing)
|
||||
.edgesIgnoringSafeArea([.top,.bottom])
|
||||
}
|
||||
}
|
||||
|
||||
struct SetupView: View {
|
||||
@State var state: SetupState? = .home
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack {
|
||||
DamusGradient()
|
||||
|
||||
VStack(alignment: .center) {
|
||||
NavigationLink(destination: CreateAccountView(), tag: .create_account, selection: $state ) {
|
||||
EmptyView()
|
||||
}
|
||||
|
||||
Image("logo-nobg")
|
||||
.resizable()
|
||||
.frame(width: 128.0, height: 128.0, alignment: .center)
|
||||
.padding([.top], 20.0)
|
||||
Text("Damus")
|
||||
.font(Font.custom("Nunito", size: 50.0))
|
||||
.kerning(-2)
|
||||
.foregroundColor(.white)
|
||||
|
||||
CarouselView()
|
||||
|
||||
Spacer()
|
||||
|
||||
DamusWhiteButton("Create Account") {
|
||||
self.state = .create_account
|
||||
}
|
||||
|
||||
Button("Login") {
|
||||
notify(.login, ())
|
||||
}
|
||||
.padding([.top, .bottom], 20)
|
||||
.foregroundColor(.white)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding(.top, -80)
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
|
||||
func DamusWhiteButton(_ title: String, action: @escaping () -> ()) -> some View {
|
||||
return Button(action: action) {
|
||||
Text(title)
|
||||
.frame(width: 300, height: 50)
|
||||
.font(.body.bold())
|
||||
.contentShape(Rectangle())
|
||||
.foregroundColor(.white)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 4.0)
|
||||
.stroke(Color.white, lineWidth: 2.0)
|
||||
.background(Color.white.opacity(0.15))
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct SetupView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
@@ -75,3 +105,4 @@ struct SetupView_Previews: PreviewProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user