# HG changeset patch # User Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com> # Date 1610554801 0 # Node ID 8023d420f4372a2d0a25b5e9cfe416fd4ab5378e # Parent cf0168a29e4d99ab2afe723ca9056d5c8cb0b7d3 implement core data diff -r cf0168a29e4d -r 8023d420f437 FavCompany+CoreDataClass.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FavCompany+CoreDataClass.swift Wed Jan 13 16:20:01 2021 +0000 @@ -0,0 +1,15 @@ +// +// FavCompany+CoreDataClass.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/1/21. +// +// + +import Foundation +import CoreData + +@objc(FavCompany) +public class FavCompany: NSManagedObject { + +} diff -r cf0168a29e4d -r 8023d420f437 FavCompany+CoreDataProperties.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FavCompany+CoreDataProperties.swift Wed Jan 13 16:20:01 2021 +0000 @@ -0,0 +1,27 @@ +// +// FavCompany+CoreDataProperties.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/1/21. +// +// + +import Foundation +import CoreData + + +extension FavCompany { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "FavCompany") + } + + @NSManaged public var cik: Int16 + @NSManaged public var symbol: String + @NSManaged public var name: String + +} + +extension FavCompany : Identifiable { + +} diff -r cf0168a29e4d -r 8023d420f437 Favourite+CoreDataClass.swift --- a/Favourite+CoreDataClass.swift Tue Jan 12 21:35:37 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -// -// Favourite+CoreDataClass.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 12/1/21. -// -// - -import Foundation -import CoreData - -@objc(Favourite) -public class Favourite: NSManagedObject { - -} diff -r cf0168a29e4d -r 8023d420f437 Favourite+CoreDataProperties.swift --- a/Favourite+CoreDataProperties.swift Tue Jan 12 21:35:37 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -// -// Favourite+CoreDataProperties.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 12/1/21. -// -// - -import Foundation -import CoreData - - -extension Favourite { - - @nonobjc public class func fetchRequest() -> NSFetchRequest { - return NSFetchRequest(entityName: "Favourite") - } - - @NSManaged public var cik: Int16 - @NSManaged public var isFavourite: Bool - -} - -extension Favourite : Identifiable { - -} diff -r cf0168a29e4d -r 8023d420f437 LazyBear.xcodeproj/project.pbxproj --- a/LazyBear.xcodeproj/project.pbxproj Tue Jan 12 21:35:37 2021 +0000 +++ b/LazyBear.xcodeproj/project.pbxproj Wed Jan 13 16:20:01 2021 +0000 @@ -20,13 +20,14 @@ 95612C502598D48200F7698F /* Companies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95612C4E2598D48200F7698F /* Companies.swift */; }; 95612C512598D48200F7698F /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95612C4F2598D48200F7698F /* SearchBar.swift */; }; 956AACC7259CA8EF00CB9F16 /* Selection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956AACC6259CA8EF00CB9F16 /* Selection.swift */; }; - 957954F125AE208F001FB4EC /* Favourite+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957954EF25AE208F001FB4EC /* Favourite+CoreDataClass.swift */; }; - 957954F225AE208F001FB4EC /* Favourite+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957954F025AE208F001FB4EC /* Favourite+CoreDataProperties.swift */; }; + 956FAF7B25AF421E0002B2C1 /* FavCompany+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956FAF7925AF421E0002B2C1 /* FavCompany+CoreDataClass.swift */; }; + 956FAF7C25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956FAF7A25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift */; }; 958DF3D825A08F4E00D10D22 /* Stock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958DF3D725A08F4E00D10D22 /* Stock.swift */; }; 958DF3DB25A08F8600D10D22 /* Insiders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958DF3DA25A08F8600D10D22 /* Insiders.swift */; }; 95A1ECAF25A36127001D4A21 /* Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A1ECAE25A36127001D4A21 /* Transaction.swift */; }; 95A1ECB225A36230001D4A21 /* TransactionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A1ECB125A36230001D4A21 /* TransactionModel.swift */; }; 95A1ECC525A37541001D4A21 /* TransactionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A1ECC425A37541001D4A21 /* TransactionRow.swift */; }; + 95A8103825AF476F000FD1D6 /* FavCompanyRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A8103725AF476F000FD1D6 /* FavCompanyRow.swift */; }; 95AB4A7A259DCBAE0064C9C1 /* ReadJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */; }; 95AB4A7D259DCC0C0064C9C1 /* CompanyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A7C259DCC0C0064C9C1 /* CompanyData.swift */; }; 95AB4A90259DD66D0064C9C1 /* CompanyRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */; }; @@ -56,13 +57,14 @@ 95612C4E2598D48200F7698F /* Companies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Companies.swift; sourceTree = ""; }; 95612C4F2598D48200F7698F /* SearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = ""; }; 956AACC6259CA8EF00CB9F16 /* Selection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Selection.swift; sourceTree = ""; }; - 957954EF25AE208F001FB4EC /* Favourite+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Favourite+CoreDataClass.swift"; sourceTree = ""; }; - 957954F025AE208F001FB4EC /* Favourite+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Favourite+CoreDataProperties.swift"; sourceTree = ""; }; + 956FAF7925AF421E0002B2C1 /* FavCompany+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavCompany+CoreDataClass.swift"; sourceTree = ""; }; + 956FAF7A25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavCompany+CoreDataProperties.swift"; sourceTree = ""; }; 958DF3D725A08F4E00D10D22 /* Stock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Stock.swift; path = lazybear/Stock.swift; sourceTree = SOURCE_ROOT; }; 958DF3DA25A08F8600D10D22 /* Insiders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Insiders.swift; path = lazybear/Insiders.swift; sourceTree = SOURCE_ROOT; }; 95A1ECAE25A36127001D4A21 /* Transaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Transaction.swift; path = lazybear/Functions/Transaction.swift; sourceTree = SOURCE_ROOT; }; 95A1ECB125A36230001D4A21 /* TransactionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TransactionModel.swift; path = lazybear/Models/TransactionModel.swift; sourceTree = SOURCE_ROOT; }; 95A1ECC425A37541001D4A21 /* TransactionRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionRow.swift; sourceTree = ""; }; + 95A8103725AF476F000FD1D6 /* FavCompanyRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavCompanyRow.swift; sourceTree = ""; }; 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReadJson.swift; path = lazybear/Functions/ReadJson.swift; sourceTree = SOURCE_ROOT; }; 95AB4A7C259DCC0C0064C9C1 /* CompanyData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompanyData.swift; path = lazybear/Models/CompanyData.swift; sourceTree = SOURCE_ROOT; }; 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyRow.swift; sourceTree = ""; }; @@ -121,6 +123,7 @@ 95DF5199259DE0E2003790B2 /* WhatsNew.swift */, 95DF519C259DE118003790B2 /* TipJar.swift */, 95A1ECC425A37541001D4A21 /* TransactionRow.swift */, + 95A8103725AF476F000FD1D6 /* FavCompanyRow.swift */, ); name = Supply; path = lazybear/Supply; @@ -157,8 +160,8 @@ 95B04EA625212369000AD27F = { isa = PBXGroup; children = ( - 957954EF25AE208F001FB4EC /* Favourite+CoreDataClass.swift */, - 957954F025AE208F001FB4EC /* Favourite+CoreDataProperties.swift */, + 956FAF7925AF421E0002B2C1 /* FavCompany+CoreDataClass.swift */, + 956FAF7A25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift */, 95B04EB125212369000AD27F /* LazyBear */, 95B04EB025212369000AD27F /* Products */, 9500257E256D17D9008FFD28 /* Frameworks */, @@ -287,13 +290,16 @@ 95612C512598D48200F7698F /* SearchBar.swift in Sources */, 955AD1F425AE2BDC00965D42 /* TestFavourites.swift in Sources */, 95A1ECC525A37541001D4A21 /* TransactionRow.swift in Sources */, + 956FAF7C25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift in Sources */, 95B04EB525212369000AD27F /* ContentView.swift in Sources */, 95AB4A90259DD66D0064C9C1 /* CompanyRow.swift in Sources */, 95D1BF4925ADCF7700E5D063 /* Persistence.swift in Sources */, 95612C472598D17F00F7698F /* User.swift in Sources */, + 956FAF7B25AF421E0002B2C1 /* FavCompany+CoreDataClass.swift in Sources */, 95D1BF4C25ADD08500E5D063 /* Main.swift in Sources */, 95612C4A2598D1F800F7698F /* About.swift in Sources */, 95B04EB325212369000AD27F /* LazyBearApp.swift in Sources */, + 95A8103825AF476F000FD1D6 /* FavCompanyRow.swift in Sources */, 958DF3D825A08F4E00D10D22 /* Stock.swift in Sources */, 956AACC7259CA8EF00CB9F16 /* Selection.swift in Sources */, 954D998325A27571001F7F60 /* Price.swift in Sources */, @@ -304,13 +310,11 @@ 95612C502598D48200F7698F /* Companies.swift in Sources */, 95DF5197259DDD68003790B2 /* AppInfo.swift in Sources */, 954D997125A253A9001F7F60 /* Config.swift in Sources */, - 957954F225AE208F001FB4EC /* Favourite+CoreDataProperties.swift in Sources */, 95A1ECAF25A36127001D4A21 /* Transaction.swift in Sources */, 9521A8BD259B93200000D417 /* Company.swift in Sources */, 954D992525A2123B001F7F60 /* PriceModel.swift in Sources */, 95F7CAF625ADC7B7009E0E7C /* LazyBear.xcdatamodeld in Sources */, 95DF519D259DE118003790B2 /* TipJar.swift in Sources */, - 957954F125AE208F001FB4EC /* Favourite+CoreDataClass.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff -r cf0168a29e4d -r 8023d420f437 LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed diff -r cf0168a29e4d -r 8023d420f437 lazybear/ContentView.swift --- a/lazybear/ContentView.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/ContentView.swift Wed Jan 13 16:20:01 2021 +0000 @@ -10,8 +10,8 @@ struct ContentView: View { @Environment(\.managedObjectContext) private var viewContext - @FetchRequest(entity: Favourite.entity(), sortDescriptors: []) - var favourites: FetchedResults + @FetchRequest(entity: FavCompany.entity(), sortDescriptors: []) + var favourites: FetchedResults var body: some View { Main() diff -r cf0168a29e4d -r 8023d420f437 lazybear/Core Data/Persistence.swift --- a/lazybear/Core Data/Persistence.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/Core Data/Persistence.swift Wed Jan 13 16:20:01 2021 +0000 @@ -14,9 +14,10 @@ let result = PersistenceController(inMemory: true) let viewContext = result.container.viewContext for _ in 0..<10 { - let newItem = Favourite(context: viewContext) + let newItem = FavCompany(context: viewContext) newItem.cik = 123 - newItem.isFavourite = true + newItem.symbol = "Symbol" + newItem.name = "Name" } do { diff -r cf0168a29e4d -r 8023d420f437 lazybear/LazyBear.xcdatamodeld/LazyBear.xcdatamodel/contents --- a/lazybear/LazyBear.xcdatamodeld/LazyBear.xcdatamodel/contents Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/LazyBear.xcdatamodeld/LazyBear.xcdatamodel/contents Wed Jan 13 16:20:01 2021 +0000 @@ -1,10 +1,11 @@ - + - + + - + \ No newline at end of file diff -r cf0168a29e4d -r 8023d420f437 lazybear/LazyBearApp.swift --- a/lazybear/LazyBearApp.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/LazyBearApp.swift Wed Jan 13 16:20:01 2021 +0000 @@ -14,7 +14,7 @@ var body: some Scene { WindowGroup { NavigationView { - TestFavourites() + ContentView() .environment(\.managedObjectContext, persistenceController.container.viewContext) } .navigationViewStyle(StackNavigationViewStyle()) diff -r cf0168a29e4d -r 8023d420f437 lazybear/Main.swift --- a/lazybear/Main.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/Main.swift Wed Jan 13 16:20:01 2021 +0000 @@ -27,7 +27,6 @@ } Spacer() - /* Button(action: {self.showingUser.toggle() }) { Image(systemName: "person") @@ -35,14 +34,13 @@ }.sheet(isPresented: $showingUser) { User() } - */ } .transition(.move(edge: .top)) .animation(.default) .padding() } - SearchBar(searchedText: $searchedCompany, placeholder: "Search ...", showingSearch: $showingSearch) + SearchBar(searchedText: $searchedCompany, placeholder: "Search ...", showingSearch: $showingSearch, exitButton: "Cancel") if showingSearch == false { Companies() diff -r cf0168a29e4d -r 8023d420f437 lazybear/Supply/FavCompanyRow.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Supply/FavCompanyRow.swift Wed Jan 13 16:20:01 2021 +0000 @@ -0,0 +1,64 @@ +// +// FavCompanyRow.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 13/1/21. +// + +import SwiftUI + +struct FavCompanyRow: View { + var company: CompanyData + @Environment(\.managedObjectContext) private var viewContext + @FetchRequest(entity: FavCompany.entity(), sortDescriptors: []) + var favCompanies: FetchedResults + + var body: some View { + let names = favCompanies.map { $0.name } + HStack { + if names.contains(company.name) { + Button(action: { deleteFavourite(symbol: company.symbol, name: company.name) }) { + Image(systemName: "minus.circle.fill") + .iconModifier() + } + } + else { + Button(action: { addFavourite(symbol: company.symbol, name: company.name) }) { + Image(systemName: "plus.circle.fill") + .iconModifier() + } + } + Text(company.name.capitalized) + } + } + + func addFavourite(symbol: String, name: String) { + let favCompany = FavCompany(context: viewContext) + favCompany.symbol = symbol + favCompany.name = name + do { + try viewContext.save() + print("Company saved.") + } catch { + print(error.localizedDescription) + } + } + + func deleteFavourite(symbol: String, name: String) { + + } +} +extension Image { + func iconModifier() -> some View { + self + .renderingMode(.original) + .resizable() + .frame(width: 25, height: 25) + } +} + +struct FavCompanyRow_Previews: PreviewProvider { + static var previews: some View { + FavCompanyRow(company: companiesData[0]) + } +} diff -r cf0168a29e4d -r 8023d420f437 lazybear/Supply/SearchBar.swift --- a/lazybear/Supply/SearchBar.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/Supply/SearchBar.swift Wed Jan 13 16:20:01 2021 +0000 @@ -14,6 +14,7 @@ @State var searchBarIsEditing = false @State var placeholder: String @Binding var showingSearch: Bool // Content View + @State var exitButton: String var body: some View { HStack { @@ -59,7 +60,7 @@ UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) }) { - Text("Cancel") + Text(exitButton) } } } @@ -69,6 +70,6 @@ struct SearchBar_Previews: PreviewProvider { static var previews: some View { - SearchBar(searchedText: .constant(""), placeholder: "Placeholder", showingSearch: .constant(true)) + SearchBar(searchedText: .constant(""), placeholder: "Placeholder", showingSearch: .constant(true), exitButton: "Cancel") } } diff -r cf0168a29e4d -r 8023d420f437 lazybear/Tests/TestFavourites.swift --- a/lazybear/Tests/TestFavourites.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/Tests/TestFavourites.swift Wed Jan 13 16:20:01 2021 +0000 @@ -4,13 +4,13 @@ // // Created by Dennis Concepción Martín on 12/1/21. // - +/* import SwiftUI struct TestFavourites: View { @Environment(\.managedObjectContext) private var viewContext - @FetchRequest(entity: Favourite.entity(), sortDescriptors: []) - var favourites: FetchedResults + @FetchRequest(entity: FavCompany.entity(), sortDescriptors: []) + var favCompanies: FetchedResults var body: some View { VStack { @@ -21,23 +21,18 @@ // Display favourites List { - ForEach(favourites) { favourite in + ForEach(favCompanies) { favCompany in HStack { - Text(String(favourite.cik)) - Spacer() - Text(String(favourite.isFavourite)) - // Update cik -> I could use that to update bool - Spacer() - Button(action: { updateFavourite(favourite: favourite) }) { - Text("Update bool") - .foregroundColor(.blue) - } + Text(String(favCompany.cik)) + Text(favCompany.symbol) + Text(favCompany.name) + }.padding() } // Delete from persistent storage .onDelete { indexSet in for index in indexSet { - viewContext.delete(favourites[index]) + viewContext.delete(favCompanies[index]) } do { try viewContext.save() @@ -51,9 +46,10 @@ } func addFavourite() { - let favourite = Favourite(context: viewContext) - favourite.cik = 12345 - favourite.isFavourite = true + let favCompany = FavCompany(context: viewContext) + favCompany.cik = 12345 + favCompany.symbol = "AAPL" + favCompany.name = "Apple Inc" do { try viewContext.save() print("Company saved.") @@ -61,15 +57,16 @@ print(error.localizedDescription) } } - - func updateFavourite(favourite: Favourite) { + /* + func updateFavourite(favCompany: FavCompany) { let newStatus = false viewContext.performAndWait { - favourite.isFavourite = newStatus + favCompany.cik = newStatus try? viewContext.save() print("Company updated") } } + */ } struct TestFavourites_Previews: PreviewProvider { @@ -77,3 +74,4 @@ TestFavourites() } } +*/ diff -r cf0168a29e4d -r 8023d420f437 lazybear/User.swift --- a/lazybear/User.swift Tue Jan 12 21:35:37 2021 +0000 +++ b/lazybear/User.swift Wed Jan 13 16:20:01 2021 +0000 @@ -9,41 +9,70 @@ struct User: View { @Environment(\.presentationMode) var userPresentation + @State var searchedCompany: String = "" + @State public var showingSearch: Bool = false // Search Bar + + @Environment(\.managedObjectContext) private var viewContext + @FetchRequest(entity: FavCompany.entity(), sortDescriptors: []) + var favCompanies: FetchedResults var body: some View { - VStack(alignment:.leading) { - HStack { - Button(action: {self.userPresentation.wrappedValue.dismiss() - }) { - Image(systemName: "multiply") - .resizable() - .frame(width: 25, height: 25) - + NavigationView { + VStack(alignment:.leading) { + SearchBar(searchedText: $searchedCompany, placeholder: "Add a company ...", showingSearch: $showingSearch, exitButton: "Done") + if showingSearch == false { + // Display favourites + List { + ForEach(favCompanies) { favCompany in + HStack { + Text(favCompany.name.capitalized) + + }.padding() + } + // Delete from persistent storage + .onDelete { indexSet in + for index in indexSet { + viewContext.delete(favCompanies[index]) + } + do { + try viewContext.save() + print("Company deleted") + } catch { + print(error.localizedDescription) + } + } + } + } + else { + if searchedCompany.count > 2 { + Spacer() + List { + ForEach(companiesData.filter({ searchedCompany.isEmpty ? true : $0.name.localizedStandardContains(searchedCompany) }), id: \.cik) { company in + FavCompanyRow(company: company) + } + } + .edgesIgnoringSafeArea(.bottom) + .cornerRadius(20) + .id(UUID()) // Increase speed in search the list + } Spacer() } } - - Text("My favourites") - .font(.largeTitle) - .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/) - - List { - HStack { - Image(systemName: "star") - .renderingMode(.original) + .padding() + .navigationTitle("My watchlist") + .navigationBarItems(leading: + Button(action: {self.userPresentation.wrappedValue.dismiss()}) { + Image(systemName: "multiply") .resizable() .frame(width: 25, height: 25) - - Text("Company 1") } - } + ) } - .padding() } } struct User_Previews: PreviewProvider { static var previews: some View { - User() + User() } }