diff --git a/LaunchIntents/IntentHandler.swift b/LaunchIntents/IntentHandler.swift index f43679c..a55b7a2 100644 --- a/LaunchIntents/IntentHandler.swift +++ b/LaunchIntents/IntentHandler.swift @@ -43,8 +43,6 @@ class IntentHandler: INExtension, SelectCountdownIntentHandling { } let cp = CountdownProperties(identifier: countdown.objectID.uriRepresentation().absoluteString, display: displayName) - cp.name = countdown.activity?.name - cp.duration = NSNumber(value: countdown.duration) return cp } diff --git a/LaunchWidget/LaunchWidget.intentdefinition b/LaunchWidget/LaunchWidget.intentdefinition index 006d76f..f5689af 100644 --- a/LaunchWidget/LaunchWidget.intentdefinition +++ b/LaunchWidget/LaunchWidget.intentdefinition @@ -182,34 +182,6 @@ INTypePropertyType SpeakableString - - INTypePropertyDisplayName - Name - INTypePropertyDisplayNameID - 1g3sqi - INTypePropertyDisplayPriority - 5 - INTypePropertyName - name - INTypePropertyTag - 100 - INTypePropertyType - String - - - INTypePropertyDisplayName - Duration - INTypePropertyDisplayNameID - NjMwkO - INTypePropertyDisplayPriority - 6 - INTypePropertyName - duration - INTypePropertyTag - 102 - INTypePropertyType - Decimal - diff --git a/LaunchWidget/LaunchWidget.swift b/LaunchWidget/LaunchWidget.swift index 3099134..0edb90c 100644 --- a/LaunchWidget/LaunchWidget.swift +++ b/LaunchWidget/LaunchWidget.swift @@ -16,15 +16,26 @@ struct Provider: IntentTimelineProvider { func getSnapshot(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) { - guard let countdown = configuration.countdown, - let identifier = countdown.identifier, - let duration = countdown.duration else { + guard let cp = configuration.countdown, + let identifier = cp.identifier, + let countdown = IntentDataProvider.main.countdown(id: identifier) else { print("WARNING PLACEHOLDER!") - completion(placeholder(in: context)) + + let entry = SimpleEntry(id: "", + name: "Not found", + duration: 0.0, + date: Date(), + configuration: configuration) + + completion(entry) return } - let entry = SimpleEntry(id: identifier, name: countdown.name, duration: duration.doubleValue, date: Date(), configuration: configuration) + let entry = SimpleEntry(id: identifier, + name: countdown.name, + duration: countdown.duration, + date: Date(), + configuration: configuration) completion(entry) } diff --git a/LaunchWidgetExtension.entitlements b/LaunchWidgetExtension.entitlements new file mode 100644 index 0000000..a7c6d47 --- /dev/null +++ b/LaunchWidgetExtension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.com.staxriver.countdown + + + diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index 2583fd8..8931169 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -45,6 +45,12 @@ C438C80D2982847300BF3EF9 /* CoreDataRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C80C2982847300BF3EF9 /* CoreDataRequests.swift */; }; C438C80F29828B8600BF3EF9 /* RecordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C80E29828B8600BF3EF9 /* RecordsView.swift */; }; C438C81129829EAF00BF3EF9 /* PropertyWrappers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C81029829EAF00BF3EF9 /* PropertyWrappers.swift */; }; + C438C8152982BD9000BF3EF9 /* IntentDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7FE2981300500BF3EF9 /* IntentDataProvider.swift */; }; + C438C8162982BE1E00BF3EF9 /* LeCountdown.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C4060DCA297AE73D003FAB80 /* LeCountdown.xcdatamodeld */; }; + C438C8172982BE9C00BF3EF9 /* Model+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C806298195E600BF3EF9 /* Model+Extensions.swift */; }; + C438C8182982BFC100BF3EF9 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4060DC8297AE73D003FAB80 /* Persistence.swift */; }; + C438C8192982BFDB00BF3EF9 /* NSManagedContext+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7C4298024E900BF3EF9 /* NSManagedContext+Extensions.swift */; }; + C438C81A2982BFF100BF3EF9 /* NSManagedContext+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7C4298024E900BF3EF9 /* NSManagedContext+Extensions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -133,6 +139,7 @@ C438C80C2982847300BF3EF9 /* CoreDataRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataRequests.swift; sourceTree = ""; }; C438C80E29828B8600BF3EF9 /* RecordsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordsView.swift; sourceTree = ""; }; C438C81029829EAF00BF3EF9 /* PropertyWrappers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyWrappers.swift; sourceTree = ""; }; + C438C8122982BAA100BF3EF9 /* LaunchWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LaunchWidgetExtension.entitlements; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -180,6 +187,7 @@ C4060DB3297AE73B003FAB80 = { isa = PBXGroup; children = ( + C438C8122982BAA100BF3EF9 /* LaunchWidgetExtension.entitlements */, C4060DBE297AE73B003FAB80 /* LeCountdown */, C4060DD5297AE73D003FAB80 /* LeCountdownTests */, C4060DDF297AE73D003FAB80 /* LeCountdownUITests */, @@ -549,10 +557,15 @@ files = ( C438C7EB2981266F00BF3EF9 /* CountdownView.swift in Sources */, C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */, + C438C8172982BE9C00BF3EF9 /* Model+Extensions.swift in Sources */, + C438C8162982BE1E00BF3EF9 /* LeCountdown.xcdatamodeld in Sources */, + C438C8152982BD9000BF3EF9 /* IntentDataProvider.swift in Sources */, C438C7DF2981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */, C438C7E82981255D00BF3EF9 /* TimeInterval+Extensions.swift in Sources */, C438C7D82981216200BF3EF9 /* LaunchWidgetLiveActivity.swift in Sources */, + C438C8192982BFDB00BF3EF9 /* NSManagedContext+Extensions.swift in Sources */, C438C7DA2981216200BF3EF9 /* LaunchWidget.swift in Sources */, + C438C8182982BFC100BF3EF9 /* Persistence.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -563,6 +576,7 @@ C438C7F529812BB200BF3EF9 /* IntentHandler.swift in Sources */, C438C80529813FB400BF3EF9 /* TimeInterval+Extensions.swift in Sources */, C438C802298132B900BF3EF9 /* LeCountdown.xcdatamodeld in Sources */, + C438C81A2982BFF100BF3EF9 /* NSManagedContext+Extensions.swift in Sources */, C438C8012981327600BF3EF9 /* Persistence.swift in Sources */, C438C7FD29812BF700BF3EF9 /* LaunchWidget.intentdefinition in Sources */, C438C800298130E900BF3EF9 /* IntentDataProvider.swift in Sources */, @@ -723,7 +737,6 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = LeCountdown/Info.plist; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; @@ -755,7 +768,6 @@ ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = LeCountdown/Info.plist; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; @@ -854,6 +866,7 @@ buildSettings = { ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CODE_SIGN_ENTITLEMENTS = LaunchWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 526E96RFNP; @@ -881,6 +894,7 @@ buildSettings = { ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CODE_SIGN_ENTITLEMENTS = LaunchWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 526E96RFNP; diff --git a/LeCountdown/Info.plist b/LeCountdown/Info.plist index 4badefc..3847eec 100644 --- a/LeCountdown/Info.plist +++ b/LeCountdown/Info.plist @@ -2,6 +2,10 @@ + NSUserActivityTypes + + SelectCountdownIntent + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -9,9 +13,5 @@ UISceneConfigurations - NSUserActivityTypes - - SelectCountdownIntent - diff --git a/LeCountdown/Model/CoreDataRequests.swift b/LeCountdown/Model/CoreDataRequests.swift index b7f448c..fe38f78 100644 --- a/LeCountdown/Model/CoreDataRequests.swift +++ b/LeCountdown/Model/CoreDataRequests.swift @@ -6,23 +6,37 @@ // import Foundation +import CoreData + +enum CountdownException : Error { + case entityNameNotFound +} class CoreDataRequests { - static func getOrCreateActivity(name: String) -> Activity { + static func findBy(property: String, value: V) throws -> T? { let context = PersistenceController.shared.container.viewContext - let request = Activity.fetchRequest() - request.predicate = NSPredicate(format: "name like %@", name) + if let entityName = T.entity().name { + let fetchRequest = NSFetchRequest(entityName: entityName) + fetchRequest.predicate = NSPredicate(format: "%K == %@", argumentArray: [property, value]) + let results = try context.fetch(fetchRequest) + return results.first + } else { + throw CountdownException.entityNameNotFound + } + } + + static func getOrCreateActivity(name: String) -> Activity { do { - let results = try context.fetch(request) - if let activity = results.first { + if let activity: Activity = try findBy(property: #keyPath(Activity.name), value: name) { return activity } } catch { print("error = \(error)") } + let context = PersistenceController.shared.container.viewContext let activity = Activity(context: context) activity.name = name return activity diff --git a/LeCountdown/Model/Model+Extensions.swift b/LeCountdown/Model/Model+Extensions.swift index b574f16..2c425e4 100644 --- a/LeCountdown/Model/Model+Extensions.swift +++ b/LeCountdown/Model/Model+Extensions.swift @@ -10,20 +10,9 @@ import SwiftUI extension Countdown { - var endDate: Date? { - return AppEnvironment.sun.notificationDates[self.stringId]?.end - } - var isLive: Bool { - return endDate != nil - } - - var colorForStatus: Color { - if isLive { - return Color(red: 0.9, green: 1.0, blue: 0.95) - } else { - return Color(red: 0.9, green: 0.95, blue: 1.0) - } + var name: String? { + return self.activity?.name } } diff --git a/LeCountdown/Views/ContentView.swift b/LeCountdown/Views/ContentView.swift index a7abe4e..4739787 100644 --- a/LeCountdown/Views/ContentView.swift +++ b/LeCountdown/Views/ContentView.swift @@ -160,6 +160,26 @@ struct ContentView: View { } +fileprivate extension Countdown { + + var endDate: Date? { + return AppEnvironment.sun.notificationDates[self.stringId]?.end + } + + var isLive: Bool { + return endDate != nil + } + + var colorForStatus: Color { + if isLive { + return Color(red: 0.9, green: 1.0, blue: 0.95) + } else { + return Color(red: 0.9, green: 0.95, blue: 1.0) + } + } + +} + //private let itemFormatter: DateFormatter = { // let formatter = DateFormatter() // formatter.dateStyle = .short diff --git a/LeCountdown/Widget/IntentDataProvider.swift b/LeCountdown/Widget/IntentDataProvider.swift index 8246aec..7e87b87 100644 --- a/LeCountdown/Widget/IntentDataProvider.swift +++ b/LeCountdown/Widget/IntentDataProvider.swift @@ -18,4 +18,9 @@ class IntentDataProvider { return try context.fetch(request) } + func countdown(id: String) -> Countdown? { + let context = PersistenceController.shared.container.viewContext + return context.object(stringId: id) as? Countdown + } + }