This commit implements a new layer called NostrNetworkManager, responsible for managing interactions with the Nostr network, and providing a higher level API that is easier and more secure to use for the layer above it. It also integrates it with the rest of the app, by moving RelayPool and PostBox into NostrNetworkManager, along with all their usages. Changelog-Added: Added NIP-65 relay list support Changelog-Changed: Improved robustness of relay list handling Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
228 lines
8.9 KiB
Swift
228 lines
8.9 KiB
Swift
//
|
|
// NWCSettings.swift
|
|
// damus
|
|
//
|
|
// Created by eric on 1/24/25.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct NWCSettings: View {
|
|
|
|
let damus_state: DamusState
|
|
let nwc: WalletConnectURL
|
|
@ObservedObject var model: WalletModel
|
|
@ObservedObject var settings: UserSettingsStore
|
|
|
|
|
|
func donation_binding() -> Binding<Double> {
|
|
return Binding(get: {
|
|
return Double(model.settings.donation_percent)
|
|
}, set: { v in
|
|
model.settings.donation_percent = Int(v)
|
|
})
|
|
}
|
|
|
|
static let min_donation: Double = 0.0
|
|
static let max_donation: Double = 100.0
|
|
|
|
var percent: Double {
|
|
Double(model.settings.donation_percent) / 100.0
|
|
}
|
|
|
|
var tip_msats: String {
|
|
let msats = Int64(percent * Double(model.settings.default_zap_amount * 1000))
|
|
let s = format_msats_abbrev(msats)
|
|
// TODO: fix formatting and remove this hack
|
|
let parts = s.split(separator: ".")
|
|
if parts.count == 1 {
|
|
return s
|
|
}
|
|
if let end = parts[safe: 1] {
|
|
if end.allSatisfy({ c in c.isNumber }) {
|
|
return String(parts[0])
|
|
} else {
|
|
return s
|
|
}
|
|
}
|
|
return s
|
|
}
|
|
|
|
var SupportDamus: some View {
|
|
ZStack(alignment: .topLeading) {
|
|
RoundedRectangle(cornerRadius: 20)
|
|
.fill(DamusGradient.gradient.opacity(0.5))
|
|
|
|
VStack(alignment: .leading, spacing: 20) {
|
|
HStack {
|
|
Image("logo-nobg")
|
|
.resizable()
|
|
.frame(width: 50, height: 50)
|
|
Text("Support Damus", comment: "Text calling for the user to support Damus through zaps")
|
|
.font(.title.bold())
|
|
.foregroundColor(.white)
|
|
}
|
|
|
|
Text("Help build the future of decentralized communication on the web.", comment: "Text indicating the goal of developing Damus which the user can help with.")
|
|
.fixedSize(horizontal: false, vertical: true)
|
|
.foregroundColor(.white)
|
|
|
|
Text("An additional percentage of each zap will be sent to support Damus development", comment: "Text indicating that they can contribute zaps to support Damus development.")
|
|
.fixedSize(horizontal: false, vertical: true)
|
|
.foregroundColor(.white)
|
|
|
|
let binding = donation_binding()
|
|
|
|
HStack {
|
|
Slider(value: binding,
|
|
in: NWCSettings.min_donation...NWCSettings.max_donation,
|
|
label: { })
|
|
Text("\(Int(binding.wrappedValue))%", comment: "Percentage of additional zap that should be sent to support Damus development.")
|
|
.font(.title.bold())
|
|
.foregroundColor(.white)
|
|
.frame(width: 80)
|
|
}
|
|
|
|
HStack{
|
|
Spacer()
|
|
|
|
VStack {
|
|
HStack {
|
|
Text("\(Image("zap.fill")) \(format_msats_abbrev(Int64(model.settings.default_zap_amount) * 1000))")
|
|
.font(.title)
|
|
.foregroundColor(percent == 0 ? .gray : .yellow)
|
|
.frame(width: 120)
|
|
}
|
|
|
|
Text("Zap", comment: "Text underneath the number of sats indicating that it's the amount used for zaps.")
|
|
.foregroundColor(.white)
|
|
}
|
|
Spacer()
|
|
|
|
Text(verbatim: "+")
|
|
.font(.title)
|
|
.foregroundColor(.white)
|
|
Spacer()
|
|
|
|
VStack {
|
|
HStack {
|
|
Text("\(Image("zap.fill")) \(tip_msats)")
|
|
.font(.title)
|
|
.foregroundColor(percent == 0 ? .gray : Color.yellow)
|
|
.frame(width: 120)
|
|
}
|
|
|
|
Text(verbatim: percent == 0 ? "🩶" : "💜")
|
|
.foregroundColor(.white)
|
|
}
|
|
Spacer()
|
|
}
|
|
|
|
EventProfile(damus_state: damus_state, pubkey: damus_state.pubkey, size: .small)
|
|
}
|
|
.padding(25)
|
|
}
|
|
.frame(height: 370)
|
|
}
|
|
|
|
var body: some View {
|
|
|
|
VStack(alignment: .leading, spacing: 20) {
|
|
|
|
SupportDamus
|
|
.padding(.bottom)
|
|
|
|
AccountDetailsView(nwc: nwc)
|
|
|
|
Button(action: {
|
|
self.model.disconnect()
|
|
}) {
|
|
HStack {
|
|
Text("Disconnect Wallet", comment: "Text for button to disconnect from Nostr Wallet Connect lightning wallet.")
|
|
}
|
|
.frame(minWidth: 300, maxWidth: .infinity, maxHeight: 18, alignment: .center)
|
|
}
|
|
.buttonStyle(GradientButtonStyle())
|
|
}
|
|
.padding()
|
|
.onAppear() {
|
|
model.initial_percent = model.settings.donation_percent
|
|
}
|
|
.onChange(of: model.settings.donation_percent) { p in
|
|
let profile_txn = damus_state.profiles.lookup(id: damus_state.pubkey)
|
|
guard let profile = profile_txn?.unsafeUnownedValue else {
|
|
return
|
|
}
|
|
|
|
let prof = Profile(name: profile.name, display_name: profile.display_name, about: profile.about, picture: profile.picture, banner: profile.banner, website: profile.website, lud06: profile.lud06, lud16: profile.lud16, nip05: profile.nip05, damus_donation: p, reactions: profile.reactions)
|
|
|
|
notify(.profile_updated(.manual(pubkey: self.damus_state.pubkey, profile: prof)))
|
|
}
|
|
.onDisappear {
|
|
let profile_txn = damus_state.profiles.lookup(id: damus_state.pubkey)
|
|
|
|
guard let keypair = damus_state.keypair.to_full(),
|
|
let profile = profile_txn?.unsafeUnownedValue,
|
|
model.initial_percent != profile.damus_donation
|
|
else {
|
|
return
|
|
}
|
|
|
|
let prof = Profile(name: profile.name, display_name: profile.display_name, about: profile.about, picture: profile.picture, banner: profile.banner, website: profile.website, lud06: profile.lud06, lud16: profile.lud16, nip05: profile.nip05, damus_donation: model.settings.donation_percent, reactions: profile.reactions)
|
|
|
|
guard let meta = make_metadata_event(keypair: keypair, metadata: prof) else {
|
|
return
|
|
}
|
|
damus_state.nostrNetwork.postbox.send(meta)
|
|
}
|
|
}
|
|
|
|
struct AccountDetailsView: View {
|
|
let nwc: WalletConnect.ConnectURL
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading) {
|
|
|
|
Text("Account details", comment: "Prompt to ask user if they want to attach their Nostr Wallet Connect lightning wallet.")
|
|
.font(.title2)
|
|
.fontWeight(.bold)
|
|
.multilineTextAlignment(.center)
|
|
.padding(.bottom)
|
|
|
|
Text("Routing", comment: "Label indicating the routing address for Nostr Wallet Connect payments. In other words, the relay used by the NWC wallet provider")
|
|
.font(.headline)
|
|
|
|
Text(nwc.relay.absoluteString)
|
|
.font(.body)
|
|
.fontWeight(.bold)
|
|
.foregroundColor(.gray)
|
|
.padding(.bottom)
|
|
|
|
if let lud16 = nwc.lud16 {
|
|
Text("Account", comment: "Label for the user account information with the Nostr Wallet Connect wallet provider.")
|
|
.font(.headline)
|
|
|
|
Text(lud16)
|
|
.font(.body)
|
|
.fontWeight(.bold)
|
|
.foregroundColor(.gray)
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity, minHeight: 250, alignment: .leading)
|
|
.padding(.horizontal, 20)
|
|
.cornerRadius(10)
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: 25)
|
|
.stroke(DamusColors.neutral3, lineWidth: 2)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
struct NWCSettings_Previews: PreviewProvider {
|
|
static let tds = test_damus_state
|
|
static var previews: some View {
|
|
NWCSettings(damus_state: tds, nwc: test_wallet_connect_url, model: WalletModel(state: .existing(test_wallet_connect_url), settings: tds.settings), settings: tds.settings)
|
|
}
|
|
}
|