Merge remote-tracking branches 'github/pr/3066' and 'github/pr/3065'
This commit is contained in:
@@ -116,6 +116,9 @@ class UserSettingsStore: ObservableObject {
|
|||||||
@Setting(key: "dismiss_wallet_high_balance_warning", default_value: false)
|
@Setting(key: "dismiss_wallet_high_balance_warning", default_value: false)
|
||||||
var dismiss_wallet_high_balance_warning: Bool
|
var dismiss_wallet_high_balance_warning: Bool
|
||||||
|
|
||||||
|
@Setting(key: "hide_wallet_balance", default_value: false)
|
||||||
|
var hide_wallet_balance: Bool
|
||||||
|
|
||||||
@Setting(key: "left_handed", default_value: false)
|
@Setting(key: "left_handed", default_value: false)
|
||||||
var left_handed: Bool
|
var left_handed: Bool
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ struct SuggestedUserView: View {
|
|||||||
let target = FollowTarget.pubkey(user.pubkey)
|
let target = FollowTarget.pubkey(user.pubkey)
|
||||||
InnerProfilePicView(url: user.pfp,
|
InnerProfilePicView(url: user.pfp,
|
||||||
fallbackUrl: nil,
|
fallbackUrl: nil,
|
||||||
pubkey: target.pubkey,
|
|
||||||
size: 50,
|
size: 50,
|
||||||
highlight: .none,
|
highlight: .none,
|
||||||
disable_animation: false)
|
disable_animation: false)
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ func pfp_line_width(_ h: Highlight) -> CGFloat {
|
|||||||
struct InnerProfilePicView: View {
|
struct InnerProfilePicView: View {
|
||||||
let url: URL?
|
let url: URL?
|
||||||
let fallbackUrl: URL?
|
let fallbackUrl: URL?
|
||||||
let pubkey: Pubkey
|
|
||||||
let size: CGFloat
|
let size: CGFloat
|
||||||
let highlight: Highlight
|
let highlight: Highlight
|
||||||
let disable_animation: Bool
|
let disable_animation: Bool
|
||||||
@@ -65,16 +64,19 @@ struct InnerProfilePicView: View {
|
|||||||
|
|
||||||
|
|
||||||
struct ProfilePicView: View {
|
struct ProfilePicView: View {
|
||||||
|
@Environment(\.redactionReasons) var redactionReasons
|
||||||
|
|
||||||
let pubkey: Pubkey
|
let pubkey: Pubkey
|
||||||
let size: CGFloat
|
let size: CGFloat
|
||||||
let highlight: Highlight
|
let highlight: Highlight
|
||||||
let profiles: Profiles
|
let profiles: Profiles
|
||||||
let disable_animation: Bool
|
let disable_animation: Bool
|
||||||
let zappability_indicator: Bool
|
let zappability_indicator: Bool
|
||||||
|
let privacy_sensitive: Bool
|
||||||
|
|
||||||
@State var picture: String?
|
@State var picture: String?
|
||||||
|
|
||||||
init(pubkey: Pubkey, size: CGFloat, highlight: Highlight, profiles: Profiles, disable_animation: Bool, picture: String? = nil, show_zappability: Bool? = nil) {
|
init(pubkey: Pubkey, size: CGFloat, highlight: Highlight, profiles: Profiles, disable_animation: Bool, picture: String? = nil, show_zappability: Bool? = nil, privacy_sensitive: Bool = false) {
|
||||||
self.pubkey = pubkey
|
self.pubkey = pubkey
|
||||||
self.profiles = profiles
|
self.profiles = profiles
|
||||||
self.size = size
|
self.size = size
|
||||||
@@ -82,6 +84,15 @@ struct ProfilePicView: View {
|
|||||||
self._picture = State(initialValue: picture)
|
self._picture = State(initialValue: picture)
|
||||||
self.disable_animation = disable_animation
|
self.disable_animation = disable_animation
|
||||||
self.zappability_indicator = show_zappability ?? false
|
self.zappability_indicator = show_zappability ?? false
|
||||||
|
self.privacy_sensitive = privacy_sensitive
|
||||||
|
}
|
||||||
|
|
||||||
|
var privacy_sensitive_pubkey: Pubkey {
|
||||||
|
if privacy_sensitive && redactionReasons.contains(.privacy) {
|
||||||
|
ANON_PUBKEY
|
||||||
|
} else {
|
||||||
|
pubkey
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func get_lnurl() -> String? {
|
func get_lnurl() -> String? {
|
||||||
@@ -90,7 +101,7 @@ struct ProfilePicView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack (alignment: Alignment(horizontal: .trailing, vertical: .bottom)) {
|
ZStack (alignment: Alignment(horizontal: .trailing, vertical: .bottom)) {
|
||||||
InnerProfilePicView(url: get_profile_url(picture: picture, pubkey: pubkey, profiles: profiles), fallbackUrl: URL(string: robohash(pubkey)), pubkey: pubkey, size: size, highlight: highlight, disable_animation: disable_animation)
|
InnerProfilePicView(url: get_profile_url(picture: picture, pubkey: privacy_sensitive_pubkey, profiles: profiles), fallbackUrl: URL(string: robohash(privacy_sensitive_pubkey)), size: size, highlight: highlight, disable_animation: disable_animation)
|
||||||
.onReceive(handle_notify(.profile_updated)) { updated in
|
.onReceive(handle_notify(.profile_updated)) { updated in
|
||||||
guard updated.pubkey == self.pubkey else {
|
guard updated.pubkey == self.pubkey else {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ struct KeySettingsView: View {
|
|||||||
.disabled(true)
|
.disabled(true)
|
||||||
} else {
|
} else {
|
||||||
Text(sec)
|
Text(sec)
|
||||||
|
.privacySensitive()
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 5))
|
.clipShape(RoundedRectangle(cornerRadius: 5))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ struct ZapSettingsView: View {
|
|||||||
Section(NSLocalizedString("NWC wallet", comment: "Title for section in zap settings that controls general NWC wallet settings.")) {
|
Section(NSLocalizedString("NWC wallet", comment: "Title for section in zap settings that controls general NWC wallet settings.")) {
|
||||||
Toggle(NSLocalizedString("Disable high balance warning", comment: "Setting to disable high balance warnings on the user's wallet"), isOn: $settings.dismiss_wallet_high_balance_warning)
|
Toggle(NSLocalizedString("Disable high balance warning", comment: "Setting to disable high balance warnings on the user's wallet"), isOn: $settings.dismiss_wallet_high_balance_warning)
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
|
Toggle(NSLocalizedString("Hide balance", comment: "Setting to hide wallet balance."), isOn: $settings.hide_wallet_balance)
|
||||||
|
.toggleStyle(.switch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(NSLocalizedString("Zaps", comment: "Navigation title for zap settings."))
|
.navigationTitle(NSLocalizedString("Zaps", comment: "Navigation title for zap settings."))
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import SwiftUI
|
|||||||
struct BalanceView: View {
|
struct BalanceView: View {
|
||||||
var balance: Int64?
|
var balance: Int64?
|
||||||
|
|
||||||
|
@Binding var hide_balance: Bool
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 5) {
|
VStack(spacing: 5) {
|
||||||
Text("Current balance", comment: "Label for displaying current wallet balance")
|
Text("Current balance", comment: "Label for displaying current wallet balance")
|
||||||
@@ -28,29 +30,46 @@ struct BalanceView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func numericalBalanceView(text: String) -> some View {
|
func numericalBalanceView(text: String) -> some View {
|
||||||
HStack {
|
Group {
|
||||||
Text(verbatim: text)
|
if hide_balance {
|
||||||
.lineLimit(1)
|
Text(verbatim: "*****")
|
||||||
.minimumScaleFactor(0.70)
|
.lineLimit(1)
|
||||||
.font(.veryVeryLargeTitle)
|
.minimumScaleFactor(0.70)
|
||||||
.fontWeight(.heavy)
|
.font(.veryVeryLargeTitle)
|
||||||
.foregroundStyle(PinkGradient)
|
|
||||||
|
|
||||||
HStack(alignment: .top) {
|
|
||||||
Text("SATS", comment: "Abbreviation for Satoshis, smallest bitcoin unit")
|
|
||||||
.font(.caption)
|
|
||||||
.fontWeight(.heavy)
|
.fontWeight(.heavy)
|
||||||
.foregroundStyle(PinkGradient)
|
.foregroundStyle(PinkGradient)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
HStack {
|
||||||
|
Text(verbatim: text)
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.70)
|
||||||
|
.font(.veryVeryLargeTitle)
|
||||||
|
.fontWeight(.heavy)
|
||||||
|
.foregroundStyle(PinkGradient)
|
||||||
|
|
||||||
|
HStack(alignment: .top) {
|
||||||
|
Text("SATS", comment: "Abbreviation for Satoshis, smallest bitcoin unit")
|
||||||
|
.font(.caption)
|
||||||
|
.fontWeight(.heavy)
|
||||||
|
.foregroundStyle(PinkGradient)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.privacySensitive()
|
||||||
.padding(.bottom)
|
.padding(.bottom)
|
||||||
|
.onTapGesture {
|
||||||
|
hide_balance.toggle()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BalanceView_Previews: PreviewProvider {
|
struct BalanceView_Previews: PreviewProvider {
|
||||||
|
@State private static var hide_balance: Bool = false
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
BalanceView(balance: 100000000)
|
BalanceView(balance: 100000000, hide_balance: $hide_balance)
|
||||||
BalanceView(balance: nil)
|
BalanceView(balance: nil, hide_balance: $hide_balance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ struct NWCSettings: View {
|
|||||||
Toggle(NSLocalizedString("Disable high balance warning", comment: "Setting to disable high balance warnings on the user's wallet"), isOn: $settings.dismiss_wallet_high_balance_warning)
|
Toggle(NSLocalizedString("Disable high balance warning", comment: "Setting to disable high balance warnings on the user's wallet"), isOn: $settings.dismiss_wallet_high_balance_warning)
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
|
|
||||||
|
Toggle(NSLocalizedString("Hide balance", comment: "Setting to hide wallet balance."), isOn: $settings.hide_wallet_balance)
|
||||||
|
.toggleStyle(.switch)
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
self.model.disconnect()
|
self.model.disconnect()
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|||||||
@@ -8,14 +8,18 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct TransactionView: View {
|
struct TransactionView: View {
|
||||||
|
@Environment(\.redactionReasons) var redactionReasons
|
||||||
|
|
||||||
let damus_state: DamusState
|
let damus_state: DamusState
|
||||||
var transaction: WalletConnect.Transaction
|
var transaction: WalletConnect.Transaction
|
||||||
|
|
||||||
|
@Binding var hide_balance: Bool
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
let redactedForPrivacy = redactionReasons.contains(.privacy)
|
||||||
let isIncomingTransaction = transaction.type == "incoming"
|
let isIncomingTransaction = transaction.type == "incoming"
|
||||||
let txType = isIncomingTransaction ? "arrow-bottom-left" : "arrow-top-right"
|
let txType = isIncomingTransaction ? "arrow-bottom-left" : "arrow-top-right"
|
||||||
let txColor = isIncomingTransaction ? DamusColors.success : Color.gray
|
let txColor = (isIncomingTransaction && !hide_balance && !redactedForPrivacy) ? DamusColors.success : Color.gray
|
||||||
let txOp = isIncomingTransaction ? "+" : "-"
|
let txOp = isIncomingTransaction ? "+" : "-"
|
||||||
let created_at = Date.init(timeIntervalSince1970: TimeInterval(transaction.created_at))
|
let created_at = Date.init(timeIntervalSince1970: TimeInterval(transaction.created_at))
|
||||||
let formatter = RelativeDateTimeFormatter()
|
let formatter = RelativeDateTimeFormatter()
|
||||||
@@ -26,21 +30,23 @@ struct TransactionView: View {
|
|||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
ZStack {
|
ZStack {
|
||||||
ProfilePicView(pubkey: pubkey, size: 45, highlight: .custom(.damusAdaptableBlack, 0.1), profiles: damus_state.profiles, disable_animation: damus_state.settings.disable_animation)
|
ProfilePicView(pubkey: pubkey, size: 45, highlight: .custom(.damusAdaptableBlack, 0.1), profiles: damus_state.profiles, disable_animation: damus_state.settings.disable_animation, privacy_sensitive: true)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
damus_state.nav.push(route: Route.ProfileByKey(pubkey: pubkey))
|
damus_state.nav.push(route: Route.ProfileByKey(pubkey: pubkey))
|
||||||
}
|
}
|
||||||
|
|
||||||
Image(txType)
|
if !hide_balance && !redactedForPrivacy {
|
||||||
.resizable()
|
Image(txType)
|
||||||
.frame(width: 18, height: 18)
|
.resizable()
|
||||||
.foregroundColor(.white)
|
.frame(width: 18, height: 18)
|
||||||
.padding(2)
|
.foregroundColor(.white)
|
||||||
.background(txColor)
|
.padding(2)
|
||||||
.clipShape(Circle())
|
.background(txColor)
|
||||||
.overlay(Circle().stroke(Color.damusAdaptableWhite, lineWidth: 1.0))
|
.clipShape(Circle())
|
||||||
.padding(.top, 25)
|
.overlay(Circle().stroke(Color.damusAdaptableWhite, lineWidth: 1.0))
|
||||||
.padding(.leading, 35)
|
.padding(.top, 25)
|
||||||
|
.padding(.leading, 35)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
@@ -58,10 +64,17 @@ struct TransactionView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Text(verbatim: "\(txOp) \(format_msats(transaction.amount))")
|
if hide_balance {
|
||||||
.font(.headline)
|
Text(verbatim: "*****")
|
||||||
.foregroundColor(txColor)
|
.font(.headline)
|
||||||
.bold()
|
.foregroundColor(txColor)
|
||||||
|
.bold()
|
||||||
|
} else {
|
||||||
|
Text(verbatim: "\(txOp) \(format_msats(transaction.amount))")
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor(txColor)
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, minHeight: 75, alignment: .center)
|
.frame(maxWidth: .infinity, minHeight: 75, alignment: .center)
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
@@ -107,27 +120,32 @@ struct TransactionsView: View {
|
|||||||
transactions?.sorted(by: { $0.created_at > $1.created_at })
|
transactions?.sorted(by: { $0.created_at > $1.created_at })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Binding var hide_balance: Bool
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
Text("Latest transactions", comment: "Heading for latest wallet transactions list")
|
Text("Latest transactions", comment: "Heading for latest wallet transactions list")
|
||||||
.foregroundStyle(DamusColors.neutral6)
|
.foregroundStyle(DamusColors.neutral6)
|
||||||
|
|
||||||
if let sortedTransactions {
|
Group {
|
||||||
if sortedTransactions.isEmpty {
|
if let sortedTransactions {
|
||||||
emptyTransactions
|
if sortedTransactions.isEmpty {
|
||||||
} else {
|
emptyTransactions
|
||||||
ForEach(sortedTransactions, id: \.self) { transaction in
|
} else {
|
||||||
TransactionView(damus_state: damus_state, transaction: transaction)
|
ForEach(sortedTransactions, id: \.self) { transaction in
|
||||||
|
TransactionView(damus_state: damus_state, transaction: transaction, hide_balance: $hide_balance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Make sure we do not show "No transactions yet" to the user when still loading (or when failed to load)
|
||||||
|
// This is important because if we show that when things are not loaded properly, we risk scaring the user into thinking that they have lost funds.
|
||||||
|
emptyTransactions
|
||||||
|
.redacted(reason: .placeholder)
|
||||||
|
.shimmer(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
.privacySensitive()
|
||||||
// Make sure we do not show "No transactions yet" to the user when still loading (or when failed to load)
|
|
||||||
// This is important because if we show that when things are not loaded properly, we risk scaring the user into thinking that they have lost funds.
|
|
||||||
emptyTransactions
|
|
||||||
.redacted(reason: .placeholder)
|
|
||||||
.shimmer(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +173,9 @@ struct TransactionsView_Previews: PreviewProvider {
|
|||||||
static let transaction4: WalletConnect.Transaction = WalletConnect.Transaction(type: "incoming", invoice: "", description: "", description_hash: "", preimage: "", payment_hash: "1234567890662", amount: 720000, fees_paid: 0, created_at: 1737090300, expires_at: 0, settled_at: 0, metadata: nil)
|
static let transaction4: WalletConnect.Transaction = WalletConnect.Transaction(type: "incoming", invoice: "", description: "", description_hash: "", preimage: "", payment_hash: "1234567890662", amount: 720000, fees_paid: 0, created_at: 1737090300, expires_at: 0, settled_at: 0, metadata: nil)
|
||||||
static var test_transactions: [WalletConnect.Transaction] = [transaction1, transaction2, transaction3, transaction4]
|
static var test_transactions: [WalletConnect.Transaction] = [transaction1, transaction2, transaction3, transaction4]
|
||||||
|
|
||||||
|
@State private static var hide_balance: Bool = false
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
TransactionsView(damus_state: tds, transactions: test_transactions)
|
TransactionsView(damus_state: tds, transactions: test_transactions, hide_balance: $hide_balance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ struct WalletView: View {
|
|||||||
@State var show_settings: Bool = false
|
@State var show_settings: Bool = false
|
||||||
@ObservedObject var model: WalletModel
|
@ObservedObject var model: WalletModel
|
||||||
@ObservedObject var settings: UserSettingsStore
|
@ObservedObject var settings: UserSettingsStore
|
||||||
|
@State private var showBalance: Bool = false
|
||||||
|
|
||||||
init(damus_state: DamusState, model: WalletModel? = nil) {
|
init(damus_state: DamusState, model: WalletModel? = nil) {
|
||||||
self.damus_state = damus_state
|
self.damus_state = damus_state
|
||||||
@@ -47,6 +48,7 @@ struct WalletView: View {
|
|||||||
.bold()
|
.bold()
|
||||||
.foregroundStyle(.damusWarningTertiary)
|
.foregroundStyle(.damusWarningTertiary)
|
||||||
}
|
}
|
||||||
|
.privacySensitive()
|
||||||
.padding()
|
.padding()
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 20)
|
RoundedRectangle(cornerRadius: 20)
|
||||||
@@ -56,9 +58,9 @@ struct WalletView: View {
|
|||||||
|
|
||||||
VStack(spacing: 5) {
|
VStack(spacing: 5) {
|
||||||
|
|
||||||
BalanceView(balance: model.balance)
|
BalanceView(balance: model.balance, hide_balance: $settings.hide_wallet_balance)
|
||||||
|
|
||||||
TransactionsView(damus_state: damus_state, transactions: model.transactions)
|
TransactionsView(damus_state: damus_state, transactions: model.transactions, hide_balance: $settings.hide_wallet_balance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(NSLocalizedString("Wallet", comment: "Navigation title for Wallet view"))
|
.navigationTitle(NSLocalizedString("Wallet", comment: "Navigation title for Wallet view"))
|
||||||
|
|||||||
Reference in New Issue
Block a user