edit relays

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2022-06-09 13:47:25 -07:00
parent e104de6431
commit 6de7d7ae58
7 changed files with 329 additions and 36 deletions

View File

@@ -0,0 +1,61 @@
//
// TextFieldAlert.swift
// damus
//
// Created by William Casarin on 2022-06-09.
//
import SwiftUI
struct TextFieldAlert<Presenting>: View where Presenting: View {
@Binding var isShowing: Bool
@Binding var text: String
let presenting: Presenting
let title: String
var body: some View {
GeometryReader { (deviceSize: GeometryProxy) in
ZStack {
self.presenting
.disabled(isShowing)
VStack {
Text(self.title)
TextField("Relay", text: self.$text)
Divider()
HStack {
Button(action: {
withAnimation {
self.isShowing.toggle()
}
}) {
Text("Dismiss")
}
}
}
.padding()
.background(Color.white)
.frame(
width: deviceSize.size.width*0.7,
height: deviceSize.size.height*0.7
)
.shadow(radius: 1)
.opacity(self.isShowing ? 1 : 0)
}
}
}
}
extension View {
func textFieldAlert(isShowing: Binding<Bool>,
text: Binding<String>,
title: String) -> some View {
TextFieldAlert(isShowing: isShowing,
text: text,
presenting: self,
title: title)
}
}

View File

