# HG changeset patch # User Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com> # Date 1623606042 -7200 # Node ID 6dd97877f5754ef0fde082fae959509eab1ffced # Parent bdfdf3a1b34e2c3c3608f516b785ae7e4746b826 Improve code, reorganize files diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Company/Chart.swift --- a/LazyBear/Views/Company/Chart.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Company/Chart.swift Sun Jun 13 19:40:42 2021 +0200 @@ -36,19 +36,19 @@ VStack { HStack { if let quote = company.chartData.quote![symbol.uppercased()] { - let latestPrice = quote.latestPrice ?? 0 - let changePercent = quote.changePercent ?? 0 - let priceViewStyle = PriceViewStyle( /// Define PriceView style - horizontalAlignment: .leading, - verticalAlignment: .center, - orientation: .HStack, - priceFont: .title3, - priceFontWeight: .semibold, - percentFont: .body, - percentFontWeight: .semibold, - showBackground: true - ) - PriceView(latestPrice: latestPrice, changePercent: changePercent, style: priceViewStyle) + if let latestPrice = quote.latestPrice, let changePercent = quote.changePercent { + HStack(alignment: .center) { + Text("\(latestPrice, specifier: "%.2f")") + .foregroundColor(changePercent < 0 ? .red: .green) + .fontWeight(.semibold) + + Text("\(changePercent * 100, specifier: "%.2f")%") + .foregroundColor(changePercent < 0 ? .red: .green) + .font(.callout) + .fontWeight(.semibold) + } + .padding(.top) + } } Spacer() diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Company/Helpers/CompanyHeader.swift --- a/LazyBear/Views/Company/Helpers/CompanyHeader.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Company/Helpers/CompanyHeader.swift Sun Jun 13 19:40:42 2021 +0200 @@ -20,7 +20,7 @@ Spacer() Button(action: { showViewSelector = true }) { - Text("Views ") + Text("See more ") Image(systemName: "chevron.down") } } diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Company/Helpers/StatsView.swift --- a/LazyBear/Views/Company/Helpers/StatsView.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Company/Helpers/StatsView.swift Sun Jun 13 19:40:42 2021 +0200 @@ -29,6 +29,7 @@ Spacer() Text(unwrappedValue) .font(.callout) + .lineLimit(1) } } } diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Global Helpers/Extensive List/ExtensiveList.swift --- a/LazyBear/Views/Global Helpers/Extensive List/ExtensiveList.swift Sun Jun 13 19:40:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -// -// ExtensiveList.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 14/4/21. -// - -import SwiftUI - -struct ExtensiveList: View { - var listName: String - var list: [String: QuoteModel]? - var intradayPrices: [String: [Double]]? - var latestCurrencies: [String: CurrencyModel]? - var addOnDelete: Bool - - @Environment(\.presentationMode) private var presentationMode - @Environment(\.managedObjectContext) private var moc - @FetchRequest(entity: WatchlistCompany.entity(), sortDescriptors: []) - var watchlistCompany: FetchedResults - - @State private var isEditMode: EditMode = .inactive - @State private var showRenameListAction = false - @State private var showDeleteListAlert = false - @State private var showSearchView = false - - var body: some View { - NavigationView { - ZStack { - VStack { - if let list = list { - List { - ForEach(Array(list.keys.sorted()), id: \.self) { companySymbol in - StockItem(symbol: companySymbol, - company: list[companySymbol]!, - intradayPrices: intradayPrices?[companySymbol], - orientation: .horizontal, - hidePriceView: self.isEditMode == .active // Hide on EditMode - ) - - } - .onDelete(perform: addOnDelete ? deleteCompany: nil) - } - } - - if let latestCurrencies = latestCurrencies { - List(Array(latestCurrencies.keys.sorted()), id: \.self) { currencySymbol in - CurrencyListItem(currencySymbol: currencySymbol, currency: latestCurrencies[currencySymbol]!) - - } - } - } - - // Blur background - Color(.black) - .edgesIgnoringSafeArea(.all) - .opacity(showRenameListAction ? 0.2: 0) - .animation(.easeInOut) - .onTapGesture { showRenameListAction = false } - - // Show rename Action Sheet - TextfieldAlert(listName: listName, showRenameAction: $showRenameListAction, presentationMode: presentationMode) - .offset(y: showRenameListAction ? 0: 700) - .animation(.easeInOut) - } - // Show delete list alert - .alert(isPresented: $showDeleteListAlert) { - Alert( - title: Text("Are you sure you want to delete this list?"), - message: Text("This action can't be undo"), - primaryButton: .destructive(Text("Delete")) { deleteList() }, - secondaryButton: .cancel() - ) - } - .navigationTitle(listName) - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .cancellationAction) { - if addOnDelete { - EditButton() - } else { - Button(action: { presentationMode.wrappedValue.dismiss() }) { - Image(systemName: "multiply") - .imageScale(.large) - } - } - } - ToolbarItem(placement: .navigationBarTrailing) { - if addOnDelete { - ToolbarMenu(showRenameListAction: $showRenameListAction, showDeleteListAlert: $showDeleteListAlert) - } - } - } - .environment(\.editMode, self.$isEditMode) // Always after Toolbar - } - } - - /* - Delete company from watchlist - */ - private func deleteCompany(at offsets: IndexSet) { - for index in offsets { - let company = watchlistCompany[index] - moc.delete(company) - } - do { - try moc.save() - print("Company deleted") - } catch { - print(error.localizedDescription) - } - } - - /* - Remove entire list if it's not the last one. It can't be zero watchlists - */ - private func deleteList() { - let selectedWatchlist = watchlistCompany.filter({ $0.watchlist == listName }) - for company in selectedWatchlist { - moc.delete(company) - } - do { - try moc.save() - print("List deleted") - presentationMode.wrappedValue.dismiss() // Dismiss view - } catch { - print(error.localizedDescription) - } - } -} - -struct ExtensiveList_Previews: PreviewProvider { - static var previews: some View { - ExtensiveList(listName: "List name", addOnDelete: false) - } -} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Global Helpers/Extensive List/Helpers/ToolbarMenu.swift --- a/LazyBear/Views/Global Helpers/Extensive List/Helpers/ToolbarMenu.swift Sun Jun 13 19:40:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -// -// ToolbarMenu.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 25/4/21. -// - -import SwiftUI - -struct ToolbarMenu: View { - @Binding var showRenameListAction: Bool - @Binding var showDeleteListAlert: Bool - - @FetchRequest(entity: WatchlistCompany.entity(), sortDescriptors: []) - var watchlistCompany: FetchedResults - - var body: some View { - Menu { - Section { - Button(action: { showRenameListAction = true }) { - Label("Rename list", systemImage: "square.and.pencil") - } - } - - if Set(watchlistCompany.map { $0.watchlist }).count > 1 { /// If there are only 1 watchlist -> It cannot be deleted - Section(header: Text("Secondary actions")) { - Button(action: { showDeleteListAlert = true }) { - Label("Delete list", systemImage: "trash") - } - } - } - } - label: { - Label("Options", systemImage: "ellipsis.circle") - .imageScale(.large) - } - } -} - -struct ToolbarMenu_Previews: PreviewProvider { - static var previews: some View { - ToolbarMenu(showRenameListAction: .constant(false), showDeleteListAlert: .constant(false)) - } -} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Global Helpers/PriceView.swift --- a/LazyBear/Views/Global Helpers/PriceView.swift Sun Jun 13 19:40:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -// -// PriceView.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 3/4/21. -// - -import SwiftUI - -struct PriceView: View { - var latestPrice: Double - var changePercent: Double - var style: PriceViewStyle - - var body: some View { - if style.orientation == .VStack { - VStack(alignment: style.horizontalAlignment) { - Price(latestPrice: latestPrice, changePercent: changePercent, style: style) - } - } else { - HStack(alignment: style.verticalAlignment) { - Price(latestPrice: latestPrice, changePercent: changePercent, style: style) - } - .if(style.showBackground) { content in - content - .padding(10) - .background( - RoundedRectangle(cornerRadius: 15) - .foregroundColor(Color(.tertiarySystemBackground)) - ) - } - } - } -} - -/* - Apply modifiers to the passed view on some condition - */ -extension View { - @ViewBuilder - func `if`(_ conditional: Bool, content: (Self) -> Content) -> some View { - if conditional { - content(self) - } else { - self - } - } -} - -struct Price: View { - var latestPrice: Double - var changePercent: Double - var style: PriceViewStyle - - var body: some View { - Text("\(latestPrice, specifier: "%.2f")") - .foregroundColor(changePercent < 0 ? .red: .green) - .font(style.priceFont) - .fontWeight(style.priceFontWeight) - - Text("\(changePercent*100, specifier: "%.2f")%") - .foregroundColor(changePercent < 0 ? .red: .green) - .font(style.percentFont) - .fontWeight(style.percentFontWeight) - } -} - - -struct PriceView_Previews: PreviewProvider { - static var previews: some View { - PriceView( - latestPrice: 120.30, - changePercent: 0.03, - style: PriceViewStyle( - horizontalAlignment: .leading, - verticalAlignment: .center, - orientation: .VStack, - priceFont: .body, - priceFontWeight: .semibold, - percentFont: .callout, - percentFontWeight: .semibold, - showBackground: true - ) - ) - } -} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Global Helpers/RowShape.swift --- a/LazyBear/Views/Global Helpers/RowShape.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Global Helpers/RowShape.swift Sun Jun 13 19:40:42 2021 +0200 @@ -21,6 +21,20 @@ } } +/* + Apply modifiers to the passed view on some condition + */ +extension View { + @ViewBuilder + func `if`(_ conditional: Bool, content: (Self) -> Content) -> some View { + if conditional { + content(self) + } else { + self + } + } +} + struct RowShape_Previews: PreviewProvider { static var previews: some View { RowShape() diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Global Helpers/StockItem.swift --- a/LazyBear/Views/Global Helpers/StockItem.swift Sun Jun 13 19:40:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -// -// StockItem.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 28/3/21. -// - -import SwiftUI -import StockCharts - -enum OrientationView { - case horizontal, vertical -} - -struct StockItem: View { - var symbol: String - var company: QuoteModel - var intradayPrices: [Double]? - var orientation: OrientationView - var hidePriceView: Bool? - - var body: some View { - if orientation == .vertical { - let verticalRow: AnyView = AnyView( - NavigationLink(destination: CompanyView(symbol: symbol)) { - VerticalStockRow(symbol: symbol, company: company, intradayPrices: intradayPrices) - } - .buttonStyle(PlainButtonStyle()) - ) - return verticalRow - } else { - let horizontalRow: AnyView = AnyView( - NavigationLink(destination: CompanyView(symbol: symbol)) { - HorizontalStockRow(symbol: symbol, company: company, intradayPrices: intradayPrices, hidePriceView: hidePriceView ?? false) - } - ) - return horizontalRow - } - } -} - -struct StockItem_Previews: PreviewProvider { - static var previews: some View { - StockItem( - symbol: "AAPL", company: QuoteModel(changePercent: 0.03, companyName: "apple inc", latestPrice: 130.3), - intradayPrices: [130.3, 132.3], orientation: .horizontal - ) - } -} - - -struct VerticalStockRow: View { - var symbol: String - var company: QuoteModel - var intradayPrices: [Double]? - - var body: some View { - RoundedRectangle(cornerRadius: 20) - .foregroundColor(Color(.secondarySystemBackground)) - .aspectRatio(0.8, contentMode: .fit) - .clipShape(RoundedRectangle(cornerRadius: 20)) - .overlay( - VStack(alignment: .leading) { - Group { - Text(symbol.uppercased()) - .fontWeight(.semibold) - .padding(.top) - - Text(company.companyName.capitalized) - .font(.callout) - .fontWeight(.semibold) - .opacity(0.6) - .lineLimit(1) - - let priceViewStyle = PriceViewStyle( - horizontalAlignment: .leading, - verticalAlignment: .center, - orientation: .VStack, - priceFont: .body, - priceFontWeight: .semibold, - percentFont: .callout, - percentFontWeight: .semibold, - showBackground: false - ) - - PriceView(latestPrice: company.latestPrice ?? 0, - changePercent: company.changePercent ?? 0, - style: priceViewStyle) - .padding(.top) - - } - .padding(.horizontal) - - Spacer() - - if let prices = intradayPrices { - LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false) - .padding(.vertical) - .clipShape(RoundedRectangle(cornerRadius: 20)) - } - - } - ,alignment: .leading - ) - } -} - - -struct HorizontalStockRow: View { - var symbol: String - var company: QuoteModel - var intradayPrices: [Double]? - var hidePriceView: Bool - - var body: some View { - HStack { - VStack(alignment: .leading) { - Text(symbol.uppercased()) - .fontWeight(.semibold) - - Text(company.companyName.capitalized) - .font(.callout) - .fontWeight(.semibold) - .opacity(0.6) - .lineLimit(1) - } - - Spacer() - if !hidePriceView { - if let prices = intradayPrices { - LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false) - .frame(width: 80) - .padding(.vertical, 10) - .padding(.leading) - } - - let priceViewStyle = PriceViewStyle( - horizontalAlignment: .leading, - verticalAlignment: .center, - orientation: .VStack, - priceFont: .body, - priceFontWeight: .semibold, - percentFont: .callout, - percentFontWeight: .semibold, - showBackground: false - ) - - PriceView(latestPrice: company.latestPrice ?? 0, - changePercent: company.changePercent ?? 0, - style: priceViewStyle) - // Center PriceView with the other rows - .frame(minWidth: 80, alignment: .trailing) - } - } - .padding(5) - } -} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Global Helpers/StockRow.swift --- a/LazyBear/Views/Global Helpers/StockRow.swift Sun Jun 13 19:40:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -// -// StockRow.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 28/3/21. -// - -import SwiftUI - - -struct StockRow: View { - var listName: String - var list: [String: QuoteModel] - var intradayPrices: [String: [Double]]? - var addOnDelete: Bool - - @State private var showExtensiveList = false - - @Environment(\.managedObjectContext) private var moc - - var body: some View { - VStack(alignment: .leading) { - HStack(alignment: .bottom) { - VStack(alignment: .leading) { - Text(listName) - .font(.title3) - .fontWeight(.semibold) - .padding([.top, .horizontal]) - - Text("Real-time quotes") - .font(.caption) - .opacity(0.5) - .padding(.horizontal) - } - - Spacer() - Button("See all", action: { self.showExtensiveList = true }) - .buttonStyle(BorderlessButtonStyle()) - .padding(.horizontal) - } - - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 20) { - ForEach(Array(list.keys.sorted()), id: \.self) { companySymbol in - StockItem(symbol: companySymbol, company: list[companySymbol]!, intradayPrices: intradayPrices?[companySymbol], orientation: .vertical) - } - } - .padding() - } - .frame(height: 250) - } - .padding(.bottom) - .sheet(isPresented: $showExtensiveList) { - ExtensiveList(listName: listName, list: list, intradayPrices: intradayPrices, latestCurrencies: nil, addOnDelete: addOnDelete) - .environment(\.managedObjectContext, self.moc) - - } - } -} - - -struct StockRectangleRow_Previews: PreviewProvider { - static var previews: some View { - StockRow( - listName: "Gainers", - list: ["AAPL": QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 130.3)], - intradayPrices: ["AAPL": [130.2]], addOnDelete: false - ) - } -} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/CurrencyItem.swift --- a/LazyBear/Views/Home/Helpers/CurrencyItem.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Home/Helpers/CurrencyItem.swift Sun Jun 13 19:40:42 2021 +0200 @@ -10,6 +10,7 @@ struct CurrencyItem: View { var currencySymbol: String var currency: CurrencyModel + var rectangleWidth: CGFloat? var body: some View { RoundedRectangle(cornerRadius: 8) diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/CurrencyListItem.swift --- a/LazyBear/Views/Home/Helpers/CurrencyListItem.swift Sun Jun 13 19:40:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -// -// CurrencyListItem.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 14/4/21. -// - -import SwiftUI - -struct CurrencyListItem: View { - var currencySymbol: String - var currency: CurrencyModel - - var body: some View { - HStack { - Text(currency.flag) - .padding(.trailing) - - VStack(alignment: .leading) { - Text("USD/\(currencySymbol)") - .font(.headline) - - Text(currency.name) - .font(.callout) - } - - Spacer() - Text("\(currency.rate, specifier: "%.2f")") - .padding(.horizontal) - } - } -} - -struct CurrencyRowItem_Previews: PreviewProvider { - static var previews: some View { - CurrencyListItem(currencySymbol: "AUD", currency: CurrencyModel(flag: "🇺🇸", name: "Australian dollar", rate: 1.3116)) - } -} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/CurrencyRow.swift --- a/LazyBear/Views/Home/Helpers/CurrencyRow.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Home/Helpers/CurrencyRow.swift Sun Jun 13 19:40:42 2021 +0200 @@ -9,8 +9,7 @@ struct CurrencyRow: View { var latestCurrencies: [String: CurrencyModel] - - @Environment(\.managedObjectContext) private var moc + @State private var showExtensiveList = false var body: some View { @@ -44,8 +43,7 @@ } } .sheet(isPresented: $showExtensiveList) { - ExtensiveList(listName: "Currencies", latestCurrencies: latestCurrencies, addOnDelete: false) - .environment(\.managedObjectContext, self.moc) + CurrencySheet(latestCurrencies: latestCurrencies) } } } diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/CurrencySheet.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Views/Home/Helpers/CurrencySheet.swift Sun Jun 13 19:40:42 2021 +0200 @@ -0,0 +1,38 @@ +// +// CurrencySheet.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/6/21. +// + +import SwiftUI + +struct CurrencySheet: View { + @Environment(\.presentationMode) private var currencySheetPresentation + + var latestCurrencies: [String: CurrencyModel] + var body: some View { + NavigationView { + VStack { + List(Array(latestCurrencies.keys.sorted()), id: \.self) { currencySymbol in + CurrencySheetRow(currencySymbol: currencySymbol, currency: latestCurrencies[currencySymbol]!) + } + } + .navigationTitle("Currencies") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: {currencySheetPresentation.wrappedValue.dismiss()}) { + Image(systemName: "multiply") + } + } + } + } + } +} + +struct CurrencySheet_Previews: PreviewProvider { + static var previews: some View { + CurrencySheet(latestCurrencies: ["AUD": CurrencyModel(flag: "🇦🇺", name: "Australian dollar", rate: 1.2938)]) + } +} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/CurrencySheetRow.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Views/Home/Helpers/CurrencySheetRow.swift Sun Jun 13 19:40:42 2021 +0200 @@ -0,0 +1,39 @@ +// +// CurrencySheetRow.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/6/21. +// + +import SwiftUI + +struct CurrencySheetRow: View { + var currencySymbol: String + var currency: CurrencyModel + + var body: some View { + HStack { + Text(currency.flag) + .padding(.trailing) + + VStack(alignment: .leading) { + Text("USD/\(currencySymbol)") + .font(.headline) + + Text(currency.name) + .font(.callout) + } + + Spacer() + Text("\(currency.rate, specifier: "%.2f")") + .fontWeight(.semibold) + .padding(.horizontal) + } + } +} + +struct CurrencySheetRow_Previews: PreviewProvider { + static var previews: some View { + CurrencySheetRow(currencySymbol: "AUD", currency: CurrencyModel(flag: "🇦🇺", name: "Australian dollar", rate: 1.2938)) + } +} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/StockItem.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Views/Home/Helpers/StockItem.swift Sun Jun 13 19:40:42 2021 +0200 @@ -0,0 +1,71 @@ +// +// StockItem.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/6/21. +// + +import SwiftUI +import StockCharts + +struct StockItem: View { + var symbol: String + var company: QuoteModel + var intradayPrices: [Double]? + + var body: some View { + RoundedRectangle(cornerRadius: 20) + .foregroundColor(Color(.secondarySystemBackground)) + .aspectRatio(0.8, contentMode: .fit) + .clipShape(RoundedRectangle(cornerRadius: 20)) + .overlay( + VStack(alignment: .leading) { + Group { + Text(symbol.uppercased()) + .fontWeight(.semibold) + .padding(.top) + + Text(company.companyName.capitalized) + .font(.callout) + .fontWeight(.semibold) + .opacity(0.6) + .lineLimit(1) + + if let latestPrice = company.latestPrice, let changePercent = company.changePercent { + VStack(alignment: .leading) { + Text("\(latestPrice, specifier: "%.2f")") + .foregroundColor(changePercent < 0 ? .red: .green) + .fontWeight(.semibold) + + Text("\(changePercent * 100, specifier: "%.2f")%") + .foregroundColor(changePercent < 0 ? .red: .green) + .font(.callout) + .fontWeight(.semibold) + } + .padding(.top) + } + } + .padding(.horizontal) + + Spacer() + + if let prices = intradayPrices { + LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false) + .padding(.vertical) + .clipShape(RoundedRectangle(cornerRadius: 20)) + } + + } + ,alignment: .leading + ) + } +} + +struct StockItem_Previews: PreviewProvider { + static var previews: some View { + StockItem( + symbol: "aapl", + company: QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 120.3) + ) + } +} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/StockRow.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Views/Home/Helpers/StockRow.swift Sun Jun 13 19:40:42 2021 +0200 @@ -0,0 +1,76 @@ +// +// StockRow.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 28/3/21. +// + +import SwiftUI + + +struct StockRow: View { + var list: [String: [String: QuoteModel]] + var intradayPrices: [String: [Double]]? + + @State private var showList = false + + var body: some View { + let listName = list.first!.key + VStack(alignment: .leading) { + HStack(alignment: .bottom) { + VStack(alignment: .leading) { + Text(adaptListTitle(listName)) + .font(.title3) + .fontWeight(.semibold) + .padding([.top, .horizontal]) + + Text("Real-time quotes") + .font(.caption) + .opacity(0.5) + .padding(.horizontal) + } + + Spacer() + Button("See all", action: { showList = true }) + .buttonStyle(BorderlessButtonStyle()) + .padding(.horizontal) + } + + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 20) { + let companies = list[listName] + ForEach(Array(companies!.keys), id: \.self) { symbol in + StockItem(symbol: symbol, company: companies![symbol]!, intradayPrices: intradayPrices![symbol]) + } + } + .padding() + } + .frame(height: 250) + } + .padding(.bottom) + .sheet(isPresented: $showList) { + StockSheet(listName: adaptListTitle(listName), companies: list[list.first!.key]!, intradayPrices: intradayPrices) + } + } + + /* + Get list keys (mostactive, losers, active) and adapt them to diplay + */ + private func adaptListTitle(_ title: String) -> String { + if title == "mostactive" { + return "Most active" + } else { + return title.capitalized + } + } +} + + +struct StockRectangleRow_Previews: PreviewProvider { + static var previews: some View { + StockRow( + list: ["mostactive": ["AAPL": QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 130.3)]], + intradayPrices: ["AAPL": [130.2]] + ) + } +} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/StockSheet.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Views/Home/Helpers/StockSheet.swift Sun Jun 13 19:40:42 2021 +0200 @@ -0,0 +1,43 @@ +// +// StockSheet.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/6/21. +// + +import SwiftUI + +struct StockSheet: View { + var listName: String + var companies: [String: QuoteModel] + var intradayPrices: [String: [Double]]? + + @Environment(\.presentationMode) private var stockSheetPresentation + + var body: some View { + NavigationView { + VStack { + List(Array(companies.keys.sorted()), id: \.self) { symbol in + NavigationLink(destination: CompanyView(symbol: symbol)) { + StockSheetRow(symbol: symbol, company: companies[symbol]!, intradayPrices: intradayPrices![symbol]!) + } + } + } + .navigationTitle(listName) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: {stockSheetPresentation.wrappedValue.dismiss()}) { + Image(systemName: "multiply") + } + } + } + } + } +} + +struct StockSheet_Previews: PreviewProvider { + static var previews: some View { + StockSheet(listName: "Most active", companies: ["aapl": QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 120.3)]) + } +} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/Helpers/StockSheetRow.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LazyBear/Views/Home/Helpers/StockSheetRow.swift Sun Jun 13 19:40:42 2021 +0200 @@ -0,0 +1,60 @@ +// +// StockSheetRow.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/6/21. +// + +import SwiftUI +import StockCharts + +struct StockSheetRow: View { + var symbol: String + var company: QuoteModel + var intradayPrices: [Double]? + + var body: some View { + HStack { + VStack(alignment: .leading) { + Text(symbol.capitalized.capitalized) + .fontWeight(.semibold) + + Text(company.companyName.capitalized) + .font(.callout) + .fontWeight(.semibold) + .opacity(0.6) + .lineLimit(1) + } + + Spacer() + if let prices = intradayPrices { + LineChartView(data: prices, dates: nil, hours: nil, dragGesture: false) + .frame(width: 80) + .padding(.vertical, 10) + .padding(.leading) + } + + if let latestPrice = company.latestPrice, let changePercent = company.changePercent { + VStack(alignment: .trailing) { + Text("\(latestPrice, specifier: "%.2f")") + .foregroundColor(changePercent < 0 ? .red: .green) + .fontWeight(.semibold) + + Text("\(changePercent * 100, specifier: "%.2f")%") + .foregroundColor(changePercent < 0 ? .red: .green) + .font(.callout) + .fontWeight(.semibold) + } + } + } + } +} + +struct StockSheetRow_Previews: PreviewProvider { + static var previews: some View { + StockSheetRow( + symbol: "aapl", + company: QuoteModel(changePercent: 0.03, companyName: "Apple Inc", latestPrice: 120.3) + ) + } +} diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Home/HomeView.swift --- a/LazyBear/Views/Home/HomeView.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Home/HomeView.swift Sun Jun 13 19:40:42 2021 +0200 @@ -34,7 +34,7 @@ let mirror = Mirror(reflecting: lists) ForEach(Array(mirror.children), id: \.label) { child in if let list = child.value as? [String : QuoteModel] { - StockRow(listName: "\(adaptListTitle(child.label!))", list: list, intradayPrices: home.data.intradayPrices, addOnDelete: false) + StockRow(list: [child.label!: list], intradayPrices: home.data.intradayPrices) .listRowInsets(EdgeInsets()) } } @@ -71,17 +71,6 @@ } } - - /* - Get list keys (mostactive, losers, active) and adapt them to diplay - */ - private func adaptListTitle(_ title: String) -> String { - if title == "mostactive" { - return "Most active" - } else { - return title.capitalized - } - } } struct HomeView_Previews: PreviewProvider { diff -r bdfdf3a1b34e -r 6dd97877f575 LazyBear/Views/Profile/ProfileView.swift --- a/LazyBear/Views/Profile/ProfileView.swift Sun Jun 13 19:40:18 2021 +0200 +++ b/LazyBear/Views/Profile/ProfileView.swift Sun Jun 13 19:40:42 2021 +0200 @@ -25,11 +25,13 @@ Get Watchlist names -> Create rows for each watchlist -> in each row, show companies */ let watchlists = Set(watchlistCompanies.map { $0.watchlist }) /// Set -> avoid duplicates names + ForEach(Array(watchlists).sorted(), id: \.self) { listName in - let symbols = watchlistCompanies.filter({ $0.watchlist == listName }).map { $0.symbol } + let symbols = watchlistCompanies.filter({ $0.watchlist == listName }).map { $0.symbol } /// Get symbols contained in specified watchlist (Core Data) + if let companies = profile.data.quotes { let list = companies.filter({ symbols.contains($0.key) }) /// From API response select the companies within the specified watchlist - StockRow(listName: listName, list: list, intradayPrices: profile.data.intradayPrices, addOnDelete: true) + StockRow(list: [listName: list], intradayPrices: profile.data.intradayPrices) } } .listRowInsets(EdgeInsets()) @@ -37,8 +39,8 @@ refreshList() } } - .onAppear { self.timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect() } // Start timer - .onDisappear { self.timer.upstream.connect().cancel() } // Stop timer + .onAppear { self.timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect() } /// Start timer + .onDisappear { self.timer.upstream.connect().cancel() } /// Stop timer .onReceive(timer) { _ in if !showCreateNewWatchlist { prepareUrl(.streaming)