diff --git a/apple/Omnivore.xcodeproj/project.pbxproj b/apple/Omnivore.xcodeproj/project.pbxproj index 6e53e68b2..a928eedd5 100644 --- a/apple/Omnivore.xcodeproj/project.pbxproj +++ b/apple/Omnivore.xcodeproj/project.pbxproj @@ -1388,7 +1388,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 1.40.0; + MARKETING_VERSION = 1.41.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; @@ -1423,7 +1423,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 1.40.0; + MARKETING_VERSION = 1.41.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1478,7 +1478,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.40.0; + MARKETING_VERSION = 1.41.0; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; PRODUCT_NAME = Omnivore; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1819,7 +1819,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.40.0; + MARKETING_VERSION = 1.41.0; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; PRODUCT_NAME = Omnivore; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index a7535d14e..52af57555 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -152,19 +152,21 @@ struct WebReaderContainerView: View { label: { textToSpeechButtonImage } - ).buttonStyle(.plain) + ) + .buttonStyle(.plain) + .padding(.trailing, 4) ) } } var textToSpeechButtonImage: some View { if audioController.playbackError || audioController.state == .stopped || audioController.itemAudioProperties?.itemID != self.item.id { - return AnyView(Image.audioPlay.frame(width: 48, height: 48)) + return Image.audioPlay } if audioController.isPlayingItem(itemID: item.unwrappedID) { - return AnyView(Image.audioPause.frame(width: 48, height: 48)) + return Image.audioPause } - return AnyView(Image.audioPlay.frame(width: 48, height: 48)) + return Image.audioPlay } #endif @@ -299,7 +301,7 @@ struct WebReaderContainerView: View { } ) .buttonStyle(.plain) - .padding(.horizontal, 5) + .padding(.trailing, 5) .popover(isPresented: $showPreferencesPopover) { webPreferencesPopoverView .frame(maxWidth: 400, maxHeight: 475) diff --git a/apple/OmnivoreKit/Sources/Models/CoreData/StorageProvider.swift b/apple/OmnivoreKit/Sources/Models/CoreData/StorageProvider.swift index 558282ea5..30e8e9429 100644 --- a/apple/OmnivoreKit/Sources/Models/CoreData/StorageProvider.swift +++ b/apple/OmnivoreKit/Sources/Models/CoreData/StorageProvider.swift @@ -7,11 +7,9 @@ let logger = Logger(subsystem: "app.omnivore", category: "models") /// An `NSPersistentContainer` subclass that lives in the `Models` package so that /// the data model is looked for in the same package bundle (rather than the main bundle) public class PersistentContainer: NSPersistentContainer { - public static func make() -> PersistentContainer { - let modelURL = Bundle.module.url(forResource: "CoreDataModel", withExtension: "momd")! - let model = NSManagedObjectModel(contentsOf: modelURL)! - let container = PersistentContainer(name: "DataModel", managedObjectModel: model) + public static var DatabaseFile = "store.sqlite" + public static func path() -> URL? { // Store the sqlite file in the app group container. // This allows shared access for app and app extensions. #if os(iOS) @@ -20,7 +18,15 @@ public class PersistentContainer: NSPersistentContainer { let appGroupID = "QJF2XZ86HB.app.omnivore.app" #endif let appGroupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID) - let appGroupContainerURL = appGroupContainer?.appendingPathComponent("store.sqlite") + return appGroupContainer?.appendingPathComponent(DatabaseFile) + } + + public static func make() -> PersistentContainer { + let modelURL = Bundle.module.url(forResource: "CoreDataModel", withExtension: "momd")! + let model = NSManagedObjectModel(contentsOf: modelURL)! + let container = PersistentContainer(name: "DataModel", managedObjectModel: model) + let appGroupContainerURL = path() + logger.debug("starting with sqlite container \(appGroupContainerURL?.absoluteString ?? "(nil)")") container.persistentStoreDescriptions.first!.url = appGroupContainerURL diff --git a/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift b/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift index 54edeea16..a6743b4e0 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift @@ -53,6 +53,10 @@ public final class DataService: ObservableObject { } public init(appEnvironment: AppEnvironment, networker: Networker) { + if Self.isFirstTimeRunningNewAppBuild() { + Self.deleteLocalStorage() + } + self.appEnvironment = appEnvironment self.networker = networker self.persistentContainer = PersistentContainer.make() @@ -61,13 +65,9 @@ public final class DataService: ObservableObject { backgroundContext.automaticallyMergesChangesFromParent = true backgroundContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump - if isFirstTimeRunningNewAppBuild() { - resetLocalStorage() - } else { - persistentContainer.loadPersistentStores { _, error in - if let error = error { - fatalError("Core Data store failed to load with error: \(error)") - } + persistentContainer.loadPersistentStores { _, error in + if let error = error { + fatalError("Core Data store failed to load with error: \(error)") } } } @@ -190,16 +190,17 @@ public final class DataService: ObservableObject { } } - public func resetLocalStorage() { - viewContext.perform { - // We want to specify the order of deleting items to better handle relationships - let entities = ["LibraryItem", "Viewer", "Filter", "Highlight", "NewsletterEmail", - "LinkedItemLabel", "RecentSearchItem", "Recommendation", "RecommendationGroup", "UserProfile"] - entities.forEach { entityName in - self.deleteAllEntities(entityName: entityName, inContext: self.viewContext) + public static func deleteLocalStorage() { + do { + if let storeURL = PersistentContainer.path() { + try FileManager.default.removeItem(atPath: storeURL.path) } + } catch { + print(error.localizedDescription) } + } + public func resetLocalStorage() { UserDefaults.standard.set(nil, forKey: UserDefaultKey.lastSelectedTabItem.rawValue) lastItemSyncTime = Date(timeIntervalSinceReferenceDate: 0) @@ -216,7 +217,7 @@ public final class DataService: ObservableObject { backgroundContext = persistentContainer.newBackgroundContext() } - private func isFirstTimeRunningNewAppBuild() -> Bool { + private static func isFirstTimeRunningNewAppBuild() -> Bool { let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String let buildNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String