mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 01:40:12 +01:00
wip
This commit is contained in:
parent
5429d5d7cd
commit
bff110b425
@ -6,6 +6,7 @@
|
||||
import AppIntents
|
||||
import SwiftUI
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
struct PriceIntent: AppIntent {
|
||||
// MARK: - Intent Metadata
|
||||
|
||||
@ -60,7 +61,7 @@ struct PriceIntent: AppIntent {
|
||||
price: "N/A",
|
||||
lastUpdated: "--",
|
||||
currencySymbol: getCurrencySymbol(for: selectedFiatCurrency.rawValue),
|
||||
dataSource: "Error fetching data"
|
||||
dataSource: "Error fetching data")
|
||||
|
||||
|
||||
return .result(
|
||||
|
@ -9,7 +9,7 @@
|
||||
import SwiftUICore
|
||||
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
@available(iOS 16.0, *)
|
||||
struct PriceWidgetEntryView: View {
|
||||
let entry: PriceWidgetEntry
|
||||
|
||||
|
@ -9,137 +9,182 @@
|
||||
import SwiftUI
|
||||
import WidgetKit
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
@available(iOS 16.0, *)
|
||||
struct PriceView: View {
|
||||
var entry: PriceWidgetEntry
|
||||
|
||||
var body: some View {
|
||||
switch entry.family {
|
||||
case .accessoryInline, .accessoryCircular, .accessoryRectangular:
|
||||
getView(for: entry.family)
|
||||
default:
|
||||
defaultView.background(Color(UIColor.systemBackground))
|
||||
var entry: PriceWidgetEntry
|
||||
|
||||
var body: some View {
|
||||
switch entry.family {
|
||||
case .accessoryInline, .accessoryCircular, .accessoryRectangular:
|
||||
if #available(iOSApplicationExtension 16.0, *) {
|
||||
wrappedView(for: getView(for: entry.family), family: entry.family)
|
||||
} else {
|
||||
getView(for: entry.family)
|
||||
}
|
||||
default:
|
||||
defaultView.background(Color(UIColor.systemBackground))
|
||||
}
|
||||
}
|
||||
|
||||
private func getView(for family: WidgetFamily) -> some View {
|
||||
switch family {
|
||||
case .accessoryCircular:
|
||||
return AnyView(accessoryCircularView)
|
||||
case .accessoryInline:
|
||||
return AnyView(accessoryInlineView)
|
||||
case .accessoryRectangular:
|
||||
return AnyView(accessoryRectangularView)
|
||||
default:
|
||||
return AnyView(defaultView)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func wrappedView<Content: View>(for content: Content, family: WidgetFamily) -> some View {
|
||||
if #available(iOSApplicationExtension 16.0, *) {
|
||||
ZStack {
|
||||
if family == .accessoryRectangular {
|
||||
AccessoryWidgetBackground()
|
||||
.background(Color(UIColor.systemBackground))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
} else {
|
||||
AccessoryWidgetBackground()
|
||||
}
|
||||
content
|
||||
}
|
||||
} else {
|
||||
content
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func getView(for family: WidgetFamily) -> some View {
|
||||
switch family {
|
||||
case .accessoryCircular:
|
||||
accessoryCircularView
|
||||
case .accessoryInline:
|
||||
accessoryInlineView
|
||||
case .accessoryRectangular:
|
||||
accessoryRectangularView
|
||||
default:
|
||||
defaultView
|
||||
}
|
||||
|
||||
private var accessoryCircularView: some View {
|
||||
let priceString = formattedPriceString(from: entry.currentMarketData?.rate)
|
||||
let priceChangePercentage = formattedPriceChangePercentage(currentRate: entry.currentMarketData?.rate, previousRate: entry.previousMarketData?.rate)
|
||||
|
||||
return VStack(alignment: .center, spacing: 4) {
|
||||
Text("BTC")
|
||||
.font(.caption)
|
||||
.minimumScaleFactor(0.1)
|
||||
Text(priceString)
|
||||
.font(.body)
|
||||
.minimumScaleFactor(0.1)
|
||||
.lineLimit(1)
|
||||
if let priceChangePercentage = priceChangePercentage {
|
||||
Text(priceChangePercentage)
|
||||
.font(.caption2)
|
||||
.foregroundColor(priceChangePercentage.contains("-") ? .red : .green)
|
||||
}
|
||||
}
|
||||
.widgetURL(URL(string: "bluewallet://marketprice"))
|
||||
}
|
||||
|
||||
private var accessoryInlineView: some View {
|
||||
let priceString = formattedCurrencyString(from: entry.currentMarketData?.rate)
|
||||
let priceChangePercentage = formattedPriceChangePercentage(currentRate: entry.currentMarketData?.rate, previousRate: entry.previousMarketData?.rate)
|
||||
|
||||
return HStack {
|
||||
Text(priceString)
|
||||
.font(.body)
|
||||
.minimumScaleFactor(0.1)
|
||||
if let priceChangePercentage = priceChangePercentage {
|
||||
Image(systemName: priceChangePercentage.contains("-") ? "arrow.down" : "arrow.up")
|
||||
.foregroundColor(priceChangePercentage.contains("-") ? .red : .green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var accessoryRectangularView: some View {
|
||||
let currentPrice = formattedCurrencyString(from: entry.currentMarketData?.rate)
|
||||
|
||||
return VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Bitcoin (\(Currency.getUserPreferredCurrency()))")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
HStack {
|
||||
Text(currentPrice)
|
||||
.font(.caption)
|
||||
.fontWeight(.bold)
|
||||
if let currentMarketDataRate = entry.currentMarketData?.rate,
|
||||
let previousMarketDataRate = entry.previousMarketData?.rate,
|
||||
currentMarketDataRate != previousMarketDataRate {
|
||||
Image(systemName: currentMarketDataRate > previousMarketDataRate ? "arrow.up" : "arrow.down")
|
||||
}
|
||||
}
|
||||
|
||||
if let previousMarketDataPrice = entry.previousMarketData?.price, Int(entry.currentMarketData?.rate ?? 0) != Int(entry.previousMarketData?.rate ?? 0) {
|
||||
Text("From \(previousMarketDataPrice)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
Text("at \(entry.currentMarketData?.formattedDate ?? "--")")
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
private var accessoryCircularView: some View {
|
||||
let priceString = (entry.currentMarketData?.rate ?? 0).formattedPriceString()
|
||||
let priceChangePercentage = formattedPriceChangePercentage(currentRate: entry.currentMarketData?.rate, previousRate: entry.previousMarketData?.rate)
|
||||
|
||||
return VStack(alignment: .center, spacing: 4) {
|
||||
Text("BTC")
|
||||
.font(.caption)
|
||||
.minimumScaleFactor(0.1)
|
||||
Text(priceString)
|
||||
.font(.body)
|
||||
.minimumScaleFactor(0.1)
|
||||
.lineLimit(1)
|
||||
if let priceChangePercentage = priceChangePercentage {
|
||||
Text(priceChangePercentage)
|
||||
.font(.caption2)
|
||||
.foregroundColor(priceChangePercentage.contains("-") ? .red : .green)
|
||||
}
|
||||
.padding(.all, 8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Color(UIColor.systemBackground))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
}
|
||||
|
||||
private var defaultView: some View {
|
||||
VStack(alignment: .trailing, spacing: nil, content: {
|
||||
Text("Last Updated").font(Font.system(size: 11, weight: .regular)).foregroundColor(Color(UIColor.lightGray))
|
||||
HStack(alignment: .lastTextBaseline, spacing: nil, content: {
|
||||
Text(entry.currentMarketData?.formattedDate ?? "").lineLimit(1).foregroundColor(.primary).font(Font.system(size: 13, weight: .regular)).minimumScaleFactor(0.01).transition(.opacity)
|
||||
})
|
||||
Spacer()
|
||||
VStack(alignment: .trailing, spacing: 16, content: {
|
||||
HStack(alignment: .lastTextBaseline, spacing: nil, content: {
|
||||
Text(entry.currentMarketData?.price ?? "").lineLimit(1).foregroundColor(.primary).font(Font.system(size: 28, weight: .bold)).minimumScaleFactor(0.01).transition(.opacity)
|
||||
})
|
||||
if let previousMarketDataPrice = entry.previousMarketData?.price, let currentMarketDataRate = entry.currentMarketData?.rate, let previousMarketDataRate = entry.previousMarketData?.rate, previousMarketDataRate > 0, currentMarketDataRate != previousMarketDataRate {
|
||||
HStack(alignment: .lastTextBaseline, spacing: nil, content: {
|
||||
Image(systemName: currentMarketDataRate > previousMarketDataRate ? "arrow.up" : "arrow.down")
|
||||
Text("from").lineLimit(1).foregroundColor(.primary).font(Font.system(size: 13, weight: .regular)).minimumScaleFactor(0.01)
|
||||
Text(previousMarketDataPrice).lineLimit(1).foregroundColor(.primary).font(Font.system(size: 13, weight: .regular)).minimumScaleFactor(0.01)
|
||||
}).transition(.slide)
|
||||
}
|
||||
.widgetURL(URL(string: "bluewallet://marketprice"))
|
||||
}
|
||||
|
||||
private var accessoryInlineView: some View {
|
||||
let priceString = (entry.currentMarketData?.rate ?? 0).formattedCurrencyString()
|
||||
let priceChangePercentage = formattedPriceChangePercentage(currentRate: entry.currentMarketData?.rate, previousRate: entry.previousMarketData?.rate)
|
||||
|
||||
return HStack {
|
||||
Text(priceString)
|
||||
.font(.body)
|
||||
.minimumScaleFactor(0.1)
|
||||
if let priceChangePercentage = priceChangePercentage {
|
||||
Image(systemName: priceChangePercentage.contains("-") ? "arrow.down" : "arrow.up")
|
||||
.foregroundColor(priceChangePercentage.contains("-") ? .red : .green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var accessoryRectangularView: some View {
|
||||
let currentPrice = (entry.currentMarketData?.rate ?? 0).formattedCurrencyString()
|
||||
|
||||
return VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Bitcoin (\(Currency.getUserPreferredCurrency()))")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
HStack {
|
||||
Text(currentPrice)
|
||||
.font(.caption)
|
||||
.fontWeight(.bold)
|
||||
if let currentRate = entry.currentMarketData?.rate,
|
||||
let previousRate = entry.previousMarketData?.rate,
|
||||
currentRate != previousRate {
|
||||
Image(systemName: currentRate > previousRate ? "arrow.up" : "arrow.down")
|
||||
}
|
||||
}
|
||||
|
||||
if let previousPrice = entry.previousMarketData?.price,
|
||||
let currentRate = entry.currentMarketData?.rate,
|
||||
let previousRate = entry.previousMarketData?.rate,
|
||||
currentRate != previousRate {
|
||||
Text("From \(previousPrice)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
Text("at \(entry.currentMarketData?.formattedDate ?? "--")")
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding(.all, 8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Color(UIColor.systemBackground))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||
}
|
||||
|
||||
private var defaultView: some View {
|
||||
VStack(alignment: .trailing, spacing: nil) {
|
||||
Text("Last Updated").font(Font.system(size: 11, weight: .regular)).foregroundColor(Color(UIColor.lightGray))
|
||||
HStack(alignment: .lastTextBaseline, spacing: nil) {
|
||||
Text(entry.currentMarketData?.formattedDate ?? "").lineLimit(1).foregroundColor(.primary).font(Font.system(size: 13, weight: .regular)).minimumScaleFactor(0.01).transition(.opacity)
|
||||
}
|
||||
Spacer()
|
||||
VStack(alignment: .trailing, spacing: 16) {
|
||||
HStack(alignment: .lastTextBaseline, spacing: nil) {
|
||||
Text(entry.currentMarketData?.price ?? "").lineLimit(1).foregroundColor(.primary).font(Font.system(size: 28, weight: .bold)).minimumScaleFactor(0.01).transition(.opacity)
|
||||
}
|
||||
if let previousPrice = entry.previousMarketData?.price,
|
||||
let currentRate = entry.currentMarketData?.rate,
|
||||
let previousRate = entry.previousMarketData?.rate,
|
||||
previousRate > 0, currentRate != previousRate {
|
||||
HStack(alignment: .lastTextBaseline, spacing: nil) {
|
||||
Image(systemName: currentRate > previousRate ? "arrow.up" : "arrow.down")
|
||||
Text("from").lineLimit(1).foregroundColor(.primary).font(Font.system(size: 13, weight: .regular)).minimumScaleFactor(0.01)
|
||||
Text(previousPrice).lineLimit(1).foregroundColor(.primary).font(Font.system(size: 13, weight: .regular)).minimumScaleFactor(0.01)
|
||||
}.transition(.slide)
|
||||
}
|
||||
}
|
||||
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .trailing).padding()
|
||||
}
|
||||
|
||||
private func formattedPriceChangePercentage(currentRate: Double?, previousRate: Double?) -> (change: Double, formattedString: String)? {
|
||||
guard let currentRate = currentRate, let previousRate = previousRate, previousRate > 0 else { return nil }
|
||||
let change = ((currentRate - previousRate) / previousRate) * 100
|
||||
guard change != 0 else { return nil }
|
||||
let formattedString = String(format: "%+.1f%%", change)
|
||||
return (change, formattedString)
|
||||
}
|
||||
}
|
||||
})
|
||||
}).frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .trailing).padding()
|
||||
}
|
||||
|
||||
private func formattedPriceString(from rate: Double?) -> String {
|
||||
let numberFormatter = NumberFormatter()
|
||||
numberFormatter.numberStyle = .decimal
|
||||
numberFormatter.maximumFractionDigits = 0
|
||||
return numberFormatter.string(from: NSNumber(value: rate ?? 0)) ?? "--"
|
||||
}
|
||||
|
||||
private func formattedCurrencyString(from rate: Double?) -> String {
|
||||
let numberFormatter = NumberFormatter()
|
||||
numberFormatter.maximumFractionDigits = 0
|
||||
numberFormatter.numberStyle = .currency
|
||||
numberFormatter.currencySymbol = fiatUnit(currency: Currency.getUserPreferredCurrency())?.symbol
|
||||
return numberFormatter.string(from: NSNumber(value: rate ?? 0)) ?? "--"
|
||||
}
|
||||
|
||||
private func formattedPriceChangePercentage(currentRate: Double?, previousRate: Double?) -> String? {
|
||||
guard let currentRate = currentRate, let previousRate = previousRate, previousRate > 0 else { return nil }
|
||||
let change = ((currentRate - previousRate) / previousRate) * 100
|
||||
return change == 0 ? nil : String(format: "%+.1f%%", change)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
struct PriceView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
Group {
|
||||
PriceView(entry: PriceWidgetEntry(date: Date(), family: .systemSmall, currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00"), previousMarketData: emptyMarketData))
|
||||
.previewContext(WidgetPreviewContext(family: .systemSmall)).padding()
|
||||
if #available(iOSApplicationExtension 16.0, *) {
|
||||
PriceView(entry: PriceWidgetEntry(date: Date(), family: .accessoryCircular, currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00"), previousMarketData: emptyMarketData))
|
||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||
PriceView(entry: PriceWidgetEntry(date: Date(), family: .accessoryInline, currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00"), previousMarketData: emptyMarketData))
|
||||
.previewContext(WidgetPreviewContext(family: .accessoryInline))
|
||||
PriceView(entry: PriceWidgetEntry(date: Date(), family: .accessoryRectangular, currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00"), previousMarketData: emptyMarketData))
|
||||
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user