mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
fix linkeditem and labels data relationships. reset coredata on new app installs
This commit is contained in:
parent
f3aac3e30c
commit
b45120706b
7 changed files with 59 additions and 21 deletions
|
|
@ -64,7 +64,7 @@ import Views
|
|||
}
|
||||
|
||||
func saveItemLabelChanges(itemID: String, dataService: DataService) {
|
||||
dataService.updateItemLabels(itemID: itemID, labelNames: selectedLabels.map(\.unwrappedName))
|
||||
dataService.updateItemLabels(itemID: itemID, labelIDs: selectedLabels.map(\.unwrappedID))
|
||||
}
|
||||
|
||||
func addLabelToItem(_ label: LinkedItemLabel) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
<attribute name="slug" attributeType="String"/>
|
||||
<attribute name="title" attributeType="String"/>
|
||||
<relationship name="highlights" toMany="YES" deletionRule="Cascade" destinationEntity="Highlight" inverseName="linkedItem" inverseEntity="Highlight"/>
|
||||
<relationship name="labels" toMany="YES" deletionRule="Nullify" destinationEntity="LinkedItemLabel"/>
|
||||
<relationship name="labels" toMany="YES" deletionRule="Nullify" destinationEntity="LinkedItemLabel" inverseName="linkedItems" inverseEntity="LinkedItemLabel"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
<attribute name="labelDescription" optional="YES" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="serverSyncStatus" attributeType="Integer 64" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<relationship name="linkedItems" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="LinkedItem" inverseName="labels" inverseEntity="LinkedItem"/>
|
||||
<uniquenessConstraints>
|
||||
<uniquenessConstraint>
|
||||
<constraint value="id"/>
|
||||
|
|
@ -85,7 +86,7 @@
|
|||
<elements>
|
||||
<element name="Highlight" positionX="27" positionY="225" width="128" height="224"/>
|
||||
<element name="LinkedItem" positionX="-18" positionY="63" width="128" height="344"/>
|
||||
<element name="LinkedItemLabel" positionX="-36" positionY="18" width="128" height="119"/>
|
||||
<element name="LinkedItemLabel" positionX="-36" positionY="18" width="128" height="134"/>
|
||||
<element name="NewsletterEmail" positionX="0" positionY="180" width="128" height="74"/>
|
||||
<element name="Viewer" positionX="45" positionY="234" width="128" height="89"/>
|
||||
</elements>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import CoreData
|
|||
import Foundation
|
||||
import Models
|
||||
import OSLog
|
||||
import Utils
|
||||
|
||||
let logger = Logger(subsystem: "app.omnivore", category: "data-service")
|
||||
|
||||
|
|
@ -13,8 +14,8 @@ public final class DataService: ObservableObject {
|
|||
public let appEnvironment: AppEnvironment
|
||||
let networker: Networker
|
||||
|
||||
let persistentContainer: PersistentContainer
|
||||
let backgroundContext: NSManagedObjectContext
|
||||
var persistentContainer: PersistentContainer
|
||||
var backgroundContext: NSManagedObjectContext
|
||||
var subscriptions = Set<AnyCancellable>()
|
||||
|
||||
public var viewContext: NSManagedObjectContext {
|
||||
|
|
@ -28,9 +29,13 @@ public final class DataService: ObservableObject {
|
|||
self.backgroundContext = persistentContainer.newBackgroundContext()
|
||||
backgroundContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
|
||||
|
||||
persistentContainer.loadPersistentStores { _, error in
|
||||
if let error = error {
|
||||
fatalError("Core Data store failed to load with error: \(error)")
|
||||
if isFirstTimeRunningNewAppVersion() {
|
||||
resetCoreData()
|
||||
} else {
|
||||
persistentContainer.loadPersistentStores { _, error in
|
||||
if let error = error {
|
||||
fatalError("Core Data store failed to load with error: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,4 +54,38 @@ public final class DataService: ObservableObject {
|
|||
fatalError("Unable to write to Keychain: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
private func resetCoreData() {
|
||||
let storeContainer =
|
||||
persistentContainer.persistentStoreCoordinator
|
||||
|
||||
do {
|
||||
for store in storeContainer.persistentStores {
|
||||
try storeContainer.destroyPersistentStore(
|
||||
at: store.url!,
|
||||
ofType: store.type,
|
||||
options: nil
|
||||
)
|
||||
}
|
||||
persistentContainer = PersistentContainer.make()
|
||||
persistentContainer.loadPersistentStores { _, error in
|
||||
if let error = error {
|
||||
fatalError("Core Data store failed to load with error: \(error)")
|
||||
}
|
||||
}
|
||||
backgroundContext = persistentContainer.newBackgroundContext()
|
||||
} catch {
|
||||
logger.debug("Failed to reset core data stores")
|
||||
}
|
||||
}
|
||||
|
||||
private func isFirstTimeRunningNewAppVersion() -> Bool {
|
||||
let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")
|
||||
guard let appVersion = appVersion as? String else { return false }
|
||||
|
||||
let lastUsedAppVersion = UserDefaults.standard.string(forKey: UserDefaultKey.lastUsedAppVersion.rawValue)
|
||||
let isFirstRun = (lastUsedAppVersion ?? "unknown") != appVersion
|
||||
UserDefaults.standard.set(appVersion, forKey: UserDefaultKey.lastUsedAppVersion.rawValue)
|
||||
return isFirstRun
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ extension DataService {
|
|||
// Update CoreData
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let label = LinkedItemLabel.lookup(byName: name, inContext: self.backgroundContext) else { return }
|
||||
guard let label = LinkedItemLabel.lookup(byID: labelID, inContext: self.backgroundContext) else { return }
|
||||
label.remove(inContext: self.backgroundContext)
|
||||
|
||||
// Send update to server
|
||||
|
|
@ -15,7 +15,7 @@ extension DataService {
|
|||
}
|
||||
}
|
||||
|
||||
func syncLabelDeletion(labelID: String, labelName: String) {
|
||||
func syncLabelDeletion(labelID: String, labelName _: String) {
|
||||
enum MutationResult {
|
||||
case success(labelID: String)
|
||||
case error(errorCode: Enums.DeleteLabelErrorCode)
|
||||
|
|
@ -43,7 +43,7 @@ extension DataService {
|
|||
let isSyncSuccess = data != nil
|
||||
|
||||
context.perform {
|
||||
let label = LinkedItemLabel.lookup(byName: labelName, inContext: context)
|
||||
let label = LinkedItemLabel.lookup(byID: labelID, inContext: context)
|
||||
guard let label = label else { return }
|
||||
|
||||
if isSyncSuccess {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Models
|
|||
import SwiftGraphQL
|
||||
|
||||
extension DataService {
|
||||
public func updateItemLabels(itemID: String, labelNames: [String]) {
|
||||
public func updateItemLabels(itemID: String, labelIDs: [String]) {
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) else { return }
|
||||
|
|
@ -13,12 +13,9 @@ extension DataService {
|
|||
linkedItem.removeFromLabels(existingLabels)
|
||||
}
|
||||
|
||||
var labelIDs = [String]()
|
||||
|
||||
for labelName in labelNames {
|
||||
if let labelObject = LinkedItemLabel.lookup(byName: labelName, inContext: self.backgroundContext) {
|
||||
for labelID in labelIDs {
|
||||
if let labelObject = LinkedItemLabel.lookup(byID: labelID, inContext: self.backgroundContext) {
|
||||
linkedItem.addToLabels(labelObject)
|
||||
labelIDs.append(labelObject.unwrappedID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ struct InternalLinkedItemLabel {
|
|||
}
|
||||
|
||||
func asManagedObject(inContext context: NSManagedObjectContext) -> LinkedItemLabel {
|
||||
let existingItem = LinkedItemLabel.lookup(byName: name, inContext: context)
|
||||
let label = existingItem ?? LinkedItemLabel(entity: LinkedItemLabel.entity(), insertInto: context)
|
||||
let existingLabel = LinkedItemLabel.lookup(byID: id, inContext: context)
|
||||
let label = existingLabel ?? LinkedItemLabel(entity: LinkedItemLabel.entity(), insertInto: context)
|
||||
label.id = id
|
||||
label.name = name
|
||||
label.color = color
|
||||
|
|
@ -44,10 +44,10 @@ extension LinkedItemLabel {
|
|||
public var unwrappedID: String { id ?? "" }
|
||||
public var unwrappedName: String { name ?? "" }
|
||||
|
||||
static func lookup(byName name: String, inContext context: NSManagedObjectContext) -> LinkedItemLabel? {
|
||||
static func lookup(byID id: String, inContext context: NSManagedObjectContext) -> LinkedItemLabel? {
|
||||
let fetchRequest: NSFetchRequest<Models.LinkedItemLabel> = LinkedItemLabel.fetchRequest()
|
||||
fetchRequest.predicate = NSPredicate(
|
||||
format: "%K == %@", #keyPath(LinkedItemLabel.name), name
|
||||
format: "id == %@", id
|
||||
)
|
||||
|
||||
var label: LinkedItemLabel?
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ public enum UserDefaultKey: String {
|
|||
case firebasePushToken
|
||||
case homeFeedlayoutPreference
|
||||
case lastSelectedLinkedItemFilter
|
||||
case lastUsedAppVersion
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue