Enable stopwatch selection in widgets

release
Laurent 3 years ago
parent f5a1b7d15b
commit f6777f4cb4
  1. 2
      LaunchIntents/Info.plist
  2. 38
      LaunchIntents/IntentHandler.swift
  3. 18
      LaunchWidget/LaunchWidget.intentdefinition
  4. 52
      LaunchWidget/LaunchWidget.swift
  5. 46
      LaunchWidget/SingleTimerView.swift
  6. 8
      LeCountdown.xcodeproj/project.pbxproj
  7. 2
      LeCountdown/Info.plist
  8. 10
      LeCountdown/Widget/IntentDataProvider.swift

@ -12,7 +12,7 @@
<array/> <array/>
<key>IntentsSupported</key> <key>IntentsSupported</key>
<array> <array>
<string>SelectCountdownIntent</string> <string>SelectTimerIntent</string>
</array> </array>
</dict> </dict>
<key>NSExtensionPointIdentifier</key> <key>NSExtensionPointIdentifier</key>

@ -7,38 +7,46 @@
import Intents import Intents
class IntentHandler: INExtension, SelectCountdownIntentHandling { class IntentHandler: INExtension, SelectTimerIntentHandling {
func resolveCountdown(for intent: SelectCountdownIntent) async -> [CountdownPropertiesResolutionResult] { func resolveTimer(for intent: SelectTimerIntent) async -> [TimerPropertiesResolutionResult] {
print("***resolveCountdown") print("***resolveCountdown")
if let properties = intent.countdown?.first { if let properties = intent.timer?.first {
return [CountdownPropertiesResolutionResult.success(with: properties)] return [TimerPropertiesResolutionResult.success(with: properties)]
} }
return [CountdownPropertiesResolutionResult.needsValue()] return [TimerPropertiesResolutionResult.needsValue()]
} }
func provideCountdownOptionsCollection(for intent: SelectCountdownIntent) async throws -> INObjectCollection<CountdownProperties> { func provideTimerOptionsCollection(for intent: SelectTimerIntent) async throws -> INObjectCollection<TimerProperties> {
print("*** provideCountdownOptionsCollection") print("*** provideCountdownOptionsCollection")
do { do {
let countdowns = try IntentDataProvider.main.countdowns() let timers = try IntentDataProvider.main.timers()
let properties: [CountdownProperties] = countdowns.map { countdown in let properties: [TimerProperties] = timers.map { timer in
let displayName: String let displayName: String
let formattedDuration = countdown.duration.minuteSecond switch timer {
if let name = countdown.activity?.name, !name.isEmpty { case let countdown as Countdown:
displayName = "\(name) (\(formattedDuration))" let formattedDuration = countdown.duration.minuteSecond
} else { if let name = timer.activity?.name, !name.isEmpty {
displayName = formattedDuration displayName = "\(name) (\(formattedDuration))"
} else {
displayName = formattedDuration
}
break
case let stopwatch as Stopwatch:
displayName = stopwatch.name ?? "no name"
default:
displayName = "no name"
} }
let cp = CountdownProperties(identifier: countdown.objectID.uriRepresentation().absoluteString, display: displayName) let cp = TimerProperties(identifier: timer.objectID.uriRepresentation().absoluteString, display: displayName)
return cp return cp
} }
let collection: INObjectCollection<CountdownProperties> = INObjectCollection(items: properties) let collection: INObjectCollection<TimerProperties> = INObjectCollection(items: properties)
print("*** provide \(properties.count) countdowns") print("*** provide \(properties.count) countdowns")
return collection return collection

@ -28,7 +28,7 @@
<key>INIntentLastParameterTag</key> <key>INIntentLastParameterTag</key>
<integer>3</integer> <integer>3</integer>
<key>INIntentName</key> <key>INIntentName</key>
<string>SelectCountdown</string> <string>SelectTimer</string>
<key>INIntentParameters</key> <key>INIntentParameters</key>
<array> <array>
<dict> <dict>
@ -88,7 +88,7 @@
<key>INIntentParameterCustomDisambiguation</key> <key>INIntentParameterCustomDisambiguation</key>
<true/> <true/>
<key>INIntentParameterDisplayName</key> <key>INIntentParameterDisplayName</key>
<string>Countdown</string> <string>Timer</string>
<key>INIntentParameterDisplayNameID</key> <key>INIntentParameterDisplayNameID</key>
<string>lE8mOk</string> <string>lE8mOk</string>
<key>INIntentParameterDisplayPriority</key> <key>INIntentParameterDisplayPriority</key>
@ -96,9 +96,9 @@
<key>INIntentParameterFixedSizeArray</key> <key>INIntentParameterFixedSizeArray</key>
<integer>1</integer> <integer>1</integer>
<key>INIntentParameterName</key> <key>INIntentParameterName</key>
<string>countdown</string> <string>timer</string>
<key>INIntentParameterObjectType</key> <key>INIntentParameterObjectType</key>
<string>CountdownProperties</string> <string>TimerProperties</string>
<key>INIntentParameterObjectTypeNamespace</key> <key>INIntentParameterObjectTypeNamespace</key>
<string>88xZPY</string> <string>88xZPY</string>
<key>INIntentParameterPromptDialogs</key> <key>INIntentParameterPromptDialogs</key>
@ -119,7 +119,7 @@
<key>INIntentParameterPromptDialogCustom</key> <key>INIntentParameterPromptDialogCustom</key>
<true/> <true/>
<key>INIntentParameterPromptDialogFormatString</key> <key>INIntentParameterPromptDialogFormatString</key>
<string>There are ${count} options matching ‘${countdown}’.</string> <string>There are ${count} options matching ‘${timer}’.</string>
<key>INIntentParameterPromptDialogFormatStringID</key> <key>INIntentParameterPromptDialogFormatStringID</key>
<string>gtJyOP</string> <string>gtJyOP</string>
<key>INIntentParameterPromptDialogType</key> <key>INIntentParameterPromptDialogType</key>
@ -129,7 +129,7 @@
<key>INIntentParameterPromptDialogCustom</key> <key>INIntentParameterPromptDialogCustom</key>
<true/> <true/>
<key>INIntentParameterPromptDialogFormatString</key> <key>INIntentParameterPromptDialogFormatString</key>
<string>Just to confirm, you wanted ‘${countdown}’?</string> <string>Just to confirm, you wanted ‘${timer}’?</string>
<key>INIntentParameterPromptDialogFormatStringID</key> <key>INIntentParameterPromptDialogFormatStringID</key>
<string>nntWsg</string> <string>nntWsg</string>
<key>INIntentParameterPromptDialogType</key> <key>INIntentParameterPromptDialogType</key>
@ -165,7 +165,7 @@
</array> </array>
</dict> </dict>
<key>INIntentTitle</key> <key>INIntentTitle</key>
<string>Select Countdown</string> <string>Select Timer</string>
<key>INIntentTitleID</key> <key>INIntentTitleID</key>
<string>Dm6sPw</string> <string>Dm6sPw</string>
<key>INIntentType</key> <key>INIntentType</key>
@ -178,13 +178,13 @@
<array> <array>
<dict> <dict>
<key>INTypeDisplayName</key> <key>INTypeDisplayName</key>
<string>CountdownProperties</string> <string>TimerProperties</string>
<key>INTypeDisplayNameID</key> <key>INTypeDisplayNameID</key>
<string>ZTfW1g</string> <string>ZTfW1g</string>
<key>INTypeLastPropertyTag</key> <key>INTypeLastPropertyTag</key>
<integer>102</integer> <integer>102</integer>
<key>INTypeName</key> <key>INTypeName</key>
<string>CountdownProperties</string> <string>TimerProperties</string>
<key>INTypeProperties</key> <key>INTypeProperties</key>
<array> <array>
<dict> <dict>

@ -11,33 +11,33 @@ import Intents
struct Provider: IntentTimelineProvider { struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry { func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(countdowns: [], date: Date(), configuration: SelectCountdownIntent()) SimpleEntry(timers: [], date: Date(), configuration: SelectTimerIntent())
} }
func getSnapshot(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) { func getSnapshot(for configuration: SelectTimerIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
guard let cp = configuration.countdown guard let cp = configuration.timer
else { else {
completion(placeholder(in: context)) completion(placeholder(in: context))
return return
} }
let countdowns: [Countdown] = cp.compactMap { let timers: [AbstractTimer] = cp.compactMap {
if let id = $0.identifier { if let id = $0.identifier {
return IntentDataProvider.main.countdown(id: id) return IntentDataProvider.main.timer(id: id)
} else { } else {
return nil return nil
} }
} }
let entry = SimpleEntry(countdowns: countdowns, let entry = SimpleEntry(timers: timers,
date: Date(), date: Date(),
configuration: configuration) configuration: configuration)
completion(entry) completion(entry)
} }
func getTimeline(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { func getTimeline(for configuration: SelectTimerIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
getSnapshot(for: configuration, in: context) { entry in getSnapshot(for: configuration, in: context) { entry in
let timeline = Timeline(entries: [entry], policy: .atEnd) let timeline = Timeline(entries: [entry], policy: .atEnd)
@ -48,28 +48,28 @@ struct Provider: IntentTimelineProvider {
} }
struct SimpleEntry: TimelineEntry { struct SimpleEntry: TimelineEntry {
let countdowns: [Countdown] let timers: [AbstractTimer]
let date: Date let date: Date
let configuration: SelectCountdownIntent let configuration: SelectTimerIntent
} }
struct CountdownSimpleWidgetView: View { struct CountdownSimpleWidgetView: View {
let countdown: Countdown let timer: AbstractTimer
var body: some View { var body: some View {
SingleCountdownView(countdown: countdown) SingleTimerView(timer: timer)
.widgetURL(countdown.url) .widgetURL(timer.url)
} }
} }
struct CountdownMultiWidgetView: View { struct CountdownMultiWidgetView: View {
let countdowns: [Countdown] let timers: [AbstractTimer]
var body: some View { var body: some View {
MultiCountdownView(countdowns: countdowns) MultiCountdownView(timers: timers)
} }
} }
@ -93,23 +93,23 @@ struct LaunchWidgetEntryView : View {
var body: some View { var body: some View {
switch family { switch family {
case .systemSmall, .accessoryInline: case .systemSmall, .accessoryInline:
if let countdown = entry.countdowns.first { if let timer = entry.timers.first {
CountdownSimpleWidgetView(countdown: countdown) CountdownSimpleWidgetView(timer: timer)
.background(Image(countdown.imageName)) .background(Image(timer.imageName))
} else { } else {
VoidView() VoidView()
} }
case .accessoryCircular: case .accessoryCircular:
if let countdown = entry.countdowns.first { if let countdown = entry.timers.first {
LockScreenCountdownView(countdown: countdown) LockScreenCountdownView(timer: countdown)
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black) .background(Color.black)
} else { } else {
VoidView() VoidView()
} }
case .accessoryRectangular: case .accessoryRectangular:
if let countdown = entry.countdowns.first { if let timer = entry.timers.first {
LockScreenCountdownView(countdown: countdown) LockScreenCountdownView(timer: timer)
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black) .background(Color.black)
.cornerRadius(16.0) .cornerRadius(16.0)
@ -117,7 +117,7 @@ struct LaunchWidgetEntryView : View {
VoidView() VoidView()
} }
default: default:
MultiCountdownView(countdowns: entry.countdowns) MultiCountdownView(timers: entry.timers)
} }
} }
@ -128,7 +128,7 @@ struct LaunchWidget: Widget {
var body: some WidgetConfiguration { var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, IntentConfiguration(kind: kind,
intent: SelectCountdownIntent.self, intent: SelectTimerIntent.self,
provider: Provider()) { entry in provider: Provider()) { entry in
LaunchWidgetEntryView(entry: entry) LaunchWidgetEntryView(entry: entry)
} }
@ -143,11 +143,11 @@ struct LaunchWidget_Previews: PreviewProvider {
let fake = Countdown.fake(context: PersistenceController.preview.container.viewContext) let fake = Countdown.fake(context: PersistenceController.preview.container.viewContext)
LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake], date: Date(), configuration: SelectCountdownIntent())) LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall)) .previewContext(WidgetPreviewContext(family: .systemSmall))
LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake, fake, fake, fake], date: Date(), configuration: SelectCountdownIntent())) LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake, fake, fake, fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .systemMedium)) .previewContext(WidgetPreviewContext(family: .systemMedium))
LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake], date: Date(), configuration: SelectCountdownIntent())) LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .accessoryRectangular)) .previewContext(WidgetPreviewContext(family: .accessoryRectangular))
} }