@@ -63,7 +63,7 @@ struct ContentView: View {
var LoadingContainer: some View {
VStack {
HStack {
HStack(alignment: .center) {
Spacer()
if home.signal.signal != home.signal.max_signal {
@@ -71,6 +71,11 @@ struct ContentView: View {
.font(.callout)
.foregroundColor(.gray)
}
NavigationLink(destination: ConfigView(state: damus_state!)) {
Label("", systemImage: "gear")
}
.buttonStyle(PlainButtonStyle())
}
Spacer()
@@ -91,36 +96,32 @@ struct ContentView: View {
}
func MainContent(damus: DamusState) -> some View {
NavigationView {
VStack {
NavigationLink(destination: MaybeProfileView, isActive: $profile_open) {
EmptyView()
}
NavigationLink(destination: MaybeThreadView, isActive: $thread_open) {
EmptyView()
}
NavigationLink(destination: MaybeSearchView, isActive: $search_open) {
EmptyView()
}
switch selected_timeline {
case .search:
SearchHomeView(damus_state: damus_state!, model: SearchHomeModel(pool: damus_state!.pool) )
case .home:
PostingTimelineView
case .notifications:
TimelineView(events: $home.notifications, damus: damus)
.navigationTitle("Notifications")
case .none:
EmptyView()
}
VStack {
NavigationLink(destination: MaybeProfileView, isActive: $profile_open) {
EmptyView()
}
NavigationLink(destination: MaybeThreadView, isActive: $thread_open) {
EmptyView()
}
NavigationLink(destination: MaybeSearchView, isActive: $search_open) {
EmptyView()
}
switch selected_timeline {
case .search:
SearchHomeView(damus_state: damus_state!, model: SearchHomeModel(pool: damus_state!.pool) )
case .home:
PostingTimelineView
case .notifications:
TimelineView(events: $home.notifications, damus: damus)
.navigationTitle("Notifications")
case .none:
EmptyView()
}
.navigationBarTitle("Damus", displayMode: .inline)
}
.navigationViewStyle(.stack)
.navigationBarTitle("Damus", displayMode: .inline)
}
var MaybeSearchView: some View {
@@ -159,12 +160,13 @@ struct ContentView: View {
var body: some View {
VStack {
if let damus = self.damus_state {
ZStack {
NavigationView {
MainContent(damus: damus)
.padding([.bottom], -8.0)
LoadingContainer
.toolbar {
LoadingContainer
}
}
.navigationViewStyle(.stack)
}
TabBar(new_notifications: $home.new_notifications, selected: $selected_timeline, action: switch_timeline)

View File

@@ -138,14 +138,52 @@ func decode_json_relays(_ content: String) -> [String: RelayInfo]? {
return decode_json(content)
}
/*
func remove_relay(ev: NostrEvent, privkey: String, relay: String) -> NostrEvent? {
let damus_relay = RelayDescriptor(url: URL(string: "wss://relay.damus.io")!, info: .rw)
var relays = ensure_relay_info(relays: [damus_relay], content: ev.content)
guard relays.index(forKey: relay) != nil else {
return nil
}
relays.removeValue(forKey: relay)
guard let content = encode_json(relays) else {
return nil
}
let new_ev = NostrEvent(content: content, pubkey: ev.pubkey, kind: 3, tags: ev.tags)
new_ev.calculate_id()
new_ev.sign(privkey: privkey)
return new_ev
}
func add_relay(ev: NostrEvent, privkey: String, relay: String, info: RelayInfo) -> NostrEvent? {
let damus_relay = RelayDescriptor(url: URL(string: "wss://relay.damus.io")!, info: .rw)
var relays = ensure_relay_info(relays: [damus_relay], content: ev.content)
guard relays.index(forKey: relay) == nil else {
return nil
}
relays[relay] = info
guard let content = encode_json(relays) else {
return nil
}
let new_ev = NostrEvent(content: content, pubkey: ev.pubkey, kind: 3, tags: ev.tags)
new_ev.calculate_id()
new_ev.sign(privkey: privkey)
return new_ev
}
func ensure_relay_info(relays: [RelayDescriptor], content: String) -> [String: RelayInfo] {
guard let relay_info = decode_json_relays(content) else {
return make_contact_relays(relays)
}
return relay_info
}
*/
func follow_with_existing_contacts(our_pubkey: String, our_contacts: NostrEvent, follow: ReferencedId) -> NostrEvent? {
// don't update if we're already following

View File

@@ -165,7 +165,7 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
public var is_local: Bool {
return (self.flags & 1) != 0
}
init(content: String, pubkey: String, kind: Int = 1, tags: [[String]] = []) {
self.id = ""
self.sig = ""
@@ -176,6 +176,17 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
self.tags = tags
self.created_at = Int64(Date().timeIntervalSince1970)
}
init(from: NostrEvent) {
self.id = from.id
self.sig = from.sig
self.content = from.content
self.pubkey = from.pubkey
self.kind = from.kind
self.tags = from.tags
self.created_at = from.created_at
}
func calculate_id() {
self.id = calculate_event_id(ev: self)

View File

@@ -0,0 +1,55 @@
//
// AddRelayView.swift
// damus
//
// Created by William Casarin on 2022-06-09.
//
import SwiftUI
struct AddRelayView: View {
@Binding var show_add_relay: Bool
@Binding var relay: String
let action: (String?) -> Void
var body: some View {
VStack(alignment: .leading) {
Form {
Section("Add Relay") {
TextField("wss://some.relay.com", text: $relay)
.textInputAutocapitalization(.never)
}
}
VStack {
HStack {
Button("Cancel") {
show_add_relay = false
action(nil)
}
.contentShape(Rectangle())
Spacer()
Button("Add") {
show_add_relay = false
action(relay)
}
.buttonStyle(.borderedProminent)
.contentShape(Rectangle())
}
.padding()
}
}
}
}
struct AddRelayView_Previews: PreviewProvider {
@State static var show: Bool = true
@State static var relay: String = ""
static var previews: some View {
AddRelayView(show_add_relay: $show, relay: $relay, action: {_ in })
}
}

View File

@@ -0,0 +1,106 @@
//
// ConfigView.swift
// damus
//
// Created by William Casarin on 2022-06-09.
//
import SwiftUI
struct ConfigView: View {
let state: DamusState
@Environment(\.dismiss) var dismiss
@State var show_add_relay: Bool = false
@State var new_relay: String = ""
func Relay(_ ev: NostrEvent, relay: String) -> some View {
return Text(relay)
.swipeActions {
if let privkey = state.keypair.privkey {
Button {
guard let new_ev = remove_relay( ev: ev, privkey: privkey, relay: relay) else {
return
}
state.contacts.event = new_ev
state.pool.send(.event(new_ev))
} label: {
Label("Delete", systemImage: "trash")
}
.tint(.red)
}
}
}
var body: some View {
ZStack(alignment: .leading) {
Form {
if let ev = state.contacts.event {
Section("Relays") {
if let relays = decode_json_relays(ev.content) {
List(Array(relays.keys.sorted()), id: \.self) { relay in
Relay(ev, relay: relay)
}
}
}
}
}
VStack {
HStack {
Spacer()
Button(action: { show_add_relay = true }) {
Label("", systemImage: "plus")
.foregroundColor(.accentColor)
.padding()
}
}
Spacer()
}
}
.navigationTitle("Settings")
.navigationBarTitleDisplayMode(.large)
.sheet(isPresented: $show_add_relay) {
AddRelayView(show_add_relay: $show_add_relay, relay: $new_relay) { _ in
guard let url = URL(string: new_relay) else {
return
}
guard let ev = state.contacts.event else {
return
}
guard let privkey = state.keypair.privkey else {
return
}
let info = RelayInfo.rw
guard (try? state.pool.add_relay(url, info: info)) != nil else {
return
}
state.pool.connect(to: [new_relay])
guard let new_ev = add_relay(ev: ev, privkey: privkey, relay: new_relay, info: info) else {
return
}
state.contacts.event = new_ev
state.pool.send(.event(new_ev))
}
}
.onReceive(handle_notify(.switched_timeline)) { _ in
dismiss()
}
}
}
struct ConfigView_Previews: PreviewProvider {
static var previews: some View {
ConfigView(state: test_damus_state())
}
}