initial CreateAccountView

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2022-05-21 19:44:04 -07:00
parent 0f453c39e6
commit 2920325639
17 changed files with 507 additions and 94 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,3 @@
xcuserdata xcuserdata
Preview\ Content
damus/TestingPrivate.swift damus/TestingPrivate.swift
.DS_Store .DS_Store

View File

@@ -14,6 +14,11 @@
4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */; }; 4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */; };
4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F96280F8E02000448DE /* ThreadView.swift */; }; 4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F96280F8E02000448DE /* ThreadView.swift */; };
4C285C8228385570008A31F1 /* CarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8128385570008A31F1 /* CarouselView.swift */; }; 4C285C8228385570008A31F1 /* CarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8128385570008A31F1 /* CarouselView.swift */; };
4C285C8428385690008A31F1 /* CreateAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8328385690008A31F1 /* CreateAccountView.swift */; };
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C85283892E7008A31F1 /* CreateAccountModel.swift */; };
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */; };
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8B28398BC6008A31F1 /* Keys.swift */; };
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */; };
4C363A8428233689006E126D /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8328233689006E126D /* Parser.swift */; }; 4C363A8428233689006E126D /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8328233689006E126D /* Parser.swift */; };
4C363A8628234FDE006E126D /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8528234FDE006E126D /* ImageCache.swift */; }; 4C363A8628234FDE006E126D /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8528234FDE006E126D /* ImageCache.swift */; };
4C363A8828236948006E126D /* BlocksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8728236948006E126D /* BlocksView.swift */; }; 4C363A8828236948006E126D /* BlocksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8728236948006E126D /* BlocksView.swift */; };
@@ -105,6 +110,11 @@
4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyQuoteView.swift; sourceTree = "<group>"; }; 4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyQuoteView.swift; sourceTree = "<group>"; };
4C0A3F96280F8E02000448DE /* ThreadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadView.swift; sourceTree = "<group>"; }; 4C0A3F96280F8E02000448DE /* ThreadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadView.swift; sourceTree = "<group>"; };
4C285C8128385570008A31F1 /* CarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselView.swift; sourceTree = "<group>"; }; 4C285C8128385570008A31F1 /* CarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselView.swift; sourceTree = "<group>"; };
4C285C8328385690008A31F1 /* CreateAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateAccountView.swift; sourceTree = "<group>"; };
4C285C85283892E7008A31F1 /* CreateAccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateAccountModel.swift; sourceTree = "<group>"; };
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePictureSelector.swift; sourceTree = "<group>"; };
4C285C8B28398BC6008A31F1 /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveKeysView.swift; sourceTree = "<group>"; };
4C363A8328233689006E126D /* Parser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; }; 4C363A8328233689006E126D /* Parser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
4C363A8528234FDE006E126D /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; }; 4C363A8528234FDE006E126D /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
4C363A8728236948006E126D /* BlocksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlocksView.swift; sourceTree = "<group>"; }; 4C363A8728236948006E126D /* BlocksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlocksView.swift; sourceTree = "<group>"; };
@@ -219,6 +229,7 @@
4C363A9B282838B9006E126D /* EventRef.swift */, 4C363A9B282838B9006E126D /* EventRef.swift */,
4C363AA328296DEE006E126D /* SearchModel.swift */, 4C363AA328296DEE006E126D /* SearchModel.swift */,
4C3AC79A28306D7B00E1F516 /* Contacts.swift */, 4C3AC79A28306D7B00E1F516 /* Contacts.swift */,
4C285C85283892E7008A31F1 /* CreateAccountModel.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -252,6 +263,9 @@
4C3AC7A42836987600E1F516 /* MainTabView.swift */, 4C3AC7A42836987600E1F516 /* MainTabView.swift */,
4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */, 4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */,
4C285C8128385570008A31F1 /* CarouselView.swift */, 4C285C8128385570008A31F1 /* CarouselView.swift */,
4C285C8328385690008A31F1 /* CreateAccountView.swift */,
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -284,6 +298,7 @@
4C363A8528234FDE006E126D /* ImageCache.swift */, 4C363A8528234FDE006E126D /* ImageCache.swift */,
4C363AA728297703006E126D /* InsertSort.swift */, 4C363AA728297703006E126D /* InsertSort.swift */,
4C477C9D282C3A4800033AA3 /* TipCounter.swift */, 4C477C9D282C3A4800033AA3 /* TipCounter.swift */,
4C285C8B28398BC6008A31F1 /* Keys.swift */,
); );
path = Util; path = Util;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -502,7 +517,9 @@
4C3AC79D2833036D00E1F516 /* FollowingView.swift in Sources */, 4C3AC79D2833036D00E1F516 /* FollowingView.swift in Sources */,
4C363A8A28236B57006E126D /* MentionView.swift in Sources */, 4C363A8A28236B57006E126D /* MentionView.swift in Sources */,
4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */, 4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */,
4C285C8428385690008A31F1 /* CreateAccountView.swift in Sources */,
4C363AA828297703006E126D /* InsertSort.swift in Sources */, 4C363AA828297703006E126D /* InsertSort.swift in Sources */,
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */, 4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
4C363A8628234FDE006E126D /* ImageCache.swift in Sources */, 4C363A8628234FDE006E126D /* ImageCache.swift in Sources */,
4C75EFB728049D990006080F /* RelayPool.swift in Sources */, 4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
@@ -510,6 +527,7 @@
4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */, 4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */,
4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */, 4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */,
4C363AA228296A7E006E126D /* SearchView.swift in Sources */, 4C363AA228296A7E006E126D /* SearchView.swift in Sources */,
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */,
4C75EFB92804A2740006080F /* EventView.swift in Sources */, 4C75EFB92804A2740006080F /* EventView.swift in Sources */,
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */, 4C7FF7D52823313F009601DB /* Mentions.swift in Sources */,
4C363A9828283441006E126D /* TestingPrivate.swift in Sources */, 4C363A9828283441006E126D /* TestingPrivate.swift in Sources */,
@@ -518,6 +536,7 @@
4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */, 4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */,
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */, 4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */, 4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */,
4C75EFB328049D640006080F /* NostrEvent.swift in Sources */, 4C75EFB328049D640006080F /* NostrEvent.swift in Sources */,
4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */, 4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */,
4C363A8428233689006E126D /* Parser.swift in Sources */, 4C363A8428233689006E126D /* Parser.swift in Sources */,
@@ -533,6 +552,7 @@
4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */, 4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */,
4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */, 4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */,
4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */, 4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */,
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */,
4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */, 4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */,
4C363A94282704FA006E126D /* Post.swift in Sources */, 4C363A94282704FA006E126D /* Post.swift in Sources */,
4C363A8828236948006E126D /* BlocksView.swift in Sources */, 4C363A8828236948006E126D /* BlocksView.swift in Sources */,

