Add support for manual price entry

This commit is contained in:
2024-08-29 23:17:40 +03:00
parent 46d2c2c7ef
commit 29650a3ea4
5 changed files with 47 additions and 14 deletions

View File

@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
3A7B2AA32B86407A00ACC4A7 /* FakePriceFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B2AA22B86407A00ACC4A7 /* FakePriceFetcher.swift */; }; 3A7B2AA32B86407A00ACC4A7 /* FakePriceFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B2AA22B86407A00ACC4A7 /* FakePriceFetcher.swift */; };
3A8E5DA72C810C9900E9E6BD /* ManualPriceFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8E5DA62C810C9900E9E6BD /* ManualPriceFetcher.swift */; };
3AE2D39D2B83338D00DE5F31 /* SatsPriceApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE2D39C2B83338D00DE5F31 /* SatsPriceApp.swift */; }; 3AE2D39D2B83338D00DE5F31 /* SatsPriceApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE2D39C2B83338D00DE5F31 /* SatsPriceApp.swift */; };
3AE2D3A22B83338D00DE5F31 /* SatsPrice.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3AE2D3A02B83338D00DE5F31 /* SatsPrice.xcdatamodeld */; }; 3AE2D3A22B83338D00DE5F31 /* SatsPrice.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3AE2D3A02B83338D00DE5F31 /* SatsPrice.xcdatamodeld */; };
3AE2D3A42B83338D00DE5F31 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE2D3A32B83338D00DE5F31 /* ContentView.swift */; }; 3AE2D3A42B83338D00DE5F31 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE2D3A32B83338D00DE5F31 /* ContentView.swift */; };
@@ -45,6 +46,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
3A7B2AA22B86407A00ACC4A7 /* FakePriceFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakePriceFetcher.swift; sourceTree = "<group>"; }; 3A7B2AA22B86407A00ACC4A7 /* FakePriceFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakePriceFetcher.swift; sourceTree = "<group>"; };
3A8E5DA62C810C9900E9E6BD /* ManualPriceFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualPriceFetcher.swift; sourceTree = "<group>"; };
3AE2D3992B83338D00DE5F31 /* SatsPrice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SatsPrice.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3AE2D3992B83338D00DE5F31 /* SatsPrice.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SatsPrice.app; sourceTree = BUILT_PRODUCTS_DIR; };
3AE2D39C2B83338D00DE5F31 /* SatsPriceApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SatsPriceApp.swift; sourceTree = "<group>"; }; 3AE2D39C2B83338D00DE5F31 /* SatsPriceApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SatsPriceApp.swift; sourceTree = "<group>"; };
3AE2D3A12B83338D00DE5F31 /* SatsPrice.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SatsPrice.xcdatamodel; sourceTree = "<group>"; }; 3AE2D3A12B83338D00DE5F31 /* SatsPrice.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = SatsPrice.xcdatamodel; sourceTree = "<group>"; };
@@ -159,6 +161,7 @@
3AE2D3E02B8459D600DE5F31 /* CoinbasePriceFetcher.swift */, 3AE2D3E02B8459D600DE5F31 /* CoinbasePriceFetcher.swift */,
3AE2D3E22B8461FE00DE5F31 /* CoinGeckoPriceFetcher.swift */, 3AE2D3E22B8461FE00DE5F31 /* CoinGeckoPriceFetcher.swift */,
3A7B2AA22B86407A00ACC4A7 /* FakePriceFetcher.swift */, 3A7B2AA22B86407A00ACC4A7 /* FakePriceFetcher.swift */,
3A8E5DA62C810C9900E9E6BD /* ManualPriceFetcher.swift */,
3AE2D3DE2B84597100DE5F31 /* PriceFetcher.swift */, 3AE2D3DE2B84597100DE5F31 /* PriceFetcher.swift */,
3AE2D3E62B85690200DE5F31 /* PriceFetcherDelegator.swift */, 3AE2D3E62B85690200DE5F31 /* PriceFetcherDelegator.swift */,
3AE2D3E42B846A8600DE5F31 /* PriceSource.swift */, 3AE2D3E42B846A8600DE5F31 /* PriceSource.swift */,
@@ -309,6 +312,7 @@
3AE2D39D2B83338D00DE5F31 /* SatsPriceApp.swift in Sources */, 3AE2D39D2B83338D00DE5F31 /* SatsPriceApp.swift in Sources */,
3AE2D3A22B83338D00DE5F31 /* SatsPrice.xcdatamodeld in Sources */, 3AE2D3A22B83338D00DE5F31 /* SatsPrice.xcdatamodeld in Sources */,
3AE2D3A42B83338D00DE5F31 /* ContentView.swift in Sources */, 3AE2D3A42B83338D00DE5F31 /* ContentView.swift in Sources */,
3A8E5DA72C810C9900E9E6BD /* ManualPriceFetcher.swift in Sources */,
3AE2D3D52B83E58500DE5F31 /* SatsViewModel.swift in Sources */, 3AE2D3D52B83E58500DE5F31 /* SatsViewModel.swift in Sources */,
3AE2D3E32B8461FE00DE5F31 /* CoinGeckoPriceFetcher.swift in Sources */, 3AE2D3E32B8461FE00DE5F31 /* CoinGeckoPriceFetcher.swift in Sources */,
3AE2D3DF2B84597100DE5F31 /* PriceFetcher.swift in Sources */, 3AE2D3DF2B84597100DE5F31 /* PriceFetcher.swift in Sources */,