@ -9,18 +9,20 @@ import SwiftUI
import WidgetKit import WidgetKit
import CoreData import CoreData
struct SingleCountdownView: View { struct SingleTimerView: View {
@Environment(\.widgetFamily) var family: WidgetFamily @Environment(\.widgetFamily) var family: WidgetFamily
var countdown: Countdown var timer: AbstractTimer
var body: some View { var body: some View {
VStack { VStack {
HStack { HStack {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Text(countdown.displayName.uppercased()) Text(timer.displayName.uppercased())
Text(countdown.duration.minuteSecond) if let countdown = timer as? Countdown {
Text(countdown.duration.minuteSecond)
}
} }
Spacer() Spacer()
} }
@ -30,7 +32,7 @@ struct SingleCountdownView: View {
.monospaced() .monospaced()
.foregroundColor(Color.white) .foregroundColor(Color.white)
.font(self.font) .font(self.font)
.widgetURL(countdown.url) .widgetURL(timer.url)
} }
private var font: Font { private var font: Font {
@ -51,17 +53,19 @@ struct LockScreenCountdownView: View {
@Environment(\.widgetFamily) var family: WidgetFamily @Environment(\.widgetFamily) var family: WidgetFamily
var countdown: Countdown var timer: AbstractTimer
var body: some View { var body: some View {
VStack { VStack {
Text(countdown.displayName.uppercased()) Text(timer.displayName.uppercased())
Text(countdown.duration.minuteSecond) if let countdown = timer as? Countdown {
Text(countdown.duration.minuteSecond)
}
} }
.monospaced() .monospaced()
.foregroundColor(Color.white) .foregroundColor(Color.white)
.font(self.font) .font(self.font)
.widgetURL(countdown.url) .widgetURL(timer.url)
} }
private var font: Font { private var font: Font {
@ -86,11 +90,11 @@ struct MultiCountdownView: View {
GridItem(spacing: 10.0), GridItem(spacing: 10.0),
] ]
var countdowns: [Countdown] var timers: [AbstractTimer]
var body: some View { var body: some View {
if countdowns.isEmpty { if timers.isEmpty {
VoidView() VoidView()
} else { } else {
@ -99,22 +103,24 @@ struct MultiCountdownView: View {
spacing: 10.0 spacing: 10.0
) { ) {
ForEach(countdowns) { countdown in ForEach(timers) { timer in
Link(destination: countdown.url) { Link(destination: timer.url) {
HStack { HStack {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Spacer() Spacer()
Text(countdown.displayName.uppercased()) Text(timer.displayName.uppercased())
Text(countdown.duration.minuteSecond) if let countdown = timer as? Countdown {
Text(countdown.duration.minuteSecond)
}
Spacer() Spacer()
} }
Spacer() Spacer()
} }
.padding(.horizontal) .padding(.horizontal)
.font(.callout) .font(.callout)
.background(Image(countdown.imageName)) .background(Image(timer.imageName))
.foregroundColor(.white) .foregroundColor(.white)
.monospaced() .monospaced()
.cornerRadius(16.0) .cornerRadius(16.0)
@ -157,10 +163,10 @@ struct MultiCountdownView: View {
struct CountdownView_Previews: PreviewProvider { struct CountdownView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
SingleCountdownView(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemSmall)).background(.black) SingleTimerView(timer: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemSmall)).background(.black)
LockScreenCountdownView(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryRectangular)) LockScreenCountdownView(timer: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryRectangular))
LockScreenCountdownView(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryCircular)) LockScreenCountdownView(timer: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryCircular))
MultiCountdownView(countdowns: self.countdowns(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemMedium)) MultiCountdownView(timers: self.countdowns(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemMedium))
} }
static func countdowns(context: NSManagedObjectContext) -> [Countdown] { static func countdowns(context: NSManagedObjectContext) -> [Countdown] {

@ -32,7 +32,7 @@
C438C7E02981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */; }; C438C7E02981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */; };
C438C7E32981216300BF3EF9 /* LaunchWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C438C7CE2981216200BF3EF9 /* LaunchWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; C438C7E32981216300BF3EF9 /* LaunchWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C438C7CE2981216200BF3EF9 /* LaunchWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C438C7E82981255D00BF3EF9 /* TimeInterval+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4060DF4297AE9A7003FAB80 /* TimeInterval+Extensions.swift */; }; C438C7E82981255D00BF3EF9 /* TimeInterval+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4060DF4297AE9A7003FAB80 /* TimeInterval+Extensions.swift */; };
C438C7EB2981266F00BF3EF9 /* SingleCountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7E92981260D00BF3EF9 /* SingleCountdownView.swift */; }; C438C7EB2981266F00BF3EF9 /* SingleTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7E92981260D00BF3EF9 /* SingleTimerView.swift */; };
C438C7F229812BB200BF3EF9 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C438C7F129812BB200BF3EF9 /* Intents.framework */; }; C438C7F229812BB200BF3EF9 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C438C7F129812BB200BF3EF9 /* Intents.framework */; };
C438C7F529812BB200BF3EF9 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7F429812BB200BF3EF9 /* IntentHandler.swift */; }; C438C7F529812BB200BF3EF9 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7F429812BB200BF3EF9 /* IntentHandler.swift */; };
C438C7F929812BB200BF3EF9 /* LaunchIntents.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C438C7F029812BB200BF3EF9 /* LaunchIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; C438C7F929812BB200BF3EF9 /* LaunchIntents.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C438C7F029812BB200BF3EF9 /* LaunchIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -225,7 +225,7 @@
C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = LaunchWidget.intentdefinition; sourceTree = "<group>"; }; C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = LaunchWidget.intentdefinition; sourceTree = "<group>"; };
C438C7DC2981216300BF3EF9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; C438C7DC2981216300BF3EF9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
C438C7DE2981216300BF3EF9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; C438C7DE2981216300BF3EF9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C438C7E92981260D00BF3EF9 /* SingleCountdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleCountdownView.swift; sourceTree = "<group>"; }; C438C7E92981260D00BF3EF9 /* SingleTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleTimerView.swift; sourceTree = "<group>"; };
C438C7F029812BB200BF3EF9 /* LaunchIntents.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LaunchIntents.appex; sourceTree = BUILT_PRODUCTS_DIR; }; C438C7F029812BB200BF3EF9 /* LaunchIntents.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LaunchIntents.appex; sourceTree = BUILT_PRODUCTS_DIR; };
C438C7F129812BB200BF3EF9 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; C438C7F129812BB200BF3EF9 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; };
C438C7F429812BB200BF3EF9 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = "<group>"; }; C438C7F429812BB200BF3EF9 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = "<group>"; };
@ -425,7 +425,7 @@
C438C7D52981216200BF3EF9 /* LaunchWidgetBundle.swift */, C438C7D52981216200BF3EF9 /* LaunchWidgetBundle.swift */,
C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */, C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */,
C438C7D92981216200BF3EF9 /* LaunchWidget.swift */, C438C7D92981216200BF3EF9 /* LaunchWidget.swift */,
C438C7E92981260D00BF3EF9 /* SingleCountdownView.swift */, C438C7E92981260D00BF3EF9 /* SingleTimerView.swift */,
C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */, C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */,
C438C7DC2981216300BF3EF9 /* Assets.xcassets */, C438C7DC2981216300BF3EF9 /* Assets.xcassets */,
C438C7DE2981216300BF3EF9 /* Info.plist */, C438C7DE2981216300BF3EF9 /* Info.plist */,
@ -882,7 +882,7 @@
C4F8B1AF298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */, C4F8B1AF298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */,
C445FA932987CF280054D761 /* Sound.swift in Sources */, C445FA932987CF280054D761 /* Sound.swift in Sources */,
C498E5A6299152C600E90DE0 /* GreenCheckmarkView.swift in Sources */, C498E5A6299152C600E90DE0 /* GreenCheckmarkView.swift in Sources */,
C438C7EB2981266F00BF3EF9 /* SingleCountdownView.swift in Sources */, C438C7EB2981266F00BF3EF9 /* SingleTimerView.swift in Sources */,
C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */, C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */,
C4F8B18B298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */, C4F8B18B298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */,
C4F8B195298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */, C4F8B195298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */,

