diff --git a/LaunchIntents/Info.plist b/LaunchIntents/Info.plist
index 34469a7..6e03edf 100644
--- a/LaunchIntents/Info.plist
+++ b/LaunchIntents/Info.plist
@@ -12,7 +12,7 @@
IntentsSupported
- SelectCountdownIntent
+ SelectTimerIntent
NSExtensionPointIdentifier
diff --git a/LaunchIntents/IntentHandler.swift b/LaunchIntents/IntentHandler.swift
index 244740a..9208bad 100644
--- a/LaunchIntents/IntentHandler.swift
+++ b/LaunchIntents/IntentHandler.swift
@@ -7,38 +7,46 @@
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")
- if let properties = intent.countdown?.first {
- return [CountdownPropertiesResolutionResult.success(with: properties)]
+ if let properties = intent.timer?.first {
+ return [TimerPropertiesResolutionResult.success(with: properties)]
}
- return [CountdownPropertiesResolutionResult.needsValue()]
+ return [TimerPropertiesResolutionResult.needsValue()]
}
- func provideCountdownOptionsCollection(for intent: SelectCountdownIntent) async throws -> INObjectCollection {
+ func provideTimerOptionsCollection(for intent: SelectTimerIntent) async throws -> INObjectCollection {
print("*** provideCountdownOptionsCollection")
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 formattedDuration = countdown.duration.minuteSecond
- if let name = countdown.activity?.name, !name.isEmpty {
- displayName = "\(name) (\(formattedDuration))"
- } else {
- displayName = formattedDuration
+ switch timer {
+ case let countdown as Countdown:
+ let formattedDuration = countdown.duration.minuteSecond
+ if let name = timer.activity?.name, !name.isEmpty {
+ 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
}
- let collection: INObjectCollection = INObjectCollection(items: properties)
+ let collection: INObjectCollection = INObjectCollection(items: properties)
print("*** provide \(properties.count) countdowns")
return collection
diff --git a/LaunchWidget/LaunchWidget.intentdefinition b/LaunchWidget/LaunchWidget.intentdefinition
index 8050ce0..36377bc 100644
--- a/LaunchWidget/LaunchWidget.intentdefinition
+++ b/LaunchWidget/LaunchWidget.intentdefinition
@@ -28,7 +28,7 @@
INIntentLastParameterTag
3
INIntentName
- SelectCountdown
+ SelectTimer
INIntentParameters
@@ -88,7 +88,7 @@
INIntentParameterCustomDisambiguation
INIntentParameterDisplayName
- Countdown
+ Timer
INIntentParameterDisplayNameID
lE8mOk
INIntentParameterDisplayPriority
@@ -96,9 +96,9 @@
INIntentParameterFixedSizeArray
1
INIntentParameterName
- countdown
+ timer
INIntentParameterObjectType
- CountdownProperties
+ TimerProperties
INIntentParameterObjectTypeNamespace
88xZPY
INIntentParameterPromptDialogs
@@ -119,7 +119,7 @@
INIntentParameterPromptDialogCustom
INIntentParameterPromptDialogFormatString
- There are ${count} options matching ‘${countdown}’.
+ There are ${count} options matching ‘${timer}’.
INIntentParameterPromptDialogFormatStringID
gtJyOP
INIntentParameterPromptDialogType
@@ -129,7 +129,7 @@
INIntentParameterPromptDialogCustom
INIntentParameterPromptDialogFormatString
- Just to confirm, you wanted ‘${countdown}’?
+ Just to confirm, you wanted ‘${timer}’?
INIntentParameterPromptDialogFormatStringID
nntWsg
INIntentParameterPromptDialogType
@@ -165,7 +165,7 @@
INIntentTitle
- Select Countdown
+ Select Timer
INIntentTitleID
Dm6sPw
INIntentType
@@ -178,13 +178,13 @@
INTypeDisplayName
- CountdownProperties
+ TimerProperties
INTypeDisplayNameID
ZTfW1g
INTypeLastPropertyTag
102
INTypeName
- CountdownProperties
+ TimerProperties
INTypeProperties
diff --git a/LaunchWidget/LaunchWidget.swift b/LaunchWidget/LaunchWidget.swift
index ff34545..d715859 100644
--- a/LaunchWidget/LaunchWidget.swift
+++ b/LaunchWidget/LaunchWidget.swift
@@ -11,33 +11,33 @@ import Intents
struct Provider: IntentTimelineProvider {
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 {
completion(placeholder(in: context))
return
}
- let countdowns: [Countdown] = cp.compactMap {
+ let timers: [AbstractTimer] = cp.compactMap {
if let id = $0.identifier {
- return IntentDataProvider.main.countdown(id: id)
+ return IntentDataProvider.main.timer(id: id)
} else {
return nil
}
}
- let entry = SimpleEntry(countdowns: countdowns,
+ let entry = SimpleEntry(timers: timers,
date: Date(),
configuration: configuration)
completion(entry)
}
- func getTimeline(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (Timeline) -> ()) {
+ func getTimeline(for configuration: SelectTimerIntent, in context: Context, completion: @escaping (Timeline) -> ()) {
getSnapshot(for: configuration, in: context) { entry in
let timeline = Timeline(entries: [entry], policy: .atEnd)
@@ -48,28 +48,28 @@ struct Provider: IntentTimelineProvider {
}
struct SimpleEntry: TimelineEntry {
- let countdowns: [Countdown]
+ let timers: [AbstractTimer]
let date: Date
- let configuration: SelectCountdownIntent
+ let configuration: SelectTimerIntent
}
struct CountdownSimpleWidgetView: View {
- let countdown: Countdown
+ let timer: AbstractTimer
var body: some View {
- SingleCountdownView(countdown: countdown)
- .widgetURL(countdown.url)
+ SingleTimerView(timer: timer)
+ .widgetURL(timer.url)
}
}
struct CountdownMultiWidgetView: View {
- let countdowns: [Countdown]
+ let timers: [AbstractTimer]
var body: some View {
- MultiCountdownView(countdowns: countdowns)
+ MultiCountdownView(timers: timers)
}
}
@@ -93,23 +93,23 @@ struct LaunchWidgetEntryView : View {
var body: some View {
switch family {
case .systemSmall, .accessoryInline:
- if let countdown = entry.countdowns.first {
- CountdownSimpleWidgetView(countdown: countdown)
- .background(Image(countdown.imageName))
+ if let timer = entry.timers.first {
+ CountdownSimpleWidgetView(timer: timer)
+ .background(Image(timer.imageName))
} else {
VoidView()
}
case .accessoryCircular:
- if let countdown = entry.countdowns.first {
- LockScreenCountdownView(countdown: countdown)
+ if let countdown = entry.timers.first {
+ LockScreenCountdownView(timer: countdown)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black)
} else {
VoidView()
}
case .accessoryRectangular:
- if let countdown = entry.countdowns.first {
- LockScreenCountdownView(countdown: countdown)
+ if let timer = entry.timers.first {
+ LockScreenCountdownView(timer: timer)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black)
.cornerRadius(16.0)
@@ -117,7 +117,7 @@ struct LaunchWidgetEntryView : View {
VoidView()
}
default:
- MultiCountdownView(countdowns: entry.countdowns)
+ MultiCountdownView(timers: entry.timers)
}
}
@@ -128,7 +128,7 @@ struct LaunchWidget: Widget {
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind,
- intent: SelectCountdownIntent.self,
+ intent: SelectTimerIntent.self,
provider: Provider()) { entry in
LaunchWidgetEntryView(entry: entry)
}
@@ -143,11 +143,11 @@ struct LaunchWidget_Previews: PreviewProvider {
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))
- 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))
- LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake], date: Date(), configuration: SelectCountdownIntent()))
+ LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
}
diff --git a/LaunchWidget/SingleCountdownView.swift b/LaunchWidget/SingleTimerView.swift
similarity index 68%
rename from LaunchWidget/SingleCountdownView.swift
rename to LaunchWidget/SingleTimerView.swift
index ed6e59b..974515e 100644
--- a/LaunchWidget/SingleCountdownView.swift
+++ b/LaunchWidget/SingleTimerView.swift
@@ -9,18 +9,20 @@ import SwiftUI
import WidgetKit
import CoreData
-struct SingleCountdownView: View {
+struct SingleTimerView: View {
@Environment(\.widgetFamily) var family: WidgetFamily
- var countdown: Countdown
+ var timer: AbstractTimer
var body: some View {
VStack {
HStack {
VStack(alignment: .leading) {
- Text(countdown.displayName.uppercased())
- Text(countdown.duration.minuteSecond)
+ Text(timer.displayName.uppercased())
+ if let countdown = timer as? Countdown {
+ Text(countdown.duration.minuteSecond)
+ }
}
Spacer()
}
@@ -30,7 +32,7 @@ struct SingleCountdownView: View {
.monospaced()
.foregroundColor(Color.white)
.font(self.font)
- .widgetURL(countdown.url)
+ .widgetURL(timer.url)
}
private var font: Font {
@@ -51,17 +53,19 @@ struct LockScreenCountdownView: View {
@Environment(\.widgetFamily) var family: WidgetFamily
- var countdown: Countdown
+ var timer: AbstractTimer
var body: some View {
VStack {
- Text(countdown.displayName.uppercased())
- Text(countdown.duration.minuteSecond)
+ Text(timer.displayName.uppercased())
+ if let countdown = timer as? Countdown {
+ Text(countdown.duration.minuteSecond)
+ }
}
.monospaced()
.foregroundColor(Color.white)
.font(self.font)
- .widgetURL(countdown.url)
+ .widgetURL(timer.url)
}
private var font: Font {
@@ -86,11 +90,11 @@ struct MultiCountdownView: View {
GridItem(spacing: 10.0),
]
- var countdowns: [Countdown]
+ var timers: [AbstractTimer]
var body: some View {
- if countdowns.isEmpty {
+ if timers.isEmpty {
VoidView()
} else {
@@ -99,22 +103,24 @@ struct MultiCountdownView: View {
spacing: 10.0
) {
- ForEach(countdowns) { countdown in
+ ForEach(timers) { timer in
- Link(destination: countdown.url) {
+ Link(destination: timer.url) {
HStack {
VStack(alignment: .leading) {
Spacer()
- Text(countdown.displayName.uppercased())
- Text(countdown.duration.minuteSecond)
+ Text(timer.displayName.uppercased())
+ if let countdown = timer as? Countdown {
+ Text(countdown.duration.minuteSecond)
+ }
Spacer()
}
Spacer()
}
.padding(.horizontal)
.font(.callout)
- .background(Image(countdown.imageName))
+ .background(Image(timer.imageName))
.foregroundColor(.white)
.monospaced()
.cornerRadius(16.0)
@@ -157,10 +163,10 @@ struct MultiCountdownView: View {
struct CountdownView_Previews: PreviewProvider {
static var previews: some View {
- SingleCountdownView(countdown: 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(countdown: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryCircular))
- MultiCountdownView(countdowns: self.countdowns(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemMedium))
+ SingleTimerView(timer: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemSmall)).background(.black)
+ LockScreenCountdownView(timer: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryRectangular))
+ LockScreenCountdownView(timer: Countdown.fake(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .accessoryCircular))
+ MultiCountdownView(timers: self.countdowns(context: PersistenceController.preview.container.viewContext)).previewContext(WidgetPreviewContext(family: .systemMedium))
}
static func countdowns(context: NSManagedObjectContext) -> [Countdown] {
diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj
index c201cdf..940e84f 100644
--- a/LeCountdown.xcodeproj/project.pbxproj
+++ b/LeCountdown.xcodeproj/project.pbxproj
@@ -32,7 +32,7 @@
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, ); }; };
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 */; };
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, ); }; };
@@ -225,7 +225,7 @@
C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = LaunchWidget.intentdefinition; sourceTree = ""; };
C438C7DC2981216300BF3EF9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
C438C7DE2981216300BF3EF9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- C438C7E92981260D00BF3EF9 /* SingleCountdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleCountdownView.swift; sourceTree = ""; };
+ C438C7E92981260D00BF3EF9 /* SingleTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleTimerView.swift; sourceTree = ""; };
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; };
C438C7F429812BB200BF3EF9 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; };
@@ -425,7 +425,7 @@
C438C7D52981216200BF3EF9 /* LaunchWidgetBundle.swift */,
C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */,
C438C7D92981216200BF3EF9 /* LaunchWidget.swift */,
- C438C7E92981260D00BF3EF9 /* SingleCountdownView.swift */,
+ C438C7E92981260D00BF3EF9 /* SingleTimerView.swift */,
C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */,
C438C7DC2981216300BF3EF9 /* Assets.xcassets */,
C438C7DE2981216300BF3EF9 /* Info.plist */,
@@ -882,7 +882,7 @@
C4F8B1AF298AC451005C86A5 /* Countdown+CoreDataProperties.swift in Sources */,
C445FA932987CF280054D761 /* Sound.swift in Sources */,
C498E5A6299152C600E90DE0 /* GreenCheckmarkView.swift in Sources */,
- C438C7EB2981266F00BF3EF9 /* SingleCountdownView.swift in Sources */,
+ C438C7EB2981266F00BF3EF9 /* SingleTimerView.swift in Sources */,
C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */,
C4F8B18B298AC288005C86A5 /* Record+CoreDataClass.swift in Sources */,
C4F8B195298AC288005C86A5 /* Activity+CoreDataClass.swift in Sources */,
diff --git a/LeCountdown/Info.plist b/LeCountdown/Info.plist
index 0327e78..1e9948b 100644
--- a/LeCountdown/Info.plist
+++ b/LeCountdown/Info.plist
@@ -8,7 +8,7 @@
NSUserActivityTypes
- SelectCountdownIntent
+ SelectTimerIntent
UIApplicationSceneManifest
diff --git a/LeCountdown/Widget/IntentDataProvider.swift b/LeCountdown/Widget/IntentDataProvider.swift
index 522a1a9..7b7e7fb 100644
--- a/LeCountdown/Widget/IntentDataProvider.swift
+++ b/LeCountdown/Widget/IntentDataProvider.swift
@@ -12,16 +12,16 @@ class IntentDataProvider {
static let main: IntentDataProvider = IntentDataProvider()
- func countdowns() throws -> [Countdown] {
+ func timers() throws -> [AbstractTimer] {
let context = PersistenceController.shared.container.viewContext
- let request: NSFetchRequest = Countdown.fetchRequest()
- request.sortDescriptors = [NSSortDescriptor(keyPath: (\Countdown.order), ascending: true)]
+ let request: NSFetchRequest = AbstractTimer.fetchRequest()
+ request.sortDescriptors = [NSSortDescriptor(keyPath: (\AbstractTimer.order), ascending: true)]
return try context.fetch(request)
}
- func countdown(id: String) -> Countdown? {
+ func timer(id: String) -> AbstractTimer? {
let context = PersistenceController.shared.container.viewContext
- return context.object(stringId: id) as? Countdown
+ return context.object(stringId: id) as? AbstractTimer
}
}