lnlink

iOS app for connecting to lightning nodes
git clone git://jb55.com/lnlink
Log | Files | Refs | Submodules | README | LICENSE

commit fb2575e62a436cfcbb5e37b705614f898307d4e7
parent f59c73be0c84461bbc1fda0722dd89056d9d986c
Author: William Casarin <jb55@jb55.com>
Date:   Sun,  6 Mar 2022 02:12:08 -0800

settings view, better number formatting

also support feature :)

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

Diffstat:
Mlightninglink.xcodeproj/project.pbxproj | 8++++++--
Mlightninglink/Views/ContentView.swift | 54+++++++++++++++++++++++++++++++++++++-----------------
Mlightninglink/Views/PayView.swift | 28++++++++++++++++++++++------
Alightninglink/Views/SettingsView.swift | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlightninglink/Views/SetupView.swift | 6+++++-
5 files changed, 132 insertions(+), 26 deletions(-)

diff --git a/lightninglink.xcodeproj/project.pbxproj b/lightninglink.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 4C035A0027AEF90000FF92CE /* PayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0359FF27AEF90000FF92CE /* PayView.swift */; }; 4C035A0427AEFD2F00FF92CE /* Invoice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C035A0327AEFD2F00FF92CE /* Invoice.swift */; }; + 4C3DC97127D4829A00773021 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3DC97027D4829A00773021 /* SettingsView.swift */; }; 4C641D192788FF2F002A36C9 /* lightninglinkApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C641D182788FF2F002A36C9 /* lightninglinkApp.swift */; }; 4C641D1B2788FF2F002A36C9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C641D1A2788FF2F002A36C9 /* ContentView.swift */; }; 4C641D1D2788FF30002A36C9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4C641D1C2788FF30002A36C9 /* Assets.xcassets */; }; @@ -50,6 +51,7 @@ 4C0359FE27AEEE8500FF92CE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 4C0359FF27AEF90000FF92CE /* PayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayView.swift; sourceTree = "<group>"; }; 4C035A0327AEFD2F00FF92CE /* Invoice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Invoice.swift; sourceTree = "<group>"; }; + 4C3DC97027D4829A00773021 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; 4C641D152788FF2F002A36C9 /* lightninglink.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = lightninglink.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4C641D182788FF2F002A36C9 /* lightninglinkApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lightninglinkApp.swift; sourceTree = "<group>"; }; 4C641D1A2788FF2F002A36C9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; @@ -207,6 +209,7 @@ 4C0359FF27AEF90000FF92CE /* PayView.swift */, 4C641D1A2788FF2F002A36C9 /* ContentView.swift */, 4CCB0E2A27CA71CA0026461C /* SetupView.swift */, + 4C3DC97027D4829A00773021 /* SettingsView.swift */, ); path = Views; sourceTree = "<group>"; @@ -354,6 +357,7 @@ 4C641D192788FF2F002A36C9 /* lightninglinkApp.swift in Sources */, 4CCB0E2B27CA71CA0026461C /* SetupView.swift in Sources */, 4C873FD727A6F1F5008C972C /* RPC.swift in Sources */, + 4C3DC97127D4829A00773021 /* SettingsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -549,7 +553,7 @@ "$(inherited)", "$(PROJECT_DIR)/lnsocket/target/ios", ); - MARKETING_VERSION = 0.1.2; + MARKETING_VERSION = 0.2; PRODUCT_BUNDLE_IDENTIFIER = com.jb55.lightninglink; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -589,7 +593,7 @@ "$(inherited)", "$(PROJECT_DIR)/lnsocket/target/ios", ); - MARKETING_VERSION = 0.1.2; + MARKETING_VERSION = 0.2; PRODUCT_BUNDLE_IDENTIFIER = com.jb55.lightninglink; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/lightninglink/Views/ContentView.swift b/lightninglink/Views/ContentView.swift @@ -12,6 +12,14 @@ extension Notification.Name { static var sentPayment: Notification.Name { return Notification.Name("did send payment") } + + static var reset: Notification.Name { + return Notification.Name("reset lnlink") + } + + static var donate: Notification.Name { + return Notification.Name("donate") + } } enum ActiveAlert: Identifiable { @@ -115,30 +123,32 @@ struct ContentView: View { } func main_content() -> some View { + NavigationView { VStack { VStack { - HStack { - VStack { - Text(self.dashboard.info.alias) - .font(.title) - } + HStack { + VStack { + Text(self.dashboard.info.alias) + .font(.title) + } - Spacer() + Spacer() - Button("Reset") { - reset_lnlink() - self.is_reset = true + NavigationLink(destination: SettingsView()) { + Label("", systemImage: "gear") + .font(.system(size: 24)) + .foregroundColor(.gray) + } } - } - HStack { - Text("\(self.dashboard.info.msatoshi_fees_collected / 1000) sats earned") - .font(.footnote) - .foregroundColor(.gray) + HStack { + Text("\(self.dashboard.info.msatoshi_fees_collected / 1000) sats earned") + .font(.footnote) + .foregroundColor(.gray) - Spacer() - } - } + Spacer() + } + } .padding() Spacer() @@ -212,6 +222,16 @@ struct ContentView: View { self.active_sheet = nil refresh_funds() } + .onReceive(NotificationCenter.default.publisher(for: .reset)) { _ in + self.is_reset = true + } + .onReceive(NotificationCenter.default.publisher(for: .donate)) { _ in + self.active_sheet = .pay(.offer, "lno1pfsycnjvd9hxkgrfwvsxvun9v5s8xmmxw3mkzun9yysyyateypkk2grpyrcflrd6ypek7gzfyp3kzm3qvdhkuarfde6k2grd0ysxzmrrda5x7mrfwdkj6en4v4kx2epqvdhkg6twvusxzerkv4h8gatjv4eju9q2d3hxc6twdvhxzursrcs08sggen2ndwzjdpqlpfw9sgfth8n9sjs7kjfssrnurnp5lqk66u0sgr32zxwrh0kmxnvmt5hyn0my534209573mp9ck5ekvywvugm5x3kq8ztex8yumafeft0arh6dke04jqgckmdzekqxegxzhecl23lurrj") + } + .navigationBarTitle("", displayMode: .inline) + .navigationBarHidden(true) + + } } diff --git a/lightninglink/Views/PayView.swift b/lightninglink/Views/PayView.swift @@ -115,6 +115,7 @@ struct PayView: View { let invoice = self.invoice! if invoice.description != nil { Text(invoice.description!) + .multilineTextAlignment(.center) .padding() } @@ -179,10 +180,20 @@ struct PayView: View { } func handle_custom_receive(_ new_val: String) { - let ok = new_val.allSatisfy { $0 >= "0" && $0 <= "9" } + if new_val == "" { + self.custom_amount_input = "" + return + } + + let ok = new_val.allSatisfy { $0 == "," || ($0 >= "0" && $0 <= "9") } if ok { - self.custom_amount_input = new_val - let msats = (Int64(new_val) ?? 0) * 1000 + let num_fmt = NumberFormatter() + num_fmt.numberStyle = .decimal + + let filtered = new_val.filter { $0 >= "0" && $0 <= "9" } + let sats = Int64(filtered) ?? 0 + let msats = sats * 1000 + self.custom_amount_input = num_fmt.string(from: NSNumber(value: sats)) ?? new_val self.custom_amount_msats = msats } } @@ -272,7 +283,7 @@ struct PayView: View { Form { Section { HStack(alignment: .lastTextBaseline) { - TextField("100", text: $custom_amount_input) + TextField("10,000", text: $custom_amount_input) .font(.title) .keyboardType(.numberPad) .multilineTextAlignment(.trailing) @@ -566,11 +577,16 @@ func render_amount(_ amt: InvoiceAmount) -> String { } func render_amount_msats(_ amount: Int64) -> String { + let formatter = NumberFormatter() + formatter.numberStyle = .decimal + if amount < 1000 { - return "\(amount) msats" + let amt_str = formatter.string(from: NSNumber(value: amount))! + return "\(amt_str) msats" } - return "\(amount / 1000) sats" + let amt_str = formatter.string(from: NSNumber(value: amount / 1000))! + return "\(amt_str) sats" } /* diff --git a/lightninglink/Views/SettingsView.swift b/lightninglink/Views/SettingsView.swift @@ -0,0 +1,62 @@ +// +// SettingsView.swift +// lightninglink +// +// Created by William Casarin on 2022-03-05. +// + +import SwiftUI + + + +struct SettingsView: View { + @State var is_reset: Bool = false + @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> + + func main_view() -> some View { + VStack { + HStack { + Text("Settings") + .font(.largeTitle) + .fontWeight(.bold) + Spacer() + } + + Form { + Section(header: Text("Connection settings")) { + Button("Disconnect LNLink") { + reset_lnlink() + self.presentationMode.wrappedValue.dismiss() + NotificationCenter.default.post(name: .reset, object: ()) + } + } + + Section(header: Text("Support")) { + Button("Buy me a 🍺") { + self.presentationMode.wrappedValue.dismiss() + NotificationCenter.default.post(name: .donate, object: ()) + } + } + + } + .frame(height: 200) + + Spacer() + } + .padding() + } + + var body: some View { + if is_reset { + SetupView() + } else { + main_view() + } + } +} + +struct SettingsView_Previews: PreviewProvider { + static var previews: some View { + SettingsView() + } +} diff --git a/lightninglink/Views/SetupView.swift b/lightninglink/Views/SetupView.swift @@ -75,7 +75,11 @@ struct SetupView: View { func setup_view() -> some View { VStack { Text("Connect") - .font(.headline) + .font(.largeTitle) + Text("Scan a LNLink QR Code to connect to your clightning node") + .multilineTextAlignment(.center) + .font(.subheadline) + .foregroundColor(.gray) Spacer()