@ -8,7 +8,7 @@
</array> </array>
<key>NSUserActivityTypes</key> <key>NSUserActivityTypes</key>
<array> <array>
<string>SelectCountdownIntent</string> <string>SelectTimerIntent</string>
</array> </array>
<key>UIApplicationSceneManifest</key> <key>UIApplicationSceneManifest</key>
<dict> <dict>

@ -12,16 +12,16 @@ class IntentDataProvider {
static let main: IntentDataProvider = IntentDataProvider() static let main: IntentDataProvider = IntentDataProvider()
func countdowns() throws -> [Countdown] { func timers() throws -> [AbstractTimer] {
let context = PersistenceController.shared.container.viewContext let context = PersistenceController.shared.container.viewContext
let request: NSFetchRequest<Countdown> = Countdown.fetchRequest() let request: NSFetchRequest<AbstractTimer> = AbstractTimer.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(keyPath: (\Countdown.order), ascending: true)] request.sortDescriptors = [NSSortDescriptor(keyPath: (\AbstractTimer.order), ascending: true)]
return try context.fetch(request) return try context.fetch(request)
} }
func countdown(id: String) -> Countdown? { func timer(id: String) -> AbstractTimer? {
let context = PersistenceController.shared.container.viewContext let context = PersistenceController.shared.container.viewContext
return context.object(stringId: id) as? Countdown return context.object(stringId: id) as? AbstractTimer
} }
} }

Loading…
Cancel
Save