damus

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

commit 084d699cfc20911f673745c09db4d9cd60f8fd3c
parent 3d1c011e73569722d911f11d14588c75ba1e225b
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 19 May 2022 14:38:25 -0700

Initial SetupView

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 8++++++--
Adamus/Assets.xcassets/bitcoin-p2p.imageset/Contents.json | 21+++++++++++++++++++++
Adamus/Assets.xcassets/bitcoin-p2p.imageset/bitcoin-p2p.png | 0
Adamus/Assets.xcassets/digital-nomad.imageset/Contents.json | 21+++++++++++++++++++++
Adamus/Assets.xcassets/digital-nomad.imageset/digital-nomad.png | 0
Adamus/Assets.xcassets/encrypted-message.imageset/Contents.json | 21+++++++++++++++++++++
Adamus/Assets.xcassets/encrypted-message.imageset/encrypted-message.png | 0
Adamus/Assets.xcassets/logo-nobg.imageset/Contents.json | 21+++++++++++++++++++++
Adamus/Assets.xcassets/logo-nobg.imageset/damus-nobg.png | 0
Adamus/Assets.xcassets/undercover.imageset/Contents.json | 21+++++++++++++++++++++
Adamus/Assets.xcassets/undercover.imageset/undercover.png | 0
Mdamus/ContentView.swift | 41++++++++++++++++++++++++++++-------------
Ddamus/Notifications.swift | 142-------------------------------------------------------------------------------
Adamus/Util/Notifications.swift | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdamus/TimeAgo.swift -> damus/Util/TimeAgo.swift | 0
Mdamus/Views/MainTabView.swift | 13+++++++++++++
Adamus/Views/SearchHomeView.swift | 20++++++++++++++++++++
Mdamus/Views/SetupView.swift | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mdamus/damusApp.swift | 24++++++++++++++++++++++++
19 files changed, 454 insertions(+), 159 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC79E2833115300E1F516 /* FollowButtonView.swift */; }; 4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC7A02835A81400E1F516 /* SetupView.swift */; }; 4C3AC7A52836987600E1F516 /* MainTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC7A42836987600E1F516 /* MainTabView.swift */; }; + 4C3AC7A728369BA200E1F516 /* SearchHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */; }; 4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */; }; 4C3BEFD42819DE8F00B3DE84 /* NostrKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */; }; 4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD5281D995700B3DE84 /* ActionBarModel.swift */; }; @@ -125,6 +126,7 @@ 4C3AC79E2833115300E1F516 /* FollowButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowButtonView.swift; sourceTree = "<group>"; }; 4C3AC7A02835A81400E1F516 /* SetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupView.swift; sourceTree = "<group>"; }; 4C3AC7A42836987600E1F516 /* MainTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabView.swift; sourceTree = "<group>"; }; + 4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHomeView.swift; sourceTree = "<group>"; }; 4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModel.swift; sourceTree = "<group>"; }; 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrKind.swift; sourceTree = "<group>"; }; 4C3BEFD5281D995700B3DE84 /* ActionBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBarModel.swift; sourceTree = "<group>"; }; @@ -246,6 +248,7 @@ 4C3AC79E2833115300E1F516 /* FollowButtonView.swift */, 4C3AC7A02835A81400E1F516 /* SetupView.swift */, 4C3AC7A42836987600E1F516 /* MainTabView.swift */, + 4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */, ); path = Views; sourceTree = "<group>"; @@ -272,6 +275,8 @@ 4C7FF7D628233637009601DB /* Util */ = { isa = PBXGroup; children = ( + 4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */, + 4CE4F8CC281352B30009DFBB /* Notifications.swift */, 4C363A8328233689006E126D /* Parser.swift */, 4C363A8528234FDE006E126D /* ImageCache.swift */, 4C363AA728297703006E126D /* InsertSort.swift */, @@ -313,8 +318,6 @@ 4CE6DEE827F7A08100C66700 /* ContentView.swift */, 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */, 4CE6DEEC27F7A08200C66700 /* Preview Content */, - 4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */, - 4CE4F8CC281352B30009DFBB /* Notifications.swift */, 4C363A9728283441006E126D /* TestingPrivate.swift */, ); path = damus; @@ -541,6 +544,7 @@ 4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */, 4C363A962827096D006E126D /* PostBlock.swift in Sources */, 4CEE2AED2805B22500AB5EEF /* NostrRequest.swift in Sources */, + 4C3AC7A728369BA200E1F516 /* SearchHomeView.swift in Sources */, 4C363A922825FCF2006E126D /* ProfileUpdate.swift in Sources */, 4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */, 4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */, diff --git a/damus/Assets.xcassets/bitcoin-p2p.imageset/Contents.json b/damus/Assets.xcassets/bitcoin-p2p.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "bitcoin-p2p.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/damus/Assets.xcassets/bitcoin-p2p.imageset/bitcoin-p2p.png b/damus/Assets.xcassets/bitcoin-p2p.imageset/bitcoin-p2p.png Binary files differ. diff --git a/damus/Assets.xcassets/digital-nomad.imageset/Contents.json b/damus/Assets.xcassets/digital-nomad.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "digital-nomad.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/damus/Assets.xcassets/digital-nomad.imageset/digital-nomad.png b/damus/Assets.xcassets/digital-nomad.imageset/digital-nomad.png Binary files differ. diff --git a/damus/Assets.xcassets/encrypted-message.imageset/Contents.json b/damus/Assets.xcassets/encrypted-message.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "encrypted-message.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/damus/Assets.xcassets/encrypted-message.imageset/encrypted-message.png b/damus/Assets.xcassets/encrypted-message.imageset/encrypted-message.png Binary files differ. diff --git a/damus/Assets.xcassets/logo-nobg.imageset/Contents.json b/damus/Assets.xcassets/logo-nobg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "damus-nobg.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/damus/Assets.xcassets/logo-nobg.imageset/damus-nobg.png b/damus/Assets.xcassets/logo-nobg.imageset/damus-nobg.png Binary files differ. diff --git a/damus/Assets.xcassets/undercover.imageset/Contents.json b/damus/Assets.xcassets/undercover.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "undercover.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/damus/Assets.xcassets/undercover.imageset/undercover.png b/damus/Assets.xcassets/undercover.imageset/undercover.png Binary files differ. diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -30,16 +30,6 @@ enum ThreadState { case chatroom } -enum Timeline: String, CustomStringConvertible { - case home - case notifications - case global - - var description: String { - return self.rawValue - } -} - struct ContentView: View { @State var status: String = "Not connected" @State var active_sheet: Sheets? = nil @@ -108,11 +98,11 @@ struct ContentView: View { EmptyView() } switch selected_timeline { + case .search: + SearchHomeView() + case .home: PostingTimelineView - .onAppear() { - //switch_timeline(.home) - } case .notifications: TimelineView(events: $notifications, damus: damus) @@ -718,3 +708,28 @@ 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") +} diff --git a/damus/Notifications.swift b/damus/Notifications.swift @@ -1,142 +0,0 @@ -// -// Notifications.swift -// damus -// -// Created by William Casarin on 2022-04-22. -// - -import Foundation - -extension Notification.Name { - static var thread_focus: Notification.Name { - return Notification.Name("thread focus") - } -} - -extension Notification.Name { - static var select_event: Notification.Name { - return Notification.Name("select_event") - } -} - -extension Notification.Name { - static var select_quote: Notification.Name { - return Notification.Name("select quote") - } -} - -extension Notification.Name { - static var reply: Notification.Name { - return Notification.Name("reply") - } -} - -extension Notification.Name { - static var profile_updated: Notification.Name { - return Notification.Name("profile_updated") - } -} - -extension Notification.Name { - static var switched_timeline: Notification.Name { - return Notification.Name("switched_timeline") - } -} - -extension Notification.Name { - static var liked: Notification.Name { - return Notification.Name("liked") - } -} - -extension Notification.Name { - static var open_profile: Notification.Name { - return Notification.Name("open_profile") - } -} - -extension Notification.Name { - static var scroll_to_top: Notification.Name { - return Notification.Name("scroll_to_to") - } -} - -extension Notification.Name { - static var broadcast_event: Notification.Name { - return Notification.Name("broadcast event") - } -} - -extension Notification.Name { - static var open_thread: Notification.Name { - return Notification.Name("open thread") - } -} - -extension Notification.Name { - static var notice: Notification.Name { - return Notification.Name("notice") - } -} - -extension Notification.Name { - static var like: Notification.Name { - return Notification.Name("like note") - } -} - -extension Notification.Name { - static var delete: Notification.Name { - return Notification.Name("delete note") - } -} - -extension Notification.Name { - static var post: Notification.Name { - return Notification.Name("send post") - } -} - -extension Notification.Name { - static var boost: Notification.Name { - return Notification.Name("boost") - } -} - -extension Notification.Name { - static var boosted: Notification.Name { - return Notification.Name("boosted") - } -} - -extension Notification.Name { - static var follow: Notification.Name { - return Notification.Name("follow") - } -} - -extension Notification.Name { - static var unfollow: Notification.Name { - return Notification.Name("unfollow") - } -} - -extension Notification.Name { - static var followed: Notification.Name { - return Notification.Name("followed") - } -} - -extension Notification.Name { - static var unfollowed: Notification.Name { - return Notification.Name("unfollowed") - } -} - -func handle_notify(_ name: Notification.Name) -> NotificationCenter.Publisher { - return NotificationCenter.default.publisher(for: name) -} - -func notify(_ name: NSNotification.Name, _ object: Any?) { - NotificationCenter.default.post(name: name, object: object) -} diff --git a/damus/Util/Notifications.swift b/damus/Util/Notifications.swift @@ -0,0 +1,148 @@ +// +// Notifications.swift +// damus +// +// Created by William Casarin on 2022-04-22. +// + +import Foundation + +extension Notification.Name { + static var thread_focus: Notification.Name { + return Notification.Name("thread focus") + } +} + +extension Notification.Name { + static var select_event: Notification.Name { + return Notification.Name("select_event") + } +} + +extension Notification.Name { + static var select_quote: Notification.Name { + return Notification.Name("select quote") + } +} + +extension Notification.Name { + static var reply: Notification.Name { + return Notification.Name("reply") + } +} + +extension Notification.Name { + static var profile_updated: Notification.Name { + return Notification.Name("profile_updated") + } +} + +extension Notification.Name { + static var switched_timeline: Notification.Name { + return Notification.Name("switched_timeline") + } +} + +extension Notification.Name { + static var liked: Notification.Name { + return Notification.Name("liked") + } +} + +extension Notification.Name { + static var open_profile: Notification.Name { + return Notification.Name("open_profile") + } +} + +extension Notification.Name { + static var scroll_to_top: Notification.Name { + return Notification.Name("scroll_to_to") + } +} + +extension Notification.Name { + static var broadcast_event: Notification.Name { + return Notification.Name("broadcast event") + } +} + +extension Notification.Name { + static var open_thread: Notification.Name { + return Notification.Name("open thread") + } +} + +extension Notification.Name { + static var notice: Notification.Name { + return Notification.Name("notice") + } +} + +extension Notification.Name { + static var like: Notification.Name { + return Notification.Name("like note") + } +} + +extension Notification.Name { + static var delete: Notification.Name { + return Notification.Name("delete note") + } +} + +extension Notification.Name { + static var post: Notification.Name { + return Notification.Name("send post") + } +} + +extension Notification.Name { + static var boost: Notification.Name { + return Notification.Name("boost") + } +} + +extension Notification.Name { + static var boosted: Notification.Name { + return Notification.Name("boosted") + } +} + +extension Notification.Name { + static var follow: Notification.Name { + return Notification.Name("follow") + } +} + +extension Notification.Name { + static var unfollow: Notification.Name { + return Notification.Name("unfollow") + } +} + +extension Notification.Name { + static var login: Notification.Name { + return Notification.Name("login") + } +} + +extension Notification.Name { + static var followed: Notification.Name { + return Notification.Name("followed") + } +} + +extension Notification.Name { + static var unfollowed: Notification.Name { + return Notification.Name("unfollowed") + } +} + +func handle_notify(_ name: Notification.Name) -> NotificationCenter.Publisher { + return NotificationCenter.default.publisher(for: name) +} + +func notify(_ name: NSNotification.Name, _ object: Any?) { + NotificationCenter.default.post(name: name, object: object) +} diff --git a/damus/TimeAgo.swift b/damus/Util/TimeAgo.swift diff --git a/damus/Views/MainTabView.swift b/damus/Views/MainTabView.swift @@ -7,6 +7,18 @@ import SwiftUI +enum Timeline: String, CustomStringConvertible { + case home + case notifications + case global + case search + + var description: String { + return self.rawValue + } +} + + struct MainTabView: View { var body: some View { Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) @@ -72,6 +84,7 @@ struct TabBar: View { Divider() HStack { TabButton(timeline: .home, img: "house", selected: $selected, action: action) + TabButton(timeline: .search, img: "magnifyingglass.circle", selected: $selected, action: action) NotificationsTab(new_notifications: $new_notifications, selected: $selected, action: action) TabButton(timeline: .global, img: "globe.americas", selected: $selected, action: action) } diff --git a/damus/Views/SearchHomeView.swift b/damus/Views/SearchHomeView.swift @@ -0,0 +1,20 @@ +// +// SearchHomeView.swift +// damus +// +// Created by William Casarin on 2022-05-19. +// + +import SwiftUI + +struct SearchHomeView: View { + var body: some View { + Text("Search Home") + } +} + +struct SearchHomeView_Previews: PreviewProvider { + static var previews: some View { + SearchHomeView() + } +} diff --git a/damus/Views/SetupView.swift b/damus/Views/SetupView.swift @@ -7,14 +7,122 @@ import SwiftUI +func hex_col(r: UInt8, g: UInt8, b: UInt8) -> Color { + return Color(.sRGB, + red: Double(r) / Double(0xff), + green: Double(g) / Double(0xff), + blue: Double(b) / Double(0xff), + opacity: 1.0) +} + +let damus_grad_c1 = hex_col(r: 0x1c, g: 0x55, b: 0xff) +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 { var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + 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() + } + } + } +} + +func CarouselText(_ txt: String) -> some View { + return Text(txt) +} + +struct CarouselItem: Identifiable { + let image: Image + let text: Text + + let id = UUID().uuidString +} + +struct CarouselItemView: View { + let item: CarouselItem + + var body: some View { + VStack(spacing: 30) { + item.image + .resizable() + .frame(width: 120, height: 120) + item.text + .multilineTextAlignment(.center) + .font(.title2) + .foregroundColor(Color.white) + .padding([.leading,.trailing], 50.0) + } + } +} + +let carousel_items = [ + CarouselItem(image: Image("digital-nomad"), text: Text("Welcome to the social network \(Text("you").italic()) control.")), + CarouselItem(image: Image("encrypted-message"), + text: Text("\(Text("Encrypted").bold()). End-to-End encrypted private messaging. Keep Big Tech out of your DMs")), + CarouselItem(image: Image("undercover"), + text: Text("\(Text("Private").bold()). Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.")), + CarouselItem(image: Image("bitcoin-p2p"), + text: Text("\(Text("Earn Money").bold()). Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet.")) +] + +struct CarouselView: View { + var body: some View { + TabView { + ForEach(carousel_items) { item in + CarouselItemView(item: item) + .tabItem { + Text(item.image) + } + } + } + .tabViewStyle(PageTabViewStyle()) } } struct SetupView_Previews: PreviewProvider { static var previews: some View { - SetupView() + Group { + SetupView() + .previewDevice(PreviewDevice(rawValue: "iPhone SE (3rd generation)")) + SetupView() + .previewDevice(PreviewDevice(rawValue: "iPhone 13 Pro Max")) + } } } diff --git a/damus/damusApp.swift b/damus/damusApp.swift @@ -11,7 +11,31 @@ import SwiftUI struct damusApp: App { var body: some Scene { WindowGroup { + MainView() + } + + } + + +} + +struct MainView: View { + @State var needs_setup = true; + + var body: some View { + if needs_setup { + SetupView() + .onReceive(handle_notify(.login)) { notif in + needs_setup = false + } + } else { ContentView() } } } + +func needs_setup() -> Bool { + let _ = get_saved_privkey() + return true +} +