better main view, add initial post view
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE627F7A08100C66700 /* damusApp.swift */; };
|
||||||
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE827F7A08100C66700 /* ContentView.swift */; };
|
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE6DEE827F7A08100C66700 /* ContentView.swift */; };
|
||||||
4CE6DEEB27F7A08200C66700 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */; };
|
4CE6DEEB27F7A08200C66700 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CE6DEEA27F7A08200C66700 /* Assets.xcassets */; };
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXFileReference 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; };
|
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>"; };
|
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>"; };
|
4CE6DEE827F7A08100C66700 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
@@ -77,6 +79,14 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
4C75EFA227FA576C0006080F /* Views */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4C75EFA327FA577B0006080F /* PostView.swift */,
|
||||||
|
);
|
||||||
|
path = Views;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4CE6DEDA27F7A08100C66700 = {
|
4CE6DEDA27F7A08100C66700 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -100,6 +110,7 @@
|
|||||||
4CE6DEE527F7A08100C66700 /* damus */ = {
|
4CE6DEE527F7A08100C66700 /* damus */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4C75EFA227FA576C0006080F /* Views */,
|
||||||
4CE6DEE627F7A08100C66700 /* damusApp.swift */,
|
4CE6DEE627F7A08100C66700 /* damusApp.swift */,
|
||||||
4CE6DEE827F7A08100C66700 /* ContentView.swift */,
|
4CE6DEE827F7A08100C66700 /* ContentView.swift */,
|
||||||
4CE6DEEA27F7A08200C66700 /* Assets.xcassets */,
|
4CE6DEEA27F7A08200C66700 /* Assets.xcassets */,
|
||||||
@@ -275,6 +286,7 @@
|
|||||||
4CE6DF1427F7A45200C66700 /* WSConnection.swift in Sources */,
|
4CE6DF1427F7A45200C66700 /* WSConnection.swift in Sources */,
|
||||||
4CE6DF1627F8DEBF00C66700 /* NostrConnection.swift in Sources */,
|
4CE6DF1627F8DEBF00C66700 /* NostrConnection.swift in Sources */,
|
||||||
4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */,
|
4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */,
|
||||||
|
4C75EFA427FA577B0006080F /* PostView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -361,7 +373,8 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = 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_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
@@ -415,7 +428,8 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = 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_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
|||||||
@@ -8,36 +8,111 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Starscream
|
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 {
|
struct ContentView: View {
|
||||||
@State var status: String = "Not connected"
|
@State var status: String = "Not connected"
|
||||||
|
@State var sub_id: String? = nil
|
||||||
|
@State var active_sheet: Sheets? = nil
|
||||||
@State var events: [NostrEvent] = []
|
@State var events: [NostrEvent] = []
|
||||||
@State var connection: NostrConnection? = nil
|
@State var connection: NostrConnection? = nil
|
||||||
|
|
||||||
var body: some View {
|
var MainContent: some View {
|
||||||
ForEach(events, id: \.id) {
|
ScrollView {
|
||||||
Text($0.content)
|
ForEach(events.reversed(), id: \.id) {
|
||||||
.padding()
|
EventView(event: $0)
|
||||||
}
|
}
|
||||||
.onAppear() {
|
|
||||||
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) {
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
MainContent
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
PostButton {
|
||||||
|
self.active_sheet = .post
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear() {
|
||||||
|
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 {
|
switch conn_event {
|
||||||
case .ws_event(let ev):
|
case .ws_event(let ev):
|
||||||
if case .connected = ev {
|
switch ev {
|
||||||
self.connection?.send(NostrFilter.filter_since(1648851447))
|
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)")
|
print("ws_event \(ev)")
|
||||||
|
|
||||||
case .nostr_event(let ev):
|
case .nostr_event(let ev):
|
||||||
switch ev {
|
switch ev {
|
||||||
case .event(_, let 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):
|
case .notice(let msg):
|
||||||
print(msg)
|
print(msg)
|
||||||
}
|
}
|
||||||
@@ -50,3 +125,21 @@ struct ContentView_Previews: PreviewProvider {
|
|||||||
ContentView()
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ enum NostrTag {
|
|||||||
case key_event(KeyEvent)
|
case key_event(KeyEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NostrSubscription {
|
||||||
|
let sub_id: String
|
||||||
|
let filter: NostrFilter
|
||||||
|
}
|
||||||
|
|
||||||
struct NostrFilter: Codable {
|
struct NostrFilter: Codable {
|
||||||
let ids: [String]?
|
let ids: [String]?
|
||||||
let kinds: [String]?
|
let kinds: [String]?
|
||||||
@@ -114,8 +119,8 @@ class NostrConnection: WebSocketDelegate {
|
|||||||
socket.disconnect()
|
socket.disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(_ filter: NostrFilter) {
|
func send(_ filter: NostrFilter, sub_id: String) {
|
||||||
guard let req = make_nostr_req(filter) else {
|
guard let req = make_nostr_req(filter, sub_id: sub_id) else {
|
||||||
print("failed to encode nostr req: \(filter)")
|
print("failed to encode nostr req: \(filter)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -165,14 +170,7 @@ func decode_data<T: Decodable>(_ data: Data) -> T? {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func make_nostr_req(_ filter: NostrFilter) -> String? {
|
func make_nostr_req(_ filter: NostrFilter, sub_id: String) -> String? {
|
||||||
let sub_id = UUID()
|
|
||||||
var params: [Encodable] = []
|
|
||||||
|
|
||||||
params.append("REQ")
|
|
||||||
params.append(sub_id)
|
|
||||||
params.append(filter)
|
|
||||||
|
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
guard let filter_json = try? encoder.encode(filter) else {
|
guard let filter_json = try? encoder.encode(filter) else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
20
damus/Views/PostView.swift
Normal file
20
damus/Views/PostView.swift
Normal file
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user