View File

@@ -31,6 +31,8 @@ enum ThreadState {
} }
struct ContentView: View { struct ContentView: View {
let pubkey: String
let privkey: String
@State var status: String = "Not connected" @State var status: String = "Not connected"
@State var active_sheet: Sheets? = nil @State var active_sheet: Sheets? = nil
@State var loading: Bool = true @State var loading: Bool = true
@@ -56,8 +58,6 @@ struct ContentView: View {
let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect() let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
let sub_id = UUID().description let sub_id = UUID().description
let pubkey = MY_PUBKEY
let privkey = MY_PRIVKEY
var LoadingContainer: some View { var LoadingContainer: some View {
VStack { VStack {
@@ -708,28 +708,3 @@ func update_filters_with_since(last_of_kind: [Int: NostrEvent], filters: [NostrF
} }
} }
struct Keypair {
let pubkey: String
let privkey: String
}
func save_keypair(pubkey: String, privkey: String) {
UserDefaults.standard.set(pubkey, forKey: "pubkey")
UserDefaults.standard.set(privkey, forKey: "privkey")
}
func get_saved_keypair() -> Keypair? {
get_saved_pubkey().flatMap { pubkey in
get_saved_privkey().map { privkey in
return Keypair(pubkey: pubkey, privkey: privkey)
}
}
}
func get_saved_pubkey() -> String? {
return UserDefaults.standard.string(forKey: "pubkey")
}
func get_saved_privkey() -> String? {
return UserDefaults.standard.string(forKey: "privkey")
}

View File

@@ -0,0 +1,40 @@
//
// CreateAccountModel.swift
// damus
//
// Created by William Casarin on 2022-05-20.
//
import Foundation
class CreateAccountModel: ObservableObject {
@Published var real_name: String = ""
@Published var nick_name: String = ""
@Published var about: String = ""
@Published var pubkey: String = ""
@Published var privkey: String = ""
var rendered_name: String {
if real_name.isEmpty {
return nick_name
}
return real_name
}
init() {
let keypair = generate_new_keypair()
self.pubkey = keypair.pubkey
self.privkey = keypair.privkey
}
init(real: String, nick: String, about: String) {
let keypair = generate_new_keypair()
self.pubkey = keypair.pubkey
self.privkey = keypair.privkey
self.real_name = real
self.nick_name = nick
self.about = about
}
}

View File

@@ -54,7 +54,7 @@ class ImageCache {
func insert(_ image: UIImage?, for url: URL) { func insert(_ image: UIImage?, for url: URL) {
guard let image = image else { return remove(for: url) } guard let image = image else { return remove(for: url) }
let decodedImage = image.decodedImage(Int(PFP_SIZE!)) let decodedImage = image.decodedImage(Int(PFP_SIZE))
lock.lock(); defer { lock.unlock() } lock.lock(); defer { lock.unlock() }
cache.setObject(decodedImage, forKey: url as AnyObject) cache.setObject(decodedImage, forKey: url as AnyObject)
} }

43
damus/Util/Keys.swift Normal file
View File

@@ -0,0 +1,43 @@
//
// Keys.swift
// damus
//
// Created by William Casarin on 2022-05-21.
//
import Foundation
import secp256k1
struct Keypair {
let pubkey: String
let privkey: String
}
func generate_new_keypair() -> Keypair {
let key = try! secp256k1.Signing.PrivateKey()
let privkey = hex_encode(key.rawRepresentation)
let pubkey = hex_encode(Data(key.publicKey.xonlyKeyBytes))
print("generating privkey:\(privkey) pubkey:\(pubkey)")
return Keypair(pubkey: pubkey, privkey: privkey)
}
func save_keypair(pubkey: String, privkey: String) {
UserDefaults.standard.set(pubkey, forKey: "pubkey")
UserDefaults.standard.set(privkey, forKey: "privkey")
}
func get_saved_keypair() -> Keypair? {
get_saved_pubkey().flatMap { pubkey in
get_saved_privkey().map { privkey in
return Keypair(pubkey: pubkey, privkey: privkey)
}
}
}
func get_saved_pubkey() -> String? {
return UserDefaults.standard.string(forKey: "pubkey")
}
func get_saved_privkey() -> String? {
return UserDefaults.standard.string(forKey: "privkey")
}

View 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)
}

View File

@@ -72,7 +72,7 @@ struct EventView: View {
let pv = ProfileView(damus_state: damus, profile: pmodel) let pv = ProfileView(damus_state: damus, profile: pmodel)
NavigationLink(destination: pv) { 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() Spacer()

View File

@@ -17,7 +17,7 @@ struct FollowUserView: View {
let pv = ProfileView(damus_state: damus_state, profile: pmodel) let pv = ProfileView(damus_state: damus_state, profile: pmodel)
NavigationLink(destination: pv) { 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) { VStack(alignment: .leading) {

View File

@@ -56,9 +56,6 @@ struct PostView: View {
HStack(alignment: .top) { HStack(alignment: .top) {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
TextEditor(text: $post)
.focused($focus)
if self.post == "" { if self.post == "" {
VStack { VStack {
Text("What's happening?") Text("What's happening?")
@@ -67,6 +64,9 @@ struct PostView: View {
Spacer() Spacer()
} }
} }
TextEditor(text: $post)
.focused($focus)
} }

View File

@@ -7,8 +7,7 @@
import SwiftUI import SwiftUI
let PFP_SIZE: CGFloat? = 52.0 let PFP_SIZE: CGFloat = 52.0
let CORNER_RADIUS: CGFloat = 32
func id_to_color(_ id: String) -> Color { func id_to_color(_ id: String) -> Color {
return hex_to_rgb(id) return hex_to_rgb(id)
@@ -47,9 +46,9 @@ struct ProfilePicView: View {
} }
var Placeholder: some View { var Placeholder: some View {
PlaceholderColor.opacity(0.5) PlaceholderColor
.frame(width: size, height: size) .frame(width: size, height: size)
.cornerRadius(CORNER_RADIUS) .clipShape(Circle())
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight))) .overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
.padding(2) .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 { struct ProfilePicView_Previews: PreviewProvider {
static let pubkey = "ca48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846"
static var previews: some View { 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 { func hex_to_rgb(_ hex: String) -> Color {
guard hex.count >= 6 else { guard hex.count >= 6 else {

View 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)
}
}

View File

@@ -72,7 +72,7 @@ struct ProfileView: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
let data = damus_state.profiles.lookup(id: profile.pubkey) let data = damus_state.profiles.lookup(id: profile.pubkey)
HStack(alignment: .top) { 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() Spacer()

View 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)
}
}

View File

@@ -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_c3 = hex_col(r: 0xff, g: 0x0b, b: 0xd6)
let damus_grad = [damus_grad_c1, damus_grad_c2, damus_grad_c3] 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 { var body: some View {
ZStack { LinearGradient(colors: damus_grad, startPoint: .bottomLeading, endPoint: .topTrailing)
LinearGradient(colors: damus_grad, startPoint: .bottomLeading, endPoint: .topTrailing) .edgesIgnoringSafeArea([.top,.bottom])
.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()
}
}
} }
} }
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 { struct SetupView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
@@ -75,3 +105,4 @@ struct SetupView_Previews: PreviewProvider {
} }
} }
} }

View File

@@ -21,21 +21,27 @@ struct damusApp: App {
struct MainView: View { struct MainView: View {
@State var needs_setup = true; @State var needs_setup = true;
@State var keypair: Keypair? = nil;
var body: some View { var body: some View {
if needs_setup { Group {
SetupView() if let kp = keypair, !needs_setup {
.onReceive(handle_notify(.login)) { notif in ContentView(pubkey: kp.pubkey, privkey: kp.privkey)
needs_setup = false } else {
} SetupView()
} else { .onReceive(handle_notify(.login)) { notif in
ContentView() needs_setup = false
keypair = get_saved_keypair()
}
}
}
.onAppear {
keypair = get_saved_keypair()
} }
} }
} }
func needs_setup() -> Bool { func needs_setup() -> Keypair? {
let _ = get_saved_privkey() return get_saved_keypair()
return true
} }

View File

@@ -19,10 +19,12 @@ class LikeTests: XCTestCase {
} }
func testLikeHasNotification() throws { func testLikeHasNotification() throws {
let privkey = "0fc2092231f958f8d57d66f5e238bb45b6a2571f44c0ce024bbc6f3a9c8a15fe"
let pubkey = "30c6d1dc7f7c156794fa15055e651b758a61b99f50fcf759de59386050bf6ae2"
let liked = NostrEvent(content: "awesome #[0] post", pubkey: "orig_pk", tags: [["p", "cindy"], ["e", "bob"]]) let liked = NostrEvent(content: "awesome #[0] post", pubkey: "orig_pk", tags: [["p", "cindy"], ["e", "bob"]])
liked.calculate_id() liked.calculate_id()
let id = liked.id let id = liked.id
let like_ev = make_like_event(pubkey: "pubkey", liked: liked)! let like_ev = make_like_event(pubkey: pubkey, privkey: privkey, liked: liked)
XCTAssertTrue(like_ev.references(id: "orig_pk", key: "p")) XCTAssertTrue(like_ev.references(id: "orig_pk", key: "p"))
XCTAssertTrue(like_ev.references(id: "cindy", key: "p")) XCTAssertTrue(like_ev.references(id: "cindy", key: "p"))