View File

@@ -50,22 +50,21 @@ struct ContentView: View {
Text($0.description) Text($0.description)
} }
} }
.onChange(of: priceSource) { newPriceSource in
priceFetcherDelegator.priceSource = newPriceSource
Task {
await updatePrice()
}
}
HStack { HStack {
TextField("", text: $satsViewModel.btcToUsdString) TextField("", text: $satsViewModel.btcToUsdString)
.disabled(true) .disabled(priceSource != .manual)
Button(action: { #if os(iOS)
Task { .keyboardType(.decimalPad)
await updatePrice() #endif
if priceSource != .manual {
Button(action: {
Task {
await updatePrice()
}
}) {
Image(systemName: "arrow.clockwise")
} }
}) {
Image(systemName: "arrow.clockwise")
} }
} }
} header: { } header: {
@@ -104,6 +103,12 @@ struct ContentView: View {
.task { .task {
await updatePrice() await updatePrice()
} }
.onChange(of: priceSource) { newPriceSource in
priceFetcherDelegator.priceSource = newPriceSource
Task {
await updatePrice()
}
}
#if os(macOS) #if os(macOS)
.formStyle(.grouped) .formStyle(.grouped)
#endif #endif

View File

@@ -0,0 +1,18 @@
//
// ManualPriceFetcher.swift
// SatsPrice
//
// Created by Terry Yiu on 8/29/24.
//
import Foundation
import BigDecimal
/// Fake price fetcher that returns a randomized price. Useful for development testing without requiring a network call.
class ManualPriceFetcher: PriceFetcher {
var price: BigDecimal = 1
func btcToUsd() async throws -> BigDecimal? {
return price
}
}

View File

@@ -11,6 +11,7 @@ import BigDecimal
class PriceFetcherDelegator: PriceFetcher { class PriceFetcherDelegator: PriceFetcher {
private let coinbasePriceFetcher = CoinbasePriceFetcher() private let coinbasePriceFetcher = CoinbasePriceFetcher()
private let coinGeckoPriceFetcher = CoinGeckoPriceFetcher() private let coinGeckoPriceFetcher = CoinGeckoPriceFetcher()
private let manualPriceFetcher = ManualPriceFetcher()
#if DEBUG #if DEBUG
private let fakePriceFetcher = FakePriceFetcher() private let fakePriceFetcher = FakePriceFetcher()
#endif #endif
@@ -27,6 +28,8 @@ class PriceFetcherDelegator: PriceFetcher {
coinbasePriceFetcher coinbasePriceFetcher
case .coingecko: case .coingecko:
coinGeckoPriceFetcher coinGeckoPriceFetcher
case .manual:
manualPriceFetcher
#if DEBUG #if DEBUG
case .fake: case .fake:
fakePriceFetcher fakePriceFetcher

View File

@@ -11,14 +11,15 @@ enum PriceSource: CaseIterable, CustomStringConvertible {
static var allCases: [PriceSource] { static var allCases: [PriceSource] {
#if DEBUG #if DEBUG
[.coinbase, .coingecko, .fake] [.coinbase, .coingecko, .manual, .fake]
#else #else
[.coinbase, .coingecko] [.coinbase, .coingecko, .manual]
#endif #endif
} }
case coinbase case coinbase
case coingecko case coingecko
case manual
#if DEBUG #if DEBUG
case fake case fake
@@ -30,6 +31,8 @@ enum PriceSource: CaseIterable, CustomStringConvertible {
"Coinbase" "Coinbase"
case .coingecko: case .coingecko:
"CoinGecko" "CoinGecko"
case .manual:
"Manual"
#if DEBUG #if DEBUG
case .fake: case .fake:
"Fake" "Fake"