# HG changeset patch # User Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com> # Date 1616168078 -3600 # Node ID 47ad897925b6368db8bdc3bbb87f9ae0f04768b9 # Parent 91a653756a16714ce3886ad718da89f59b45bd54 Minor UI updates ChartViews diff -r 91a653756a16 -r 47ad897925b6 LazyBear/Functions/Haptics.swift --- a/LazyBear/Functions/Haptics.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/Functions/Haptics.swift Fri Mar 19 16:34:38 2021 +0100 @@ -9,6 +9,7 @@ import CoreHaptics class Haptics { + func simpleSuccess() { let generator = UINotificationFeedbackGenerator() generator.notificationOccurred(.success) diff -r 91a653756a16 -r 47ad897925b6 LazyBear/Functions/StringToDate.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Functions/StringToDate.swift Fri Mar 19 16:34:38 2021 +0100 @@ -0,0 +1,21 @@ +// +// DateToString.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 19/3/21. +// + +import SwiftUI + +func convertStringToDate(_ stringDate: String) -> String { + // Convert string to date + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yy-MM-dd" + let date = dateFormatter.date(from: stringDate) + + // Format date to the final format + dateFormatter.dateStyle = .long + let finalDate = dateFormatter.string(from: date!) + + return finalDate +} diff -r 91a653756a16 -r 47ad897925b6 LazyBear/Models/HistoricalPriceModel.swift --- a/LazyBear/Models/HistoricalPriceModel.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/Models/HistoricalPriceModel.swift Fri Mar 19 16:34:38 2021 +0100 @@ -9,10 +9,11 @@ struct HistoricalPriceModel: Codable { var date: String + var minute: String? // Intraday data only var close: Double var volume: Int - var change: Double - var changePercent: Double - var changeOverTime: Double + var change: Double? // Not intraday data only + var changePercent: Double? // Not intraday data only + var changeOverTime: Double? // Not intraday data only } diff -r 91a653756a16 -r 47ad897925b6 LazyBear/UI/ChartView.swift --- a/LazyBear/UI/ChartView.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/UI/ChartView.swift Fri Mar 19 16:34:38 2021 +0100 @@ -17,42 +17,110 @@ @State var selectedPeriod = 2 // Line View + @State private var orientation: UIDeviceOrientation = UIDevice.current.orientation @State var showingChartIndicator = false @State var pointInPath: CGPoint = .zero @State var indexValue = Int() + var body: some View { + let prices = historicalPrices.map { $0.close } + let dates = historicalPrices.map { $0.date } + let minutes = historicalPrices.map {$0.minute } VStack { - let prices = historicalPrices.map { $0.close } - let dates = historicalPrices.map { $0.date } ZStack { if showingChartIndicator { - PriceChartIndicator(prices: prices, dates: dates, indexValue: $indexValue) + PriceChartIndicator(prices: prices, dates: dates, minutes: minutes, indexValue: $indexValue) } else { DateSelection(period: period, selectedperiod: $selectedPeriod) .padding(.horizontal) .onChange(of: selectedPeriod, perform: { (value) in - let url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: period[value]) + let url = rangeEndpointSelector(value) request(url: url, model: [HistoricalPriceModel].self) { self.historicalPrices = $0 } }) } } .frame(height: 40) + let (width, height) = lineViewSize() if !historicalPrices.isEmpty { - LineView(width: deviceSize.width, height: deviceSize.width/3, normalizedData: normalize(prices), showingChartIndicator: $showingChartIndicator, pointInPath: $pointInPath, indexValue: $indexValue) - .frame(width: deviceSize.width, height: deviceSize.width / 3) + LineView(colour: lineViewColour(prices) ,width: width, height: height, normalizedData: normalize(prices), showingChartIndicator: $showingChartIndicator, pointInPath: $pointInPath, indexValue: $indexValue) + .frame(width: width, height: height) .rotationEffect(.degrees(180), anchor: .center) .rotation3DEffect(.degrees(180), axis: (x: 0.0, y: 1.0, z: 0.0)) .padding([.top, .bottom]) + // Detect changes on device orientation and upodate view + .onReceive(NotificationCenter.Publisher(center: .default, name: UIDevice.orientationDidChangeNotification)) { _ in + self.orientation = UIDevice.current.orientation + } } } .onAppear { let url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: "3m") request(url: url, model: [HistoricalPriceModel].self) { self.historicalPrices = $0 } } - + } + + private enum HistoricalInterval { + case oneWeek + case oneMonth + } + + private func selected(interval: HistoricalInterval) -> String { + switch interval { + case .oneWeek: + return "5dm" + case .oneMonth: + return "1mm" + } + } + + private func rangeEndpointSelector(_ value: Int) -> String { + var url = "" + + + if selectedPeriod == 0 { // 1 week + url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: selected(interval: .oneWeek)) + } else if selectedPeriod == 1 { // 1 month + url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: selected(interval: .oneMonth)) + } else { // The rest + url = getUrl(endpoint: .historicalPrices, symbol: symbol, range: period[value]) + } + + return url + } + + private func lineViewColour(_ prices: [Double]) -> Color { + var colour = Color(.systemGreen) + + let firstPrice = prices[0] + let lastPrice = prices.last + + if lastPrice! < firstPrice { + colour = Color(.systemRed) + } + + return colour + } + + private func lineViewSize() -> (CGFloat, CGFloat) { + var divisor: CGFloat = 3 + + // if running on iPad + if UIDevice.current.userInterfaceIdiom == .pad { + divisor = 6 + } + + var width = deviceSize.width + var height = deviceSize.width / divisor + + if orientation.isLandscape { + width = deviceSize.height + height = deviceSize.height / divisor + } + + return (width, height) } } diff -r 91a653756a16 -r 47ad897925b6 LazyBear/UI/CompanyView.swift --- a/LazyBear/UI/CompanyView.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/UI/CompanyView.swift Fri Mar 19 16:34:38 2021 +0100 @@ -37,7 +37,7 @@ .onAppear { companyOption.view = .stock } .toolbar { ToolbarItem(placement: .principal) { - Button(action: { self.hudManager.showAction.toggle() }) { + Button(action: { self.hudManager.showAction.toggle(); haptics.simpleSuccess() }) { HStack { if companyOption.view == .stock { Text("Stock") diff -r 91a653756a16 -r 47ad897925b6 LazyBear/UI/IndicatorPoint.swift --- a/LazyBear/UI/IndicatorPoint.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/UI/IndicatorPoint.swift Fri Mar 19 16:34:38 2021 +0100 @@ -8,10 +8,14 @@ import SwiftUI struct IndicatorPoint: View { + @FetchRequest(entity: UserSettings.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \UserSettings.changedAt, ascending: false)]) + var userSettings: FetchedResults + var body: some View { + let colour = Color("\(userSettings.first?.theme?.lowercased() ?? "default")Accent") Circle() .frame(width: 20, height: 20) - .foregroundColor(.blue) + .foregroundColor(colour) } } diff -r 91a653756a16 -r 47ad897925b6 LazyBear/UI/LineView.swift --- a/LazyBear/UI/LineView.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/UI/LineView.swift Fri Mar 19 16:34:38 2021 +0100 @@ -8,6 +8,7 @@ import SwiftUI struct LineView: View { + var colour: Color var width: CGFloat var height: CGFloat var normalizedData: [Double] @@ -17,8 +18,13 @@ @Binding var showingChartIndicator: Bool @Binding var pointInPath: CGPoint @Binding var indexValue: Int + + @FetchRequest(entity: UserSettings.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \UserSettings.changedAt, ascending: false)]) + var userSettings: FetchedResults var body: some View { + let colour = Color("\(userSettings.first?.theme?.lowercased() ?? "default")Accent") + // Substract 2 to skip the first and the last item let widthBetweenPoints = Double(width) / Double(normalizedData.count - 2) let initialPoint = normalizedData[0] * Double(height) @@ -40,7 +46,7 @@ pathPoints.append(path.currentPoint!) } } - .stroke(self.showingChartIndicator ? Color.blue: Color.green, lineWidth: 2) + .stroke(self.showingChartIndicator ? colour: self.colour, lineWidth: 2) if showingChartIndicator { IndicatorPoint() @@ -99,7 +105,7 @@ GeometryReader { geo in VStack { let normalizedData: [Double] = [0, 0.1, 0.15, 0.2, 0.3, 0.4, 0.35, 0.38, 0.5, 0.55, 0.6, 0.57, 0.8, 1] - LineView(width: geo.size.width, height: geo.size.width / 2, normalizedData: normalizedData, showingChartIndicator: .constant(false), pointInPath: .constant(.zero), indexValue: .constant(0)) + LineView(colour: Color(.systemGreen), width: geo.size.width, height: geo.size.width / 2, normalizedData: normalizedData, showingChartIndicator: .constant(false), pointInPath: .constant(.zero), indexValue: .constant(0)) } } } diff -r 91a653756a16 -r 47ad897925b6 LazyBear/UI/PriceChartIndicator.swift --- a/LazyBear/UI/PriceChartIndicator.swift Thu Mar 18 17:23:37 2021 +0100 +++ b/LazyBear/UI/PriceChartIndicator.swift Fri Mar 19 16:34:38 2021 +0100 @@ -10,14 +10,22 @@ struct PriceChartIndicator: View { var prices: [Double] var dates: [String] + var minutes: [String?] @Binding var indexValue: Int + @FetchRequest(entity: UserSettings.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \UserSettings.changedAt, ascending: false)]) + var userSettings: FetchedResults var body: some View { + let colour = Color("\(userSettings.first?.theme?.lowercased() ?? "default")Accent") HStack { Group { - Text(dates[indexValue]) + let date = convertStringToDate(dates[indexValue]) + Text(date) + if let minute = minutes[indexValue] { + Text(minute) + } Text("\(prices[indexValue], specifier: "%.2f")") - .foregroundColor(.blue) + .foregroundColor(colour) } .font(.subheadline) } @@ -26,6 +34,6 @@ struct PriceChartIndicator_Previews: PreviewProvider { static var previews: some View { - PriceChartIndicator(prices: [100, 50], dates: ["10-10-2020", "11-10-2020"], indexValue: .constant(0)) + PriceChartIndicator(prices: [100, 50], dates: ["10-10-2020", "11-10-2020"], minutes: ["9:02", "9:03"], indexValue: .constant(0)) } }