Skip to content

Commit

Permalink
Reworking/refactoring to share functionality with Daily Calorie Track…
Browse files Browse the repository at this point in the history
…er (#12)
  • Loading branch information
reedes authored Mar 6, 2023
1 parent 3bacc1a commit bf2ff23
Show file tree
Hide file tree
Showing 73 changed files with 2,717 additions and 1,760 deletions.
6 changes: 6 additions & 0 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
--wraparguments after-first

# was changing
# let routine: Routine = Routine.get(viewContext, forURIRepresentation: routineURI)
# to
# let routine = Routine.get(viewContext, forURIRepresentation: routineURI)
--disable redundantType
4 changes: 3 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// swift-tools-version: 5.7
//
//

import PackageDescription

Expand All @@ -11,11 +11,13 @@ let package = Package(name: "GroutLib",
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections.git", from: "1.0.4"),
.package(url: "https://github.com/open-trackers/TrackerLib.git", from: "1.0.0"),
],
targets: [
.target(name: "GroutLib",
dependencies: [
.product(name: "Collections", package: "swift-collections"),
.product(name: "TrackerLib", package: "TrackerLib"),
],
path: "Sources"),
.testTarget(name: "GroutLibTests",
Expand Down
33 changes: 33 additions & 0 deletions Sources/CoreDataStack/CoreDataStack-clear.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// CoreDataStack-clear.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import CoreData

import TrackerLib

extension CoreDataStack {
/// Clear Categories and Servings from the main store. (Should not be present in Archive store.)
/// NOTE: does NOT save context
func clearPrimaryEntities(_ context: NSManagedObjectContext) throws {
try context.deleter(AppSetting.self)
try context.deleter(Exercise.self)
try context.deleter(Routine.self)
}

/// Clear the log entities from the specified store.
/// If no store specified, it will clear from all stores.
/// NOTE: does NOT save context
public func clearZEntities(_ context: NSManagedObjectContext, inStore: NSPersistentStore? = nil) throws {
try context.deleter(ZExerciseRun.self, inStore: inStore)
try context.deleter(ZExercise.self, inStore: inStore)
try context.deleter(ZRoutineRun.self, inStore: inStore)
try context.deleter(ZRoutine.self, inStore: inStore)
}
}
31 changes: 31 additions & 0 deletions Sources/CoreDataStack/CoreDataStack-preview.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// CoreDataStack-preview.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import CoreData

import TrackerLib

public extension CoreDataStack {
// obtain a manager that has been cleared of all data
static func getPreviewStack() -> CoreDataStack {
do {
let stack = CoreDataStack(isCloud: false, fileNamePrefix: "Test")

let ctx = stack.container.viewContext
try stack.clearPrimaryEntities(ctx)
try stack.clearZEntities(ctx)
try ctx.save()

return stack
} catch {
fatalError("Could not obtain preview core data stack.")
}
}
}
32 changes: 32 additions & 0 deletions Sources/CoreDataStack/CoreDataStack-stores.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// CoreDataStack-stores.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import CoreData

import TrackerLib

public extension CoreDataStack {
enum StoreType: String {
case main = ""
case archive
}

func getMainStore(_ context: NSManagedObjectContext) -> NSPersistentStore? {
getStore(context, .main)
}

func getArchiveStore(_ context: NSManagedObjectContext) -> NSPersistentStore? {
getStore(context, .archive)
}

private func getStore(_ context: NSManagedObjectContext, _ storeType: StoreType) -> NSPersistentStore? {
getStore(context, storeKey: storeType.rawValue)
}
}
113 changes: 113 additions & 0 deletions Sources/CoreDataStack/CoreDataStack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// CoreDataStack.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import CoreData

import TrackerLib

// NOTE: needed to pass as .environmentObject
extension CoreDataStack: ObservableObject {}

// NOTE that we're using two stores with a single configuration,
// where the Z* records on 'main' store eventually will be transferred
// to the 'archive' store on iOS, to reduce watch storage needs.
public final class CoreDataStack: BaseCoreDataStack {
static let modelName = "Grout"
static let baseFileName = "Grout"
static let cloudPrefix = "iCloud.org.openalloc.grout"
// static let archiveSuffix = "archive"

#if os(watchOS)
// NOTE the watch won't get the archive store
let storeKeys = [StoreType.main.rawValue]
#else
let storeKeys = [StoreType.main.rawValue, StoreType.archive.rawValue]
#endif

public init(isCloud: Bool, fileNamePrefix: String = "") {
let cloudPrefix = isCloud ? CoreDataStack.cloudPrefix : nil

super.init(modelName: CoreDataStack.modelName,
baseFileName: CoreDataStack.baseFileName,
cloudPrefix: cloudPrefix,
fileNamePrefix: fileNamePrefix,
storeKeys: storeKeys)
}

override public func loadModel(modelName: String) -> NSManagedObjectModel {
let bundle = Bundle.module
let modelURL = bundle.url(forResource: modelName, withExtension: ".momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}

// for de-duping
// NOTE that this is happening on background thread
// NOTE handler is responsible for saving context
override public func handleInsert(backgroundContext: NSManagedObjectContext,
entityName: String,
objectID: NSManagedObjectID,
storeID: String)
{
logger.debug("handleInsert: name=\(entityName) uri=\(objectID.uriRepresentation().absoluteString.suffix(5)), storeID=\(storeID.suffix(5))")

guard let mainStore = getMainStore(backgroundContext) else {
logger.error("handleInsert: unable to get main store")
return
}

#if !os(watchOS)
guard let archiveStore = getArchiveStore(backgroundContext) else {
logger.error("handleInsert: unable to get archive store")
return
}
#endif

let object = backgroundContext.object(with: objectID)

do {
switch entityName {
case AppSetting.entity().name:
try AppSetting.dedupe(backgroundContext)
case Exercise.entity().name:
try Exercise.dedupe(backgroundContext, object)
case Routine.entity().name:
try Routine.dedupe(backgroundContext, object)
case ZExercise.entity().name:
try ZExercise.dedupe(backgroundContext, object, inStore: mainStore)
#if !os(watchOS)
try ZExercise.dedupe(backgroundContext, object, inStore: archiveStore)
#endif
case ZExerciseRun.entity().name:
try ZExerciseRun.dedupe(backgroundContext, object, inStore: mainStore)
#if !os(watchOS)
try ZExerciseRun.dedupe(backgroundContext, object, inStore: archiveStore)
#endif
case ZRoutine.entity().name:
try ZRoutine.dedupe(backgroundContext, object, inStore: mainStore)
#if !os(watchOS)
try ZRoutine.dedupe(backgroundContext, object, inStore: archiveStore)
#endif
case ZRoutineRun.entity().name:
try ZRoutineRun.dedupe(backgroundContext, object, inStore: mainStore)
#if !os(watchOS)
try ZRoutineRun.dedupe(backgroundContext, object, inStore: archiveStore)
#endif
default:
_ = 0
}

try backgroundContext.save() // should automatically merge changes into foreground context
} catch let error as TrackerError {
logger.error("handleInsert: \(error)")
} catch {
logger.error("handleInsert: \(error.localizedDescription)")
}
}
}
30 changes: 0 additions & 30 deletions Sources/DataError.swift

This file was deleted.

22 changes: 0 additions & 22 deletions Sources/Date-extension.swift

This file was deleted.

Loading

0 comments on commit bf2ff23

Please sign in to comment.