configure launch widget

release
Laurent 3 years ago
parent 39c49fe031
commit 87ed5a2e0d
  1. 178
      LaunchWidget/LaunchWidget.intentdefinition
  2. 52
      LaunchWidget/LaunchWidget.swift
  3. 10
      LeCountdown.xcodeproj/project.pbxproj
  4. 6
      LeCountdown/ContentView.swift
  5. 29
      LeCountdown/CountdownView.swift
  6. 4
      LeCountdown/Info.plist

@ -9,24 +9,90 @@
<key>INIntentDefinitionNamespace</key>
<string>88xZPY</string>
<key>INIntentDefinitionSystemVersion</key>
<string>20A294</string>
<string>22A400</string>
<key>INIntentDefinitionToolsBuildVersion</key>
<string>12A6144</string>
<string>14C18</string>
<key>INIntentDefinitionToolsVersion</key>
<string>12.0</string>
<string>14.2</string>
<key>INIntents</key>
<array>
<dict>
<key>INIntentCategory</key>
<string>information</string>
<string>start</string>
<key>INIntentDescriptionID</key>
<string>tVvJ9c</string>
<string>dIYBJB</string>
<key>INIntentEligibleForWidgets</key>
<true/>
<key>INIntentIneligibleForSuggestions</key>
<true/>
<key>INIntentLastParameterTag</key>
<integer>2</integer>
<key>INIntentName</key>
<string>Configuration</string>
<string>SelectCountdown</string>
<key>INIntentParameters</key>
<array>
<dict>
<key>INIntentParameterConfigurable</key>
<true/>
<key>INIntentParameterCustomDisambiguation</key>
<true/>
<key>INIntentParameterDisplayName</key>
<string>Countdown</string>
<key>INIntentParameterDisplayNameID</key>
<string>lE8mOk</string>
<key>INIntentParameterDisplayPriority</key>
<integer>1</integer>
<key>INIntentParameterName</key>
<string>countdown</string>
<key>INIntentParameterObjectType</key>
<string>Countdown</string>
<key>INIntentParameterObjectTypeNamespace</key>
<string>88xZPY</string>
<key>INIntentParameterPromptDialogs</key>
<array>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogType</key>
<string>Configuration</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogType</key>
<string>Primary</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>There are ${count} options matching ‘${countdown}’.</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>gtJyOP</string>
<key>INIntentParameterPromptDialogType</key>
<string>DisambiguationIntroduction</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>Just to confirm, you wanted ‘${countdown}’?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>nntWsg</string>
<key>INIntentParameterPromptDialogType</key>
<string>Confirmation</string>
</dict>
</array>
<key>INIntentParameterSupportsDynamicEnumeration</key>
<true/>
<key>INIntentParameterSupportsResolution</key>
<true/>
<key>INIntentParameterTag</key>
<integer>2</integer>
<key>INIntentParameterType</key>
<string>Object</string>
</dict>
</array>
<key>INIntentResponse</key>
<dict>
<key>INIntentResponseCodes</key>
@ -44,16 +110,108 @@
</array>
</dict>
<key>INIntentTitle</key>
<string>Configuration</string>
<string>Select Countdown</string>
<key>INIntentTitleID</key>
<string>gpCwrM</string>
<string>Dm6sPw</string>
<key>INIntentType</key>
<string>Custom</string>
<key>INIntentVerb</key>
<string>View</string>
<string>Start</string>
</dict>
</array>
<key>INTypes</key>
<array/>
<array>
<dict>
<key>INTypeDisplayName</key>
<string>Countdown</string>
<key>INTypeDisplayNameID</key>
<string>ZTfW1g</string>
<key>INTypeLastPropertyTag</key>
<integer>102</integer>
<key>INTypeName</key>
<string>Countdown</string>
<key>INTypeProperties</key>
<array>
<dict>
<key>INTypePropertyDefault</key>
<true/>
<key>INTypePropertyDisplayPriority</key>
<integer>1</integer>
<key>INTypePropertyName</key>
<string>identifier</string>
<key>INTypePropertyTag</key>
<integer>1</integer>
<key>INTypePropertyType</key>
<string>String</string>
</dict>
<dict>
<key>INTypePropertyDefault</key>
<true/>
<key>INTypePropertyDisplayPriority</key>
<integer>2</integer>
<key>INTypePropertyName</key>
<string>displayString</string>
<key>INTypePropertyTag</key>
<integer>2</integer>
<key>INTypePropertyType</key>
<string>String</string>
</dict>
<dict>
<key>INTypePropertyDefault</key>
<true/>
<key>INTypePropertyDisplayPriority</key>
<integer>3</integer>
<key>INTypePropertyName</key>
<string>pronunciationHint</string>
<key>INTypePropertyTag</key>
<integer>3</integer>
<key>INTypePropertyType</key>
<string>String</string>
</dict>
<dict>
<key>INTypePropertyDefault</key>
<true/>
<key>INTypePropertyDisplayPriority</key>
<integer>4</integer>
<key>INTypePropertyName</key>
<string>alternativeSpeakableMatches</string>
<key>INTypePropertySupportsMultipleValues</key>
<true/>
<key>INTypePropertyTag</key>
<integer>4</integer>
<key>INTypePropertyType</key>
<string>SpeakableString</string>
</dict>
<dict>
<key>INTypePropertyDisplayName</key>
<string>Name</string>
<key>INTypePropertyDisplayNameID</key>
<string>1g3sqi</string>
<key>INTypePropertyDisplayPriority</key>
<integer>5</integer>
<key>INTypePropertyName</key>
<string>name</string>
<key>INTypePropertyTag</key>
<integer>100</integer>
<key>INTypePropertyType</key>
<string>String</string>
</dict>
<dict>
<key>INTypePropertyDisplayName</key>
<string>Duration</string>
<key>INTypePropertyDisplayNameID</key>
<string>NjMwkO</string>
<key>INTypePropertyDisplayPriority</key>
<integer>6</integer>
<key>INTypePropertyName</key>
<string>duration</string>
<key>INTypePropertyTag</key>
<integer>102</integer>
<key>INTypePropertyType</key>
<string>Decimal</string>
</dict>
</array>
</dict>
</array>
</dict>
</plist>

