diff --git a/Firebonk.xcodeproj/project.pbxproj b/Firebonk.xcodeproj/project.pbxproj index 18ad634..0a04671 100644 --- a/Firebonk.xcodeproj/project.pbxproj +++ b/Firebonk.xcodeproj/project.pbxproj @@ -9,6 +9,11 @@ /* Begin PBXBuildFile section */ 344B1BB92970B4680047A1FF /* Localizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344B1BB82970B4680047A1FF /* Localizer.swift */; }; 344B1BBC2970B4E00047A1FF /* General.strings in Resources */ = {isa = PBXBuildFile; fileRef = 344B1BBE2970B4E00047A1FF /* General.strings */; }; + 344B1BC52971CDE30047A1FF /* Firebonk.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 344B1BC32971CDE30047A1FF /* Firebonk.xcdatamodeld */; }; + 344B1BC72971CE1A0047A1FF /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344B1BC62971CE1A0047A1FF /* Persistence.swift */; }; + 344B1BCB2971D0620047A1FF /* Login.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344B1BCA2971D0620047A1FF /* Login.swift */; }; + 344B1BCE2971D0E00047A1FF /* User+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344B1BCD2971D0E00047A1FF /* User+CoreDataClass.swift */; }; + 344B1BD02971D0F70047A1FF /* User+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344B1BCF2971D0F70047A1FF /* User+CoreDataProperties.swift */; }; 349639EB297061D6002B1FB8 /* FirebonkApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349639EA297061D6002B1FB8 /* FirebonkApp.swift */; }; 349639EF297061D6002B1FB8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349639EE297061D6002B1FB8 /* ContentView.swift */; }; 349639F1297061D7002B1FB8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 349639F0297061D7002B1FB8 /* Assets.xcassets */; }; @@ -44,6 +49,11 @@ 344B1BB82970B4680047A1FF /* Localizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Localizer.swift; sourceTree = ""; }; 344B1BBD2970B4E00047A1FF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/General.strings; sourceTree = ""; }; 344B1BBF2970B4E30047A1FF /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/General.strings; sourceTree = ""; }; + 344B1BC42971CDE30047A1FF /* Firebonk.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Firebonk.xcdatamodel; sourceTree = ""; }; + 344B1BC62971CE1A0047A1FF /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; + 344B1BCA2971D0620047A1FF /* Login.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Login.swift; sourceTree = ""; }; + 344B1BCD2971D0E00047A1FF /* User+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "User+CoreDataClass.swift"; sourceTree = ""; }; + 344B1BCF2971D0F70047A1FF /* User+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "User+CoreDataProperties.swift"; sourceTree = ""; }; 349639E7297061D6002B1FB8 /* Firebonk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Firebonk.app; sourceTree = BUILT_PRODUCTS_DIR; }; 349639EA297061D6002B1FB8 /* FirebonkApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebonkApp.swift; sourceTree = ""; }; 349639EE297061D6002B1FB8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -104,6 +114,33 @@ path = API; sourceTree = ""; }; + 344B1BC22971CD9A0047A1FF /* CoreData */ = { + isa = PBXGroup; + children = ( + 344B1BCC2971D0D20047A1FF /* Models */, + 344B1BC32971CDE30047A1FF /* Firebonk.xcdatamodeld */, + 344B1BC62971CE1A0047A1FF /* Persistence.swift */, + ); + path = CoreData; + sourceTree = ""; + }; + 344B1BC92971D0570047A1FF /* Other */ = { + isa = PBXGroup; + children = ( + 344B1BCA2971D0620047A1FF /* Login.swift */, + ); + path = Other; + sourceTree = ""; + }; + 344B1BCC2971D0D20047A1FF /* Models */ = { + isa = PBXGroup; + children = ( + 344B1BCD2971D0E00047A1FF /* User+CoreDataClass.swift */, + 344B1BCF2971D0F70047A1FF /* User+CoreDataProperties.swift */, + ); + path = Models; + sourceTree = ""; + }; 349639DE297061D6002B1FB8 = { isa = PBXGroup; children = ( @@ -127,10 +164,11 @@ 349639E9297061D6002B1FB8 /* Firebonk */ = { isa = PBXGroup; children = ( - 344B1BC02970BA6F0047A1FF /* Utils */, 34963A28297064D2002B1FB8 /* App */, 34963A2929706503002B1FB8 /* Views */, + 344B1BC02970BA6F0047A1FF /* Utils */, 34963A2A29706510002B1FB8 /* SupportingFiles */, + 344B1BC22971CD9A0047A1FF /* CoreData */, 34963A2129706390002B1FB8 /* i18n */, 349639F4297061D7002B1FB8 /* Preview Content */, ); @@ -195,6 +233,7 @@ 34963A2929706503002B1FB8 /* Views */ = { isa = PBXGroup; children = ( + 344B1BC92971D0570047A1FF /* Other */, 34963A18297062B5002B1FB8 /* Tabs */, ); path = Views; @@ -343,11 +382,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 344B1BC72971CE1A0047A1FF /* Persistence.swift in Sources */, + 344B1BCB2971D0620047A1FF /* Login.swift in Sources */, + 344B1BD02971D0F70047A1FF /* User+CoreDataProperties.swift in Sources */, 349639EB297061D6002B1FB8 /* FirebonkApp.swift in Sources */, 34963A1A297062E7002B1FB8 /* Dashboard.swift in Sources */, 34963A2029706305002B1FB8 /* Profile.swift in Sources */, 349639EF297061D6002B1FB8 /* ContentView.swift in Sources */, 34963A1E297062FA002B1FB8 /* Spaces.swift in Sources */, + 344B1BC52971CDE30047A1FF /* Firebonk.xcdatamodeld in Sources */, + 344B1BCE2971D0E00047A1FF /* User+CoreDataClass.swift in Sources */, 344B1BB92970B4680047A1FF /* Localizer.swift in Sources */, 34963A1C297062F2002B1FB8 /* People.swift in Sources */, ); @@ -523,6 +567,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CODE_SIGN_ENTITLEMENTS = Firebonk/SupportingFiles/Firebonk.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -564,6 +609,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CODE_SIGN_ENTITLEMENTS = Firebonk/SupportingFiles/Firebonk.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -730,6 +776,19 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + 344B1BC32971CDE30047A1FF /* Firebonk.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + 344B1BC42971CDE30047A1FF /* Firebonk.xcdatamodel */, + ); + currentVersion = 344B1BC42971CDE30047A1FF /* Firebonk.xcdatamodel */; + path = Firebonk.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = 349639DF297061D6002B1FB8 /* Project object */; } diff --git a/Firebonk/App/ContentView.swift b/Firebonk/App/ContentView.swift index 0fd0b4c..61428b5 100644 --- a/Firebonk/App/ContentView.swift +++ b/Firebonk/App/ContentView.swift @@ -8,31 +8,51 @@ import SwiftUI struct ContentView: View { + @State private var user: User? var body: some View { - TabView { - Dashboard() - // Badge can show e.g. number of notifications or new posts - //.badge(2) - .tabItem { - Label("dashboard".localized(tableName: "General"), systemImage: "house.fill") - } - People() - .tabItem { - Label("people".localized(tableName: "General"), systemImage: "person.3.fill") - } - Spaces() - .tabItem { - Label("spaces".localized(tableName: "General"), systemImage: "circle.circle") - } - Profile() - .tabItem{ - Label("profile".localized(tableName: "General"), systemImage: "person") - } + if(self.userInfoPresent()) { + TabView { + Dashboard() + // Badge can show e.g. number of notifications or new posts + //.badge(2) + .tabItem { + Label("dashboard".localized(tableName: "General"), systemImage: "house.fill") + } + People() + .tabItem { + Label("people".localized(tableName: "General"), systemImage: "person.3.fill") + } + Spaces() + .tabItem { + Label("spaces".localized(tableName: "General"), systemImage: "circle.circle") + } + Profile() + .tabItem{ + Label("profile".localized(tableName: "General"), systemImage: "person") + } + } + } else { + Login() } } } +extension ContentView { + func userInfoPresent() -> Bool { + let users = User.getAll() + if(users.count < 1) { + return false + } + + let user: User = users[0] + print("Users: ") + print(user) + self.user = user + return true + } +} + struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() diff --git a/Firebonk/App/FirebonkApp.swift b/Firebonk/App/FirebonkApp.swift index 6d771c0..4a9105f 100644 --- a/Firebonk/App/FirebonkApp.swift +++ b/Firebonk/App/FirebonkApp.swift @@ -9,9 +9,12 @@ import SwiftUI @main struct FirebonkApp: App { + let persistenceController = PersistenceController.shared + var body: some Scene { WindowGroup { ContentView() + .environment(\.managedObjectContext, persistenceController.context) } } } diff --git a/Firebonk/CoreData/Firebonk.xcdatamodeld/Firebonk.xcdatamodel/contents b/Firebonk/CoreData/Firebonk.xcdatamodeld/Firebonk.xcdatamodel/contents new file mode 100644 index 0000000..8953d28 --- /dev/null +++ b/Firebonk/CoreData/Firebonk.xcdatamodeld/Firebonk.xcdatamodel/contents @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Firebonk/CoreData/Models/User+CoreDataClass.swift b/Firebonk/CoreData/Models/User+CoreDataClass.swift new file mode 100644 index 0000000..4a126d9 --- /dev/null +++ b/Firebonk/CoreData/Models/User+CoreDataClass.swift @@ -0,0 +1,43 @@ +// +// User+CoreDataClass.swift +// Firebonk +// +// Created by Patrick Müller on 13.01.23. +// + +import Foundation +import CoreData + +@objc(User) +public class User: NSManagedObject { + @nonobjc public class func getAll() -> [User] { + let managedContext = + PersistenceController.shared.context + + do { + return try managedContext.fetch(User.fetchRequest()) + } catch let error as NSError { + print("Could not fetch. \(error), \(error.userInfo)") + return [] + } + } + + @nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [User]{ + let managedContext = + PersistenceController.shared.context + + let fetchRequest: NSFetchRequest = User.fetchRequest() + + fetchRequest.sortDescriptors = sortDescriptors + if(searchPredicate != nil) { + fetchRequest.predicate = searchPredicate + } + + do { + return try managedContext.fetch(fetchRequest) + } catch let error as NSError { + print("Could not fetch. \(error), \(error.userInfo)") + return [] + } + } +} diff --git a/Firebonk/CoreData/Models/User+CoreDataProperties.swift b/Firebonk/CoreData/Models/User+CoreDataProperties.swift new file mode 100644 index 0000000..ced0e6e --- /dev/null +++ b/Firebonk/CoreData/Models/User+CoreDataProperties.swift @@ -0,0 +1,26 @@ +// +// User+CoreDataProperties.swift +// Firebonk +// +// Created by Patrick Müller on 13.01.23. +// + +import Foundation +import CoreData + + +extension User { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "User") + } + + @NSManaged public var username: String? + @NSManaged public var jwt: String? + @NSManaged public var firstName: String? + +} + +extension User : Identifiable { + +} diff --git a/Firebonk/CoreData/Persistence.swift b/Firebonk/CoreData/Persistence.swift new file mode 100644 index 0000000..93a2426 --- /dev/null +++ b/Firebonk/CoreData/Persistence.swift @@ -0,0 +1,78 @@ +// +// Persistence.swift +// Firebonk +// +// Created by Patrick Müller on 13.01.23. +// + +import Foundation +import CoreData + +struct PersistenceController { + // Singleton + static let shared = PersistenceController() + + // Cloud Kit container + let container: NSPersistentCloudKitContainer + + // Managed object context + public var context: NSManagedObjectContext { + get { + return self.container.viewContext + } + } + + // MARK: - Constructor + init(inMemory: Bool = false) { + container = NSPersistentCloudKitContainer(name: "Firebonk") + if inMemory { + container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") + } + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error as NSError? { + // Replace this implementation with code to handle the error appropriately. + // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + + /* + Typical reasons for an error here include: + * The parent directory does not exist, cannot be created, or disallows writing. + * The persistent store is not accessible, due to permissions or data protection when the device is locked. + * The device is out of space. + * The store could not be migrated to the current model version. + Check the error message to determine what the actual problem was. + */ + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + } + + // MARK: - Core Data Saving support + + public func save() { + if self.context.hasChanges { + do { + try self.context.save() + print("In PersistenceController.shared.save()") + } catch { + let nserror = error as NSError + fatalError("Unresolved error \(nserror), \(nserror.userInfo)") + } + } + } + + // MARK: - Preview content + static var preview: PersistenceController = { + let result = PersistenceController(inMemory: true) + let viewContext = result.container.viewContext + + do { + try viewContext.save() + } catch { + // Replace this implementation with code to handle the error appropriately. + // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + let nsError = error as NSError + fatalError("Unresolved error \(nsError), \(nsError.userInfo)") + } + return result + }() +} diff --git a/Firebonk/Views/Other/Login.swift b/Firebonk/Views/Other/Login.swift new file mode 100644 index 0000000..31d4354 --- /dev/null +++ b/Firebonk/Views/Other/Login.swift @@ -0,0 +1,31 @@ +// +// Login.swift +// Firebonk +// +// Created by Patrick Müller on 13.01.23. +// + +import SwiftUI + +struct Login: View { + var body: some View { + Text("Login screen") + } +} + +extension Login { + func saveUserData() { + let user = User(context: PersistenceController.shared.context) + user.username = "Paddy" + user.jwt = "" + user.firstName = "Patrick" + + PersistenceController.shared.save() + } +} + +struct Login_Previews: PreviewProvider { + static var previews: some View { + Login() + } +}