diff --git a/LaunchIntents/IntentHandler.swift b/LaunchIntents/IntentHandler.swift index a55b7a2..244740a 100644 --- a/LaunchIntents/IntentHandler.swift +++ b/LaunchIntents/IntentHandler.swift @@ -9,23 +9,15 @@ import Intents class IntentHandler: INExtension, SelectCountdownIntentHandling { -// func resolveCountdown(for intent: SelectCountdownIntent, with completion: @escaping (CountdownPropertiesResolutionResult) -> Void) { -// } - - func resolveCountdown(for intent: SelectCountdownIntent) async -> CountdownPropertiesResolutionResult { + func resolveCountdown(for intent: SelectCountdownIntent) async -> [CountdownPropertiesResolutionResult] { print("***resolveCountdown") - if let countdown = intent.countdown { - return CountdownPropertiesResolutionResult.success(with: countdown) - } else { - return CountdownPropertiesResolutionResult.needsValue() + if let properties = intent.countdown?.first { + return [CountdownPropertiesResolutionResult.success(with: properties)] } + return [CountdownPropertiesResolutionResult.needsValue()] + } -// func provideCountdownOptionsCollection(for intent: SelectCountdownIntent, with completion: @escaping (INObjectCollection?, Error?) -> Void) { -// -// -// } - func provideCountdownOptionsCollection(for intent: SelectCountdownIntent) async throws -> INObjectCollection { print("*** provideCountdownOptionsCollection") diff --git a/LaunchWidget/CountdownView.swift b/LaunchWidget/CountdownView.swift index d3c4507..0b186f9 100644 --- a/LaunchWidget/CountdownView.swift +++ b/LaunchWidget/CountdownView.swift @@ -7,18 +7,18 @@ import SwiftUI import WidgetKit +import CoreData struct CountdownView: View { @Environment(\.widgetFamily) var family: WidgetFamily - var name: String? - var duration: Double + var countdown: Countdown var body: some View { VStack { - Text(name ?? "") - Text(duration.minuteSecond) + Text(countdown.name ?? "") + Text(countdown.duration.minuteSecond) } .font(self.font) } @@ -34,8 +34,50 @@ struct CountdownView: View { } +struct CountdownMultiView: View { + + @Environment(\.widgetFamily) var family: WidgetFamily + + var countdowns: [Countdown] + + var body: some View { + + HStack { + ForEach(countdowns) { countdown in + VStack { + Text(countdown.name ?? "") + Text(countdown.duration.minuteSecond) + } + .font(self.font) + .widgetURL(countdown.url) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + }.frame(maxWidth: .infinity) + + } + + private var font: Font { + switch family { + case .systemSmall, .systemMedium, .systemLarge, .systemExtraLarge: + return .title2 + default: + return .body + } + } + +} + struct CountdownView_Previews: PreviewProvider { static var previews: some View { - CountdownView(name: "Tea", duration: 3 * 60.0).previewContext(WidgetPreviewContext(family: .accessoryRectangular)) + + CountdownView(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryRectangular)) + CountdownMultiView(countdowns: self.countdowns(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemMedium)) } + + static func countdowns(context: NSManagedObjectContext) -> [Countdown] { + return (0..<4).map { _ in + Countdown.fake(context: context) + } + } + } diff --git a/LaunchWidget/LaunchWidget.intentdefinition b/LaunchWidget/LaunchWidget.intentdefinition index f5689af..afad2f3 100644 --- a/LaunchWidget/LaunchWidget.intentdefinition +++ b/LaunchWidget/LaunchWidget.intentdefinition @@ -26,12 +26,63 @@ INIntentIneligibleForSuggestions INIntentLastParameterTag - 2 + 3 INIntentName SelectCountdown INIntentParameters + INIntentParameterArraySizes + + + INIntentParameterArraySizeSize + 1 + INIntentParameterArraySizeSizeClass + Small + + + INIntentParameterArraySizeSize + 4 + INIntentParameterArraySizeSizeClass + Medium + + + INIntentParameterArraySizeSize + 8 + INIntentParameterArraySizeSizeClass + Large + + + INIntentParameterArraySizeSize + 12 + INIntentParameterArraySizeSizeClass + ExtraLarge + + + INIntentParameterArraySizeSize + 1 + INIntentParameterArraySizeSizeClass + AccessoryInline + + + INIntentParameterArraySizeSize + 1 + INIntentParameterArraySizeSizeClass + AccessoryCorner + + + INIntentParameterArraySizeSize + 1 + INIntentParameterArraySizeSizeClass + AccessoryCircular + + + INIntentParameterArraySizeSize + 2 + INIntentParameterArraySizeSizeClass + AccessoryRectangular + + INIntentParameterConfigurable INIntentParameterCustomDisambiguation @@ -42,6 +93,8 @@ lE8mOk INIntentParameterDisplayPriority 1 + INIntentParameterFixedSizeArray + 1 INIntentParameterName countdown INIntentParameterObjectType @@ -85,10 +138,12 @@ INIntentParameterSupportsDynamicEnumeration + INIntentParameterSupportsMultipleValues + INIntentParameterSupportsResolution INIntentParameterTag - 2 + 3 INIntentParameterType Object diff --git a/LaunchWidget/LaunchWidget.swift b/LaunchWidget/LaunchWidget.swift index 0edb90c..9a741bc 100644 --- a/LaunchWidget/LaunchWidget.swift +++ b/LaunchWidget/LaunchWidget.swift @@ -11,29 +11,26 @@ import Intents struct Provider: IntentTimelineProvider { func placeholder(in context: Context) -> SimpleEntry { - SimpleEntry(id: "", name: "Tea", duration: 4 * 60.0, date: Date(), configuration: SelectCountdownIntent()) + SimpleEntry(countdowns: [], date: Date(), configuration: SelectCountdownIntent()) } func getSnapshot(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) { - guard let cp = configuration.countdown, - let identifier = cp.identifier, - let countdown = IntentDataProvider.main.countdown(id: identifier) else { - print("WARNING PLACEHOLDER!") - - let entry = SimpleEntry(id: "", - name: "Not found", - duration: 0.0, - date: Date(), - configuration: configuration) - - completion(entry) + guard let cp = configuration.countdown + else { + completion(placeholder(in: context)) return } - let entry = SimpleEntry(id: identifier, - name: countdown.name, - duration: countdown.duration, + let countdowns: [Countdown] = cp.compactMap { + if let id = $0.identifier { + return IntentDataProvider.main.countdown(id: id) + } else { + return nil + } + } + + let entry = SimpleEntry(countdowns: countdowns, date: Date(), configuration: configuration) completion(entry) @@ -51,26 +48,44 @@ struct Provider: IntentTimelineProvider { } struct SimpleEntry: TimelineEntry { - let id: String - let name: String? - let duration: Double + + let countdowns: [Countdown] + +// let id: String +// let name: String? +// let duration: Double let date: Date let configuration: SelectCountdownIntent } -struct CountdownWidgetView: View { +struct CountdownSimpleWidgetView: View { - let id: String - let name: String? - let duration: Double + let countdown: Countdown var body: some View { - CountdownView(name: name, duration: duration).widgetURL(URL(string: id)) + CountdownView(countdown: countdown) + .widgetURL(countdown.url) } } +struct CountdownMultiWidgetView: View { + + let countdowns: [Countdown] + + var body: some View { + CountdownMultiView(countdowns: countdowns) + } + +} + +struct VoidView : View { + var body: some View { + Text("Nothing here") + } +} + struct LaunchWidgetEntryView : View { @Environment(\.widgetFamily) var family: WidgetFamily @@ -80,7 +95,14 @@ struct LaunchWidgetEntryView : View { @ViewBuilder var body: some View { switch family { - case .systemSmall: CountdownWidgetView(id: entry.id, name: entry.name, duration: entry.duration) + case .systemSmall, .accessoryInline, .accessoryRectangular, .accessoryCircular: + if let countdown = entry.countdowns.first { + CountdownSimpleWidgetView(countdown: countdown) + } else { + VoidView() + } + default: + CountdownMultiView(countdowns: entry.countdowns) // case .systemMedium: GameStatusWithLastTurnResult(gameStatus) // case .systemLarge: GameStatusWithStatistics(gameStatus) @@ -88,7 +110,6 @@ struct LaunchWidgetEntryView : View { // case .accessoryCircular: HealthLevelCircular(selectedCharacter) // case .accessoryRectangular: HealthLevelRectangular(selectedCharacter) // case .accessoryInline: HealthLevelInline(selectedCharacter) - default: CountdownWidgetView(id: entry.id, name: entry.name, duration: entry.duration) } } @@ -112,10 +133,13 @@ struct LaunchWidget: Widget { struct LaunchWidget_Previews: PreviewProvider { static var previews: some View { - LaunchWidgetEntryView(entry: SimpleEntry(id: "", name: "Tea", duration: 3 * 60.0, date: Date(), configuration: SelectCountdownIntent())) + + let fake = Countdown.fake(context: PersistenceController.preview.container.viewContext) + + LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake], date: Date(), configuration: SelectCountdownIntent())) .previewContext(WidgetPreviewContext(family: .systemSmall)) - LaunchWidgetEntryView(entry: SimpleEntry(id: "", name: "Tea", duration: 3 * 60.0, date: Date(), configuration: SelectCountdownIntent())) - .previewContext(WidgetPreviewContext(family: .accessoryRectangular)) + LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake, fake, fake, fake], date: Date(), configuration: SelectCountdownIntent())) + .previewContext(WidgetPreviewContext(family: .systemMedium)) } } diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index 8f7896b..411d4b3 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -139,7 +139,6 @@ 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 */ @@ -187,7 +186,6 @@ C4060DB3297AE73B003FAB80 = { isa = PBXGroup; children = ( - C438C8122982BAA100BF3EF9 /* LaunchWidgetExtension.entitlements */, C4060DBE297AE73B003FAB80 /* LeCountdown */, C4060DD5297AE73D003FAB80 /* LeCountdownTests */, C4060DDF297AE73D003FAB80 /* LeCountdownUITests */, diff --git a/LeCountdown/Model/Model+Extensions.swift b/LeCountdown/Model/Model+Extensions.swift index ac9876d..fdcf783 100644 --- a/LeCountdown/Model/Model+Extensions.swift +++ b/LeCountdown/Model/Model+Extensions.swift @@ -7,6 +7,7 @@ import Foundation import SwiftUI +import CoreData extension Countdown { @@ -14,6 +15,19 @@ extension Countdown { return self.activity?.name } + var url: URL? { + return URL(string: self.stringId) + } + + static func fake(context: NSManagedObjectContext) -> Countdown { + let cd = Countdown(context: context) + cd.duration = 4 * 60.0 + let activity = Activity(context: context) + activity.name = "Tea" + cd.activity = activity + return cd + } + } extension Record {