@ -11,11 +11,11 @@ import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
SimpleEntry(id: "", name: "Tea", duration: 4 * 60.0, date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
let entry = SimpleEntry(id: "", name: "Tea", duration: 4 * 60.0, date: Date(), configuration: configuration)
completion(entry)
}
@ -26,7 +26,7 @@ struct Provider: IntentTimelineProvider {
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
let entry = SimpleEntry(id: "", name: "Tea", duration: 4 * 60.0, date: entryDate, configuration: configuration)
entries.append(entry)
}
@ -36,33 +36,67 @@ struct Provider: IntentTimelineProvider {
}
struct SimpleEntry: TimelineEntry {
let id: String
let name: String?
let duration: Double
let date: Date
let configuration: ConfigurationIntent
}
struct CountdownWidgetView: View {
let id: String
let name: String?
let duration: Double
var body: some View {
CountdownView(name: name, duration: duration).widgetURL(URL(string: id))
}
}
struct LaunchWidgetEntryView : View {
@Environment(\.widgetFamily) var family: WidgetFamily
var entry: Provider.Entry
@ViewBuilder
var body: some View {
Text(entry.date, style: .time)
switch family {
case .systemSmall: CountdownWidgetView(id: entry.id, name: entry.name, duration: entry.duration)
// case .systemMedium: GameStatusWithLastTurnResult(gameStatus)
// case .systemLarge: GameStatusWithStatistics(gameStatus)
// case .systemExtraLarge: GameStatusWithStatisticsExtraLarge(gameStatus)
// case .accessoryCircular: HealthLevelCircular(selectedCharacter)
// case .accessoryRectangular: HealthLevelRectangular(selectedCharacter)
// case .accessoryInline: HealthLevelInline(selectedCharacter)
default: CountdownWidgetView(id: entry.id, name: entry.name, duration: entry.duration)
}
}
}
struct LaunchWidget: Widget {
let kind: String = "LaunchWidget"
let kind: String = "com.staxriver.launch-widget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
IntentConfiguration(kind: kind,
intent: ConfigurationIntent.self,
provider: Provider()) { entry in
LaunchWidgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
.configurationDisplayName("Launch Widget")
.description("Select and launch your countdowns")
.supportedFamilies([.systemSmall, .accessoryCircular])
}
}
struct LaunchWidget_Previews: PreviewProvider {
static var previews: some View {
LaunchWidgetEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
LaunchWidgetEntryView(entry: SimpleEntry(id: "", name: "Tea", duration: 3 * 60.0, date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}

@ -30,6 +30,9 @@
C438C7DF2981216300BF3EF9 /* 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, ); }; };
C438C7E82981255D00BF3EF9 /* TimeInterval+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4060DF4297AE9A7003FAB80 /* TimeInterval+Extensions.swift */; };
C438C7EA2981260D00BF3EF9 /* CountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7E92981260D00BF3EF9 /* CountdownView.swift */; };
C438C7EB2981266F00BF3EF9 /* CountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7E92981260D00BF3EF9 /* CountdownView.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -98,6 +101,7 @@
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>"; };
C438C7DE2981216300BF3EF9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C438C7E92981260D00BF3EF9 /* CountdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -162,6 +166,7 @@
children = (
C4060DBF297AE73B003FAB80 /* LeCountdownApp.swift */,
C4060DC1297AE73B003FAB80 /* ContentView.swift */,
C438C7E92981260D00BF3EF9 /* CountdownView.swift */,
C4060DF6297AFEF2003FAB80 /* NewCountdownView.swift */,
C438C7C02980228B00BF3EF9 /* CountdownScheduler.swift */,
C4060DC3297AE73D003FAB80 /* Assets.xcassets */,
@ -384,6 +389,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C438C7EA2981260D00BF3EF9 /* CountdownView.swift in Sources */,
C4060DC9297AE73D003FAB80 /* Persistence.swift in Sources */,
C4060DC2297AE73B003FAB80 /* ContentView.swift in Sources */,
C438C7C12980228B00BF3EF9 /* CountdownScheduler.swift in Sources */,
@ -418,8 +424,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C438C7EB2981266F00BF3EF9 /* CountdownView.swift in Sources */,
C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */,
C438C7DF2981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */,
C438C7E82981255D00BF3EF9 /* TimeInterval+Extensions.swift in Sources */,
C438C7D82981216200BF3EF9 /* LaunchWidgetLiveActivity.swift in Sources */,
C438C7DA2981216200BF3EF9 /* LaunchWidget.swift in Sources */,
);
@ -572,6 +580,7 @@
DEVELOPMENT_TEAM = 526E96RFNP;
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;
@ -602,6 +611,7 @@
DEVELOPMENT_TEAM = 526E96RFNP;
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;

@ -43,11 +43,7 @@ struct ContentView: View {
Button {
self._launchCountdown(countdown)
} label: {
VStack {
Text(countdown.name ?? "")
Text(countdown.duration.minuteSecond)
}
.font(.title2)
CountdownView(name: countdown.name, duration: countdown.duration)
.aspectRatio(contentMode: .fill)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.aspectRatio(1, contentMode: .fit)

@ -0,0 +1,29 @@
//
// CountdownView.swift
// LeCountdown
//
// Created by Laurent Morvillier on 25/01/2023.
//
import SwiftUI
struct CountdownView: View {
var name: String?
var duration: Double
var body: some View {
VStack {
Text(name ?? "")
Text(duration.minuteSecond)
}
.font(.title2)
}
}
struct CountdownView_Previews: PreviewProvider {
static var previews: some View {
CountdownView(name: "Tea", duration: 3 * 60.0)
}
}

@ -2,9 +2,9 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIBackgroundModes</key>
<key>NSUserActivityTypes</key>
<array>
<string>remote-notification</string>
<string>SelectCountdownIntent</string>
</array>
</dict>
</plist>

Loading…
Cancel
Save