damus

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

commit dc376a4a7217200b60f4b5afe74bacd6b2911458
parent f4bb07081f15a783e99e2469216d4d004d3a189b
Author: William Casarin <jb55@jb55.com>
Date:   Sun,  3 Apr 2022 15:40:18 -0700

better main view, add initial post view

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

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 18++++++++++++++++--
Mdamus/ContentView.swift | 119++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mdamus/NostrConnection.swift | 18++++++++----------
Adamus/Views/PostView.swift | 20++++++++++++++++++++
Ddamus/WSConnection.swift | 50--------------------------------------------------
5 files changed, 150 insertions(+), 75 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 4C75EFA427FA577B0006080F /* PostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFA327FA577B0006080F /* PostView.swift */; }; 4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE627F7A08100C66700 /* damusApp.swift */; }; 4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE827F7A08100C66700 /* ContentView.swift */; }; 4CE6DEEB27F7A08200C66700 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */; }; @@ -37,6 +38,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 4C75EFA327FA577B0006080F /* PostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostView.swift; sourceTree = "<group>"; }; 4CE6DEE327F7A08100C66700 /* damus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = damus.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4CE6DEE627F7A08100C66700 /* damusApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = damusApp.swift; sourceTree = "<group>"; }; 4CE6DEE827F7A08100C66700 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; @@ -77,6 +79,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 4C75EFA227FA576C0006080F /* Views */ = { + isa = PBXGroup; + children = ( + 4C75EFA327FA577B0006080F /* PostView.swift */, + ); + path = Views; + sourceTree = "<group>"; + }; 4CE6DEDA27F7A08100C66700 = { isa = PBXGroup; children = ( @@ -100,6 +110,7 @@ 4CE6DEE527F7A08100C66700 /* damus */ = { isa = PBXGroup; children = ( + 4C75EFA227FA576C0006080F /* Views */, 4CE6DEE627F7A08100C66700 /* damusApp.swift */, 4CE6DEE827F7A08100C66700 /* ContentView.swift */, 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */, @@ -275,6 +286,7 @@ 4CE6DF1427F7A45200C66700 /* WSConnection.swift in Sources */, 4CE6DF1627F8DEBF00C66700 /* NostrConnection.swift in Sources */, 4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */, + 4C75EFA427FA577B0006080F /* PostView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -361,7 +373,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.4; + IPHONEOS_DEPLOYMENT_TARGET = 15.3; + MACOSX_DEPLOYMENT_TARGET = 12.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -415,7 +428,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.4; + IPHONEOS_DEPLOYMENT_TARGET = 15.3; + MACOSX_DEPLOYMENT_TARGET = 12.3; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -8,36 +8,111 @@ import SwiftUI import Starscream +struct EventView: View { + let event: NostrEvent + + var body: some View { + VStack { + Text(String(event.pubkey.prefix(16))) + .bold() + .onTapGesture { + UIPasteboard.general.string = event.pubkey + } + .frame(maxWidth: .infinity, alignment: .leading) + Text(event.content) + .textSelection(.enabled) + .frame(maxWidth: .infinity, alignment: .leading) + Divider() + } + } +} + +enum Sheets: Identifiable { + case post + + var id: String { + switch self { + case .post: + return "post" + } + } +} + struct ContentView: View { @State var status: String = "Not connected" + @State var sub_id: String? = nil + @State var active_sheet: Sheets? = nil @State var events: [NostrEvent] = [] @State var connection: NostrConnection? = nil - + + var MainContent: some View { + ScrollView { + ForEach(events.reversed(), id: \.id) { + EventView(event: $0) + } + } + } + var body: some View { - ForEach(events, id: \.id) { - Text($0.content) - .padding() + ZStack { + MainContent + VStack { + Spacer() + + HStack { + Spacer() + PostButton { + self.active_sheet = .post + } + } + } } .onAppear() { - let url = URL(string: "wss://nostr.bitcoiner.social")! - let conn = NostrConnection(url: url, handleEvent: handle_event) - conn.connect() - self.connection = conn + self.connect() } + .sheet(item: $active_sheet) { item in + switch item { + case .post: + PostView() + } + } + } + + func connect() { + let url = URL(string: "wss://nostr.bitcoiner.social")! + let conn = NostrConnection(url: url, handleEvent: handle_event) + conn.connect() + self.connection = conn } - + func handle_event(conn_event: NostrConnectionEvent) { - switch conn_event { case .ws_event(let ev): - if case .connected = ev { - self.connection?.send(NostrFilter.filter_since(1648851447)) + switch ev { + case .connected: + let now = Int64(Date().timeIntervalSince1970) + let yesterday = now - 24 * 60 * 60 + let filter = NostrFilter.filter_since(yesterday) + let sub_id = self.sub_id ?? UUID().description + if self.sub_id != sub_id { + self.sub_id = sub_id + } + self.connection?.send(filter, sub_id: sub_id) + case .cancelled: + self.connection?.connect() + default: + break } print("ws_event \(ev)") + case .nostr_event(let ev): switch ev { case .event(_, let ev): - self.events.append(ev) + self.sub_id = sub_id + if ev.kind == 1 { + self.events.append(ev) + } + print(ev) case .notice(let msg): print(msg) } @@ -50,3 +125,21 @@ struct ContentView_Previews: PreviewProvider { ContentView() } } + +func PostButton(action: @escaping () -> ()) -> some View { + return Button(action: action, label: { + Text("+") + .font(.system(.largeTitle)) + .frame(width: 67, height: 60) + .foregroundColor(Color.white) + .padding(.bottom, 7) + }) + .background(Color.blue) + .cornerRadius(38.5) + .padding() + .shadow(color: Color.black.opacity(0.3), + radius: 3, + x: 3, + y: 3) +} + diff --git a/damus/NostrConnection.swift b/damus/NostrConnection.swift @@ -28,6 +28,11 @@ enum NostrTag { case key_event(KeyEvent) } +struct NostrSubscription { + let sub_id: String + let filter: NostrFilter +} + struct NostrFilter: Codable { let ids: [String]? let kinds: [String]? @@ -114,8 +119,8 @@ class NostrConnection: WebSocketDelegate { socket.disconnect() } - func send(_ filter: NostrFilter) { - guard let req = make_nostr_req(filter) else { + func send(_ filter: NostrFilter, sub_id: String) { + guard let req = make_nostr_req(filter, sub_id: sub_id) else { print("failed to encode nostr req: \(filter)") return } @@ -165,14 +170,7 @@ func decode_data<T: Decodable>(_ data: Data) -> T? { return nil } -func make_nostr_req(_ filter: NostrFilter) -> String? { - let sub_id = UUID() - var params: [Encodable] = [] - - params.append("REQ") - params.append(sub_id) - params.append(filter) - +func make_nostr_req(_ filter: NostrFilter, sub_id: String) -> String? { let encoder = JSONEncoder() guard let filter_json = try? encoder.encode(filter) else { return nil diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift @@ -0,0 +1,20 @@ +// +// Post.swift +// damus +// +// Created by William Casarin on 2022-04-03. +// + +import SwiftUI + +struct PostView: View { + var body: some View { + Text("New post") + } +} + +struct Post_Previews: PreviewProvider { + static var previews: some View { + PostView() + } +} diff --git a/damus/WSConnection.swift b/damus/WSConnection.swift @@ -1,50 +0,0 @@ -// -// Connection.swift -// damus -// -// Created by William Casarin on 2022-04-01. -// - -import Foundation -import Starscream - -class WSConnection: WebSocketDelegate { - var isConnected: Bool = false - var socket: WebSocket - var handleEvent: (WebSocketEvent) -> () - - init(url: URL, handleEvent: @escaping (WebSocketEvent) -> ()) { - var req = URLRequest(url: url) - req.timeoutInterval = 5 - self.socket = WebSocket(request: req) - self.handleEvent = handleEvent - - socket.delegate = self - } - - func connect(){ - socket.connect() - } - - func disconnect() { - socket.disconnect() - } - - func didReceive(event: WebSocketEvent, client: WebSocket) { - switch event { - case .connected: - self.isConnected = true - - case .disconnected: fallthrough - case .cancelled: fallthrough - case .error: - self.isConnected = false - - default: - break - } - - handleEvent(event) - } - -}