diff --git a/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/WalletInformationWidget.xcscheme b/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/WalletInformationWidget.xcscheme index 8a7e785e4..1e52de2d7 100644 --- a/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/WalletInformationWidget.xcscheme +++ b/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/WalletInformationWidget.xcscheme @@ -102,7 +102,7 @@ diff --git a/ios/WalletInformationWidget/WalletInformationWidget.swift b/ios/WalletInformationWidget/WalletInformationWidget.swift index 97270786f..34a277909 100644 --- a/ios/WalletInformationWidget/WalletInformationWidget.swift +++ b/ios/WalletInformationWidget/WalletInformationWidget.swift @@ -10,101 +10,102 @@ import WidgetKit import SwiftUI struct WalletInformationWidgetProvider: TimelineProvider { - typealias Entry = WalletInformationWidgetEntry - static var lastSuccessfulEntry: WalletInformationWidgetEntry? + typealias Entry = WalletInformationWidgetEntry + static var lastSuccessfulEntries: [WalletInformationWidgetEntry] = [] - func placeholder(in context: Context) -> WalletInformationWidgetEntry { - return WalletInformationWidgetEntry.placeholder - } - - func getSnapshot(in context: Context, completion: @escaping (WalletInformationWidgetEntry) -> ()) { - let entry: WalletInformationWidgetEntry - if (context.isPreview) { - entry = WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) - } else { - entry = WalletInformationWidgetEntry(date: Date(), marketData: emptyMarketData) + func placeholder(in context: Context) -> WalletInformationWidgetEntry { + return WalletInformationWidgetEntry.placeholder } - completion(entry) - } - - func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { - var entries: [WalletInformationWidgetEntry] = [] - let userPreferredCurrency = Currency.getUserPreferredCurrency() - let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime()) - - MarketAPI.fetchPrice(currency: userPreferredCurrency) { (result, error) in - let entry: WalletInformationWidgetEntry - - if let result = result { - entry = WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "", sats: "", price: result.formattedRate ?? "!", rate: result.rateDouble), allWalletsBalance: allwalletsBalance) - WalletInformationWidgetProvider.lastSuccessfulEntry = entry - } else { - // Use the last successful entry if available - if let lastEntry = WalletInformationWidgetProvider.lastSuccessfulEntry { - entry = lastEntry + + func getSnapshot(in context: Context, completion: @escaping (WalletInformationWidgetEntry) -> ()) { + let entry: WalletInformationWidgetEntry + if (context.isPreview) { + entry = WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) } else { - // Fallback to a default entry if no successful entry is available - entry = WalletInformationWidgetEntry.placeholder + entry = WalletInformationWidgetEntry(date: Date(), marketData: emptyMarketData) + } + completion(entry) + } + + func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { + var entries: [WalletInformationWidgetEntry] = [] + let userPreferredCurrency = Currency.getUserPreferredCurrency() + let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime()) + + MarketAPI.fetchPrice(currency: userPreferredCurrency) { (result, error) in + let entry: WalletInformationWidgetEntry + + if let result = result { + entry = WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "", sats: "", price: result.formattedRate ?? "!", rate: result.rateDouble), allWalletsBalance: allwalletsBalance) + WalletInformationWidgetProvider.lastSuccessfulEntries.append(entry) + if WalletInformationWidgetProvider.lastSuccessfulEntries.count > 5 { + WalletInformationWidgetProvider.lastSuccessfulEntries.removeFirst() + } + } else { + if let lastEntry = WalletInformationWidgetProvider.lastSuccessfulEntries.last { + entry = lastEntry + } else { + entry = WalletInformationWidgetEntry.placeholder + } + } + entries.append(entry) + let timeline = Timeline(entries: entries, policy: .atEnd) + completion(timeline) } - } - entries.append(entry) - let timeline = Timeline(entries: entries, policy: .atEnd) - completion(timeline) } - } } struct WalletInformationWidgetEntry: TimelineEntry { - let date: Date - let marketData: MarketData - var allWalletsBalance: WalletData = WalletData(balance: 0) + let date: Date + let marketData: MarketData + var allWalletsBalance: WalletData = WalletData(balance: 0) } extension WalletInformationWidgetEntry { - static var placeholder: WalletInformationWidgetEntry { - WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) - } + static var placeholder: WalletInformationWidgetEntry { + WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) + } } -struct WalletInformationWidgetEntryView : View { - let entry: WalletInformationWidgetEntry - - var WalletBalance: some View { - WalletInformationView(allWalletsBalance: entry.allWalletsBalance, marketData: entry.marketData) - } - - var body: some View { - VStack(content: { - WalletBalance - }).padding().background(Color.widgetBackground) - } +struct WalletInformationWidgetEntryView: View { + let entry: WalletInformationWidgetEntry + + var WalletBalance: some View { + WalletInformationView(allWalletsBalance: entry.allWalletsBalance, marketData: entry.marketData) + } + + var body: some View { + VStack(content: { + WalletBalance + }).padding().background(Color.widgetBackground) + } } struct WalletInformationWidget: Widget { - let kind: String = "WalletInformationWidget" - - var body: some WidgetConfiguration { - if #available(iOSApplicationExtension 16.0, *) { - return StaticConfiguration(kind: kind, provider: WalletInformationWidgetProvider()) { entry in - WalletInformationWidgetEntryView(entry: entry) - } - .configurationDisplayName("Balance") - .description("View your accumulated balance.").supportedFamilies([.systemSmall]) - .contentMarginsDisabledIfAvailable() - } else { - return StaticConfiguration(kind: kind, provider: WalletInformationWidgetProvider()) { entry in - WalletInformationWidgetEntryView(entry: entry) - } - .configurationDisplayName("Balance") - .description("View your accumulated balance.").supportedFamilies([.systemSmall]) - .contentMarginsDisabledIfAvailable() + let kind: String = "WalletInformationWidget" + + var body: some WidgetConfiguration { + if #available(iOSApplicationExtension 16.0, *) { + return StaticConfiguration(kind: kind, provider: WalletInformationWidgetProvider()) { entry in + WalletInformationWidgetEntryView(entry: entry) + } + .configurationDisplayName("Balance") + .description("View your accumulated balance.").supportedFamilies([.systemSmall]) + .contentMarginsDisabledIfAvailable() + } else { + return StaticConfiguration(kind: kind, provider: WalletInformationWidgetProvider()) { entry in + WalletInformationWidgetEntryView(entry: entry) + } + .configurationDisplayName("Balance") + .description("View your accumulated balance.").supportedFamilies([.systemSmall]) + .contentMarginsDisabledIfAvailable() + } } - } } struct WalletInformationWidget_Previews: PreviewProvider { - static var previews: some View { - WalletInformationWidgetEntryView(entry: WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: Double(0)), allWalletsBalance: WalletData(balance: 0, latestTransactionTime: LatestTransaction(isUnconfirmed: nil, epochValue: nil)))) - .previewContext(WidgetPreviewContext(family: .systemSmall)) - } + static var previews: some View { + WalletInformationWidgetEntryView(entry: WalletInformationWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: Double(0)), allWalletsBalance: WalletData(balance: 0, latestTransactionTime: LatestTransaction(isUnconfirmed: nil, epochValue: nil)))) + .previewContext(WidgetPreviewContext(family: .systemSmall)) + } } diff --git a/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift b/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift index 967933d5a..a5d2669b8 100644 --- a/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift +++ b/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift @@ -10,124 +10,123 @@ import WidgetKit import SwiftUI struct WalletInformationAndMarketWidgetProvider: TimelineProvider { - typealias Entry = WalletInformationAndMarketWidgetEntry - static var lastSuccessfulEntry: WalletInformationAndMarketWidgetEntry? + typealias Entry = WalletInformationAndMarketWidgetEntry + static var lastSuccessfulEntries: [WalletInformationAndMarketWidgetEntry] = [] - func placeholder(in context: Context) -> WalletInformationAndMarketWidgetEntry { - return WalletInformationAndMarketWidgetEntry.placeholder - } - - func getSnapshot(in context: Context, completion: @escaping (WalletInformationAndMarketWidgetEntry) -> ()) { - let entry: WalletInformationAndMarketWidgetEntry - if (context.isPreview) { - entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) - } else { - entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: emptyMarketData) + func placeholder(in context: Context) -> WalletInformationAndMarketWidgetEntry { + return WalletInformationAndMarketWidgetEntry.placeholder } - completion(entry) - } - - func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { - var entries: [WalletInformationAndMarketWidgetEntry] = [] - if (context.isPreview) { - let entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) - entries.append(entry) - let timeline = Timeline(entries: entries, policy: .atEnd) - completion(timeline) - } else { - let userPreferredCurrency = Currency.getUserPreferredCurrency() - let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime()) - - MarketAPI.fetchMarketData(currency: userPreferredCurrency) { (result, error) in + + func getSnapshot(in context: Context, completion: @escaping (WalletInformationAndMarketWidgetEntry) -> ()) { let entry: WalletInformationAndMarketWidgetEntry - - if let result = result { - entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: result, allWalletsBalance: allwalletsBalance) - WalletInformationAndMarketWidgetProvider.lastSuccessfulEntry = entry + if (context.isPreview) { + entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) } else { - // Use the last successful entry if available - if let lastEntry = WalletInformationAndMarketWidgetProvider.lastSuccessfulEntry { - entry = lastEntry - } else { - // Fallback to a default entry if no successful entry is available - entry = WalletInformationAndMarketWidgetEntry.placeholder - } + entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: emptyMarketData) + } + completion(entry) + } + + func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { + var entries: [WalletInformationAndMarketWidgetEntry] = [] + if (context.isPreview) { + let entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 10000), allWalletsBalance: WalletData(balance: 1000000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) + entries.append(entry) + let timeline = Timeline(entries: entries, policy: .atEnd) + completion(timeline) + } else { + let userPreferredCurrency = Currency.getUserPreferredCurrency() + let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime()) + + MarketAPI.fetchMarketData(currency: userPreferredCurrency) { (result, error) in + let entry: WalletInformationAndMarketWidgetEntry + + if let result = result { + entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: result, allWalletsBalance: allwalletsBalance) + WalletInformationAndMarketWidgetProvider.lastSuccessfulEntries.append(entry) + if WalletInformationAndMarketWidgetProvider.lastSuccessfulEntries.count > 5 { + WalletInformationAndMarketWidgetProvider.lastSuccessfulEntries.removeFirst() + } + } else { + if let lastEntry = WalletInformationAndMarketWidgetProvider.lastSuccessfulEntries.last { + entry = lastEntry + } else { + entry = WalletInformationAndMarketWidgetEntry.placeholder + } + } + entries.append(entry) + let timeline = Timeline(entries: entries, policy: .atEnd) + completion(timeline) + } } - entries.append(entry) - let timeline = Timeline(entries: entries, policy: .atEnd) - completion(timeline) - } } - } } struct WalletInformationAndMarketWidgetEntry: TimelineEntry { - let date: Date - let marketData: MarketData - var allWalletsBalance: WalletData = WalletData(balance: 0) - static var placeholder = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0), allWalletsBalance: WalletData(balance: 0, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) + let date: Date + let marketData: MarketData + var allWalletsBalance: WalletData = WalletData(balance: 0) + static var placeholder = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0), allWalletsBalance: WalletData(balance: 0, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000))) } -struct WalletInformationAndMarketWidgetEntryView : View { - @Environment(\.widgetFamily) var family - let entry: WalletInformationAndMarketWidgetEntry - - - var WalletBalance: some View { - WalletInformationView(allWalletsBalance: entry.allWalletsBalance, marketData: entry.marketData).background(Color.widgetBackground) - } - - var MarketStack: some View { - MarketView(marketData: entry.marketData) - } - - var SendReceiveButtonsView: some View { - SendReceiveButtons().padding(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/, /*@START_MENU_TOKEN@*/10/*@END_MENU_TOKEN@*/) - } - - var body: some View { - if family == .systemLarge { - HStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: /*@START_MENU_TOKEN@*/nil/*@END_MENU_TOKEN@*/, content: { - VStack(alignment: .leading, spacing: nil, content: { - HStack(content: { - WalletBalance.padding() - }).background(Color.widgetBackground) - HStack(content: { - MarketStack }).padding() - SendReceiveButtonsView }).background(Color(.lightGray).opacity(0.77)) - - }) - - } else { - HStack(content: { - WalletBalance.padding() - HStack(content: { - MarketStack.padding() - }).background(Color(.lightGray).opacity(0.77)) - }).background(Color.widgetBackground) - +struct WalletInformationAndMarketWidgetEntryView: View { + @Environment(\.widgetFamily) var family + let entry: WalletInformationAndMarketWidgetEntry + + var WalletBalance: some View { + WalletInformationView(allWalletsBalance: entry.allWalletsBalance, marketData: entry.marketData).background(Color.widgetBackground) + } + + var MarketStack: some View { + MarketView(marketData: entry.marketData) + } + + var SendReceiveButtonsView: some View { + SendReceiveButtons().padding(.all, 10) + } + + var body: some View { + if family == .systemLarge { + HStack(alignment: .center, spacing: nil, content: { + VStack(alignment: .leading, spacing: nil, content: { + HStack(content: { + WalletBalance.padding() + }).background(Color.widgetBackground) + HStack(content: { + MarketStack + }).padding() + SendReceiveButtonsView + }).background(Color(.lightGray).opacity(0.77)) + }) + } else { + HStack(content: { + WalletBalance.padding() + HStack(content: { + MarketStack.padding() + }).background(Color(.lightGray).opacity(0.77)) + }).background(Color.widgetBackground) + } } - } } struct WalletInformationAndMarketWidget: Widget { - let kind: String = "WalletInformationAndMarketWidget" - - var body: some WidgetConfiguration { - StaticConfiguration(kind: kind, provider: WalletInformationAndMarketWidgetProvider()) { entry in - WalletInformationAndMarketWidgetEntryView(entry: entry) + let kind: String = "WalletInformationAndMarketWidget" + + var body: some WidgetConfiguration { + StaticConfiguration(kind: kind, provider: WalletInformationAndMarketWidgetProvider()) { entry in + WalletInformationAndMarketWidgetEntryView(entry: entry) + } + .configurationDisplayName("Wallet and Market") + .description("View your total wallet balance and network prices.").supportedFamilies([.systemMedium, .systemLarge]) + .contentMarginsDisabledIfAvailable() } - .configurationDisplayName("Wallet and Market") - .description("View your total wallet balance and network prices.").supportedFamilies([.systemMedium, .systemLarge]) - .contentMarginsDisabledIfAvailable() - } } struct WalletInformationAndMarketWidget_Previews: PreviewProvider { - static var previews: some View { - WalletInformationAndMarketWidgetEntryView(entry: WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 0), allWalletsBalance: WalletData(balance: 10000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000)))) - .previewContext(WidgetPreviewContext(family: .systemMedium)) - WalletInformationAndMarketWidgetEntryView(entry: WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 0), allWalletsBalance: WalletData(balance: 10000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000)))) - .previewContext(WidgetPreviewContext(family: .systemLarge)) - } + static var previews: some View { + WalletInformationAndMarketWidgetEntryView(entry: WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 0), allWalletsBalance: WalletData(balance: 10000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000)))) + .previewContext(WidgetPreviewContext(family: .systemMedium)) + WalletInformationAndMarketWidgetEntryView(entry: WalletInformationAndMarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10,000", rate: 0), allWalletsBalance: WalletData(balance: 10000, latestTransactionTime: LatestTransaction(isUnconfirmed: false, epochValue: 1568804029000)))) + .previewContext(WidgetPreviewContext(family: .systemLarge)) + } }