diff --git a/ios/WalletInformationWidget/WalletInformationWidget.swift b/ios/WalletInformationWidget/WalletInformationWidget.swift index e21078754..399b87329 100644 --- a/ios/WalletInformationWidget/WalletInformationWidget.swift +++ b/ios/WalletInformationWidget/WalletInformationWidget.swift @@ -11,8 +11,10 @@ import SwiftUI struct WalletInformationWidgetProvider: TimelineProvider { typealias Entry = WalletInformationWidgetEntry + static var lastSuccessfulEntry: WalletInformationWidgetEntry? + func placeholder(in context: Context) -> WalletInformationWidgetEntry { - return 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))) + return WalletInformationWidgetEntry.placeholder } func getSnapshot(in context: Context, completion: @escaping (WalletInformationWidgetEntry) -> ()) { @@ -27,22 +29,28 @@ struct WalletInformationWidgetProvider: TimelineProvider { func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { var entries: [WalletInformationWidgetEntry] = [] - let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency(); - - let marketDataEntry = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0) + let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency() let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime()) - WidgetAPI.fetchPrice(currency: userPreferredCurrency, completion: { (result, error) in + + WidgetAPI.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 { - entry = WalletInformationWidgetEntry(date: Date(), marketData: marketDataEntry, allWalletsBalance: allwalletsBalance) + // Use the last successful entry if available + if let lastEntry = WalletInformationWidgetProvider.lastSuccessfulEntry { + entry = lastEntry + } else { + // Fallback to a default entry if no successful entry is available + entry = WalletInformationWidgetEntry.placeholder + } } entries.append(entry) let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) - }) + } } } @@ -52,6 +60,12 @@ struct WalletInformationWidgetEntry: TimelineEntry { 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))) + } +} + struct WalletInformationWidgetEntryView : View { let entry: WalletInformationWidgetEntry diff --git a/ios/Widgets/MarketWidget/MarketWidget.swift b/ios/Widgets/MarketWidget/MarketWidget.swift index 01b2edac0..7b3eff760 100644 --- a/ios/Widgets/MarketWidget/MarketWidget.swift +++ b/ios/Widgets/MarketWidget/MarketWidget.swift @@ -10,6 +10,8 @@ import WidgetKit import SwiftUI struct MarketWidgetProvider: TimelineProvider { + static var lastSuccessfulEntry: MarketWidgetEntry? + func placeholder(in context: Context) -> MarketWidgetEntry { return MarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10 000", rate: 10000)) } @@ -25,28 +27,34 @@ struct MarketWidgetProvider: TimelineProvider { } func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { - var entries: [MarketWidgetEntry] = [] - if context.isPreview { - let entry = MarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10 000", rate: 10000)) - entries.append(entry) - let timeline = Timeline(entries: entries, policy: .atEnd) - completion(timeline) - }else { - let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency(); - let marketDataEntry = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0) - WidgetAPI.fetchMarketData(currency: userPreferredCurrency, completion: { (result, error) in - let entry: MarketWidgetEntry - if let result = result { - entry = MarketWidgetEntry(date: Date(), marketData: result) - - } else { - entry = MarketWidgetEntry(date: Date(), marketData: marketDataEntry) - } + var entries: [MarketWidgetEntry] = [] + if context.isPreview { + let entry = MarketWidgetEntry(date: Date(), marketData: MarketData(nextBlock: "26", sats: "9 134", price: "$10 000", rate: 10000)) entries.append(entry) let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) - }) - } + } else { + let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency() + WidgetAPI.fetchMarketData(currency: userPreferredCurrency) { (result, error) in + let entry: MarketWidgetEntry + + if let result = result { + entry = MarketWidgetEntry(date: Date(), marketData: result) + MarketWidgetProvider.lastSuccessfulEntry = entry + } else { + // Use the last successful entry if available + if let lastEntry = MarketWidgetProvider.lastSuccessfulEntry { + entry = lastEntry + } else { + // Fallback to a default entry if no successful entry is available + entry = MarketWidgetEntry(date: Date(), marketData: emptyMarketData) + } + } + entries.append(entry) + let timeline = Timeline(entries: entries, policy: .atEnd) + completion(timeline) + } + } } } diff --git a/ios/Widgets/PriceWidget/PriceWidget.swift b/ios/Widgets/PriceWidget/PriceWidget.swift index 992cc39b0..e8bf87263 100644 --- a/ios/Widgets/PriceWidget/PriceWidget.swift +++ b/ios/Widgets/PriceWidget/PriceWidget.swift @@ -12,6 +12,7 @@ import SwiftUI var marketData: [MarketDataTimeline: MarketData?] = [ .Current: nil, .Previous: nil] struct PriceWidgetProvider: TimelineProvider { typealias Entry = PriceWidgetEntry + static var lastSuccessfulEntry: PriceWidgetEntry? func placeholder(in context: Context) -> PriceWidgetEntry { return PriceWidgetEntry(date: Date(), currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00")) @@ -35,74 +36,79 @@ struct PriceWidgetProvider: TimelineProvider { let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } else { - if WidgetAPI.getUserPreferredCurrency() != WidgetAPI.getLastSelectedCurrency() { + let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency() + if userPreferredCurrency != WidgetAPI.getLastSelectedCurrency() { marketData[.Current] = nil marketData[.Previous] = nil WidgetAPI.saveNewSelectedCurrency() } - var entryMarketData = marketData[.Current] ?? emptyMarketData - WidgetAPI.fetchPrice(currency: WidgetAPI.getUserPreferredCurrency()) { (data, error) in + WidgetAPI.fetchPrice(currency: userPreferredCurrency) { (data, error) in + let entry: PriceWidgetEntry + if let data = data, let formattedRate = data.formattedRate { let currentMarketData = MarketData(nextBlock: "", sats: "", price: formattedRate, rate: data.rateDouble, dateString: data.lastUpdate) - if let cachedMarketData = marketData[.Current], currentMarketData.dateString != cachedMarketData?.dateString { - marketData[.Previous] = marketData[.Current] - marketData[.Current] = currentMarketData - entryMarketData = currentMarketData - entries.append(PriceWidgetEntry(date:Date(), currentMarketData: entryMarketData)) + marketData[.Previous] = marketData[.Current] + marketData[.Current] = currentMarketData + entry = PriceWidgetEntry(date: Date(), currentMarketData: currentMarketData) + PriceWidgetProvider.lastSuccessfulEntry = entry + } else { + // Use the last successful entry if available + if let lastEntry = PriceWidgetProvider.lastSuccessfulEntry { + entry = lastEntry } else { - entries.append(PriceWidgetEntry(date:Date(), currentMarketData: currentMarketData)) + // Fallback to a default entry if no successful entry is available + entry = PriceWidgetEntry(date: Date(), currentMarketData: emptyMarketData) } } - + entries.append(entry) let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } - } - } -} - -struct PriceWidgetEntry: TimelineEntry { - let date: Date - let currentMarketData: MarketData? - var previousMarketData: MarketData? { - return marketData[.Previous] as? MarketData - } -} - -struct PriceWidgetEntryView : View { - let entry: PriceWidgetEntry - var priceView: some View { - PriceView(currentMarketData: entry.currentMarketData, previousMarketData: marketData[.Previous] ?? emptyMarketData).padding() + }} } - var body: some View { - VStack(content: { - priceView - }).background(Color.widgetBackground) - } -} - -struct PriceWidget: Widget { - let kind: String = "PriceWidget" - - var body: some WidgetConfiguration { - if #available(iOSApplicationExtension 16.0, *) { - return StaticConfiguration(kind: kind, provider: PriceWidgetProvider()) { entry in - PriceWidgetEntryView(entry: entry) - } - .configurationDisplayName("Price") - .description("View the current price of Bitcoin.").supportedFamilies([.systemSmall]) - } else { - return StaticConfiguration(kind: kind, provider: PriceWidgetProvider()) { entry in - PriceWidgetEntryView(entry: entry) - } - .configurationDisplayName("Price") - .description("View the current price of Bitcoin.").supportedFamilies([.systemSmall]) + struct PriceWidgetEntry: TimelineEntry { + let date: Date + let currentMarketData: MarketData? + var previousMarketData: MarketData? { + return marketData[.Previous] as? MarketData } } -} - + + struct PriceWidgetEntryView : View { + let entry: PriceWidgetEntry + var priceView: some View { + PriceView(currentMarketData: entry.currentMarketData, previousMarketData: marketData[.Previous] ?? emptyMarketData).padding() + } + + var body: some View { + VStack(content: { + priceView + }).background(Color.widgetBackground) + } + } + + struct PriceWidget: Widget { + let kind: String = "PriceWidget" + + var body: some WidgetConfiguration { + if #available(iOSApplicationExtension 16.0, *) { + return StaticConfiguration(kind: kind, provider: PriceWidgetProvider()) { entry in + PriceWidgetEntryView(entry: entry) + } + .configurationDisplayName("Price") + .description("View the current price of Bitcoin.").supportedFamilies([.systemSmall]) + } else { + return StaticConfiguration(kind: kind, provider: PriceWidgetProvider()) { entry in + PriceWidgetEntryView(entry: entry) + } + .configurationDisplayName("Price") + .description("View the current price of Bitcoin.").supportedFamilies([.systemSmall]) + } + } + } + struct PriceWidget_Previews: PreviewProvider { static var previews: some View { PriceWidgetEntryView(entry: PriceWidgetEntry(date: Date(), currentMarketData: MarketData(nextBlock: "", sats: "", price: "$10,000", rate: 10000, dateString: "2019-09-18T17:27:00+00:00"))) diff --git a/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift b/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift index 1baf51106..dbfe6ad82 100644 --- a/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift +++ b/ios/Widgets/WalletInformationAndMarketWidget/WalletInformationAndMarketWidget.swift @@ -11,8 +11,10 @@ import SwiftUI struct WalletInformationAndMarketWidgetProvider: TimelineProvider { typealias Entry = WalletInformationAndMarketWidgetEntry + static var lastSuccessfulEntry: WalletInformationAndMarketWidgetEntry? + func placeholder(in context: Context) -> WalletInformationAndMarketWidgetEntry { - return 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))) + return WalletInformationAndMarketWidgetEntry.placeholder } func getSnapshot(in context: Context, completion: @escaping (WalletInformationAndMarketWidgetEntry) -> ()) { @@ -33,21 +35,28 @@ struct WalletInformationAndMarketWidgetProvider: TimelineProvider { let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } else { - let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency(); + let userPreferredCurrency = WidgetAPI.getUserPreferredCurrency() let allwalletsBalance = WalletData(balance: UserDefaultsGroup.getAllWalletsBalance(), latestTransactionTime: UserDefaultsGroup.getAllWalletsLatestTransactionTime()) - let marketDataEntry = MarketData(nextBlock: "...", sats: "...", price: "...", rate: 0) - WidgetAPI.fetchMarketData(currency: userPreferredCurrency, completion: { (result, error) in + + WidgetAPI.fetchMarketData(currency: userPreferredCurrency) { (result, error) in let entry: WalletInformationAndMarketWidgetEntry + if let result = result { entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: result, allWalletsBalance: allwalletsBalance) - + WalletInformationAndMarketWidgetProvider.lastSuccessfulEntry = entry } else { - entry = WalletInformationAndMarketWidgetEntry(date: Date(), marketData: marketDataEntry, allWalletsBalance: allwalletsBalance) + // 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 + } } entries.append(entry) let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) - }) + } } } } @@ -56,6 +65,7 @@ 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))) } struct WalletInformationAndMarketWidgetEntryView : View {