Adds widget extension and name

release
Laurent 3 years ago
parent b1eab23a03
commit 39c49fe031
  1. 11
      LaunchWidget/Assets.xcassets/AccentColor.colorset/Contents.json
  2. 13
      LaunchWidget/Assets.xcassets/AppIcon.appiconset/Contents.json
  3. 6
      LaunchWidget/Assets.xcassets/Contents.json
  4. 11
      LaunchWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json
  5. 11
      LaunchWidget/Info.plist
  6. 59
      LaunchWidget/LaunchWidget.intentdefinition
  7. 68
      LaunchWidget/LaunchWidget.swift
  8. 17
      LaunchWidget/LaunchWidgetBundle.swift
  9. 77
      LaunchWidget/LaunchWidgetLiveActivity.swift
  10. 186
      LeCountdown.xcodeproj/project.pbxproj
  11. 4
      LeCountdown/ContentView.swift
  12. 4
      LeCountdown/LeCountdown.xcdatamodeld/LeCountdown.xcdatamodel/contents
  13. 14
      LeCountdown/NewCountdownView.swift
  14. 5
      LeCountdown/Persistence.swift

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
</dict>
</plist>

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>INEnums</key>
<array/>
<key>INIntentDefinitionModelVersion</key>
<string>1.2</string>
<key>INIntentDefinitionNamespace</key>
<string>88xZPY</string>
<key>INIntentDefinitionSystemVersion</key>
<string>20A294</string>
<key>INIntentDefinitionToolsBuildVersion</key>
<string>12A6144</string>
<key>INIntentDefinitionToolsVersion</key>
<string>12.0</string>
<key>INIntents</key>
<array>
<dict>
<key>INIntentCategory</key>
<string>information</string>
<key>INIntentDescriptionID</key>
<string>tVvJ9c</string>
<key>INIntentEligibleForWidgets</key>
<true/>
<key>INIntentIneligibleForSuggestions</key>
<true/>
<key>INIntentName</key>
<string>Configuration</string>
<key>INIntentResponse</key>
<dict>
<key>INIntentResponseCodes</key>
<array>
<dict>
<key>INIntentResponseCodeName</key>
<string>success</string>
<key>INIntentResponseCodeSuccess</key>
<true/>
</dict>
<dict>
<key>INIntentResponseCodeName</key>
<string>failure</string>
</dict>
</array>
</dict>
<key>INIntentTitle</key>
<string>Configuration</string>
<key>INIntentTitleID</key>
<string>gpCwrM</string>
<key>INIntentType</key>
<string>Custom</string>
<key>INIntentVerb</key>
<string>View</string>
</dict>
</array>
<key>INTypes</key>
<array/>
</dict>
</plist>

@ -0,0 +1,68 @@
//
// LaunchWidget.swift
// LaunchWidget
//
// Created by Laurent Morvillier on 25/01/2023.
//
import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
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)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
}
struct LaunchWidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
Text(entry.date, style: .time)
}
}
struct LaunchWidget: Widget {
let kind: String = "LaunchWidget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
LaunchWidgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
struct LaunchWidget_Previews: PreviewProvider {
static var previews: some View {
LaunchWidgetEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}

@ -0,0 +1,17 @@
//
// LaunchWidgetBundle.swift
// LaunchWidget
//
// Created by Laurent Morvillier on 25/01/2023.
//
import WidgetKit
import SwiftUI
@main
struct LaunchWidgetBundle: WidgetBundle {
var body: some Widget {
LaunchWidget()
LaunchWidgetLiveActivity()
}
}

@ -0,0 +1,77 @@
//
// LaunchWidgetLiveActivity.swift
// LaunchWidget
//
// Created by Laurent Morvillier on 25/01/2023.
//
import ActivityKit
import WidgetKit
import SwiftUI
struct LaunchWidgetAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
var value: Int
}
// Fixed non-changing properties about your activity go here!
var name: String
}
struct LaunchWidgetLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: LaunchWidgetAttributes.self) { context in
// Lock screen/banner UI goes here
VStack {
Text("Hello")
}
.activityBackgroundTint(Color.cyan)
.activitySystemActionForegroundColor(Color.black)
} dynamicIsland: { context in
DynamicIsland {
// Expanded UI goes here. Compose the expanded UI through
// various regions, like leading/trailing/center/bottom
DynamicIslandExpandedRegion(.leading) {
Text("Leading")
}
DynamicIslandExpandedRegion(.trailing) {
Text("Trailing")
}
DynamicIslandExpandedRegion(.bottom) {
Text("Bottom")
// more content
}
} compactLeading: {
Text("L")
} compactTrailing: {
Text("T")
} minimal: {
Text("Min")
}
.widgetURL(URL(string: "http://www.apple.com"))
.keylineTint(Color.red)
}
}
}
struct LaunchWidgetLiveActivity_Previews: PreviewProvider {
static let attributes = LaunchWidgetAttributes(name: "Me")
static let contentState = LaunchWidgetAttributes.ContentState(value: 3)
static var previews: some View {
attributes
.previewContext(contentState, viewKind: .dynamicIsland(.compact))
.previewDisplayName("Island Compact")
attributes
.previewContext(contentState, viewKind: .dynamicIsland(.expanded))
.previewDisplayName("Island Expanded")
attributes
.previewContext(contentState, viewKind: .dynamicIsland(.minimal))
.previewDisplayName("Minimal")
attributes
.previewContext(contentState, viewKind: .content)
.previewDisplayName("Notification")
}
}

@ -21,6 +21,15 @@
C438C7C12980228B00BF3EF9 /* CountdownScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7C02980228B00BF3EF9 /* CountdownScheduler.swift */; };
C438C7C5298024E900BF3EF9 /* NSManagedContext+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7C4298024E900BF3EF9 /* NSManagedContext+Extensions.swift */; };
C438C7C929803CA000BF3EF9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7C829803CA000BF3EF9 /* AppDelegate.swift */; };
C438C7D12981216200BF3EF9 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C438C7D02981216200BF3EF9 /* WidgetKit.framework */; };
C438C7D32981216200BF3EF9 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C438C7D22981216200BF3EF9 /* SwiftUI.framework */; };
C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7D52981216200BF3EF9 /* LaunchWidgetBundle.swift */; };
C438C7D82981216200BF3EF9 /* LaunchWidgetLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */; };
C438C7DA2981216200BF3EF9 /* LaunchWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = C438C7D92981216200BF3EF9 /* LaunchWidget.swift */; };
C438C7DD2981216300BF3EF9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C438C7DC2981216300BF3EF9 /* Assets.xcassets */; };
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, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -38,8 +47,29 @@
remoteGlobalIDString = C4060DBB297AE73B003FAB80;
remoteInfo = LeCountdown;
};
C438C7E12981216300BF3EF9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C4060DB4297AE73B003FAB80 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C438C7CD2981216200BF3EF9;
remoteInfo = LaunchWidgetExtension;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
C438C7E72981216300BF3EF9 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
C438C7E32981216300BF3EF9 /* LaunchWidgetExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
C4060DBC297AE73B003FAB80 /* LeCountdown.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LeCountdown.app; sourceTree = BUILT_PRODUCTS_DIR; };
C4060DBF297AE73B003FAB80 /* LeCountdownApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeCountdownApp.swift; sourceTree = "<group>"; };
@ -59,6 +89,15 @@
C438C7C02980228B00BF3EF9 /* CountdownScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountdownScheduler.swift; sourceTree = "<group>"; };
C438C7C4298024E900BF3EF9 /* NSManagedContext+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedContext+Extensions.swift"; sourceTree = "<group>"; };
C438C7C829803CA000BF3EF9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C438C7CE2981216200BF3EF9 /* LaunchWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LaunchWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
C438C7D02981216200BF3EF9 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
C438C7D22981216200BF3EF9 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
C438C7D52981216200BF3EF9 /* LaunchWidgetBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchWidgetBundle.swift; sourceTree = "<group>"; };
C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchWidgetLiveActivity.swift; sourceTree = "<group>"; };
C438C7D92981216200BF3EF9 /* LaunchWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchWidget.swift; 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>"; };
C438C7DE2981216300BF3EF9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -83,6 +122,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C438C7CB2981216200BF3EF9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C438C7D32981216200BF3EF9 /* SwiftUI.framework in Frameworks */,
C438C7D12981216200BF3EF9 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -92,6 +140,8 @@
C4060DBE297AE73B003FAB80 /* LeCountdown */,
C4060DD5297AE73D003FAB80 /* LeCountdownTests */,
C4060DDF297AE73D003FAB80 /* LeCountdownUITests */,
C438C7D42981216200BF3EF9 /* LaunchWidget */,
C438C7CF2981216200BF3EF9 /* Frameworks */,
C4060DBD297AE73B003FAB80 /* Products */,
);
sourceTree = "<group>";
@ -102,6 +152,7 @@
C4060DBC297AE73B003FAB80 /* LeCountdown.app */,
C4060DD2297AE73D003FAB80 /* LeCountdownTests.xctest */,
C4060DDC297AE73D003FAB80 /* LeCountdownUITests.xctest */,
C438C7CE2981216200BF3EF9 /* LaunchWidgetExtension.appex */,
);
name = Products;
sourceTree = "<group>";
@ -150,6 +201,28 @@
path = LeCountdownUITests;
sourceTree = "<group>";
};
C438C7CF2981216200BF3EF9 /* Frameworks */ = {
isa = PBXGroup;
children = (
C438C7D02981216200BF3EF9 /* WidgetKit.framework */,
C438C7D22981216200BF3EF9 /* SwiftUI.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
C438C7D42981216200BF3EF9 /* LaunchWidget */ = {
isa = PBXGroup;
children = (
C438C7D52981216200BF3EF9 /* LaunchWidgetBundle.swift */,
C438C7D72981216200BF3EF9 /* LaunchWidgetLiveActivity.swift */,
C438C7D92981216200BF3EF9 /* LaunchWidget.swift */,
C438C7DB2981216200BF3EF9 /* LaunchWidget.intentdefinition */,
C438C7DC2981216300BF3EF9 /* Assets.xcassets */,
C438C7DE2981216300BF3EF9 /* Info.plist */,
);
path = LaunchWidget;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -160,10 +233,12 @@
C4060DB8297AE73B003FAB80 /* Sources */,
C4060DB9297AE73B003FAB80 /* Frameworks */,
C4060DBA297AE73B003FAB80 /* Resources */,
C438C7E72981216300BF3EF9 /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
C438C7E22981216300BF3EF9 /* PBXTargetDependency */,
);
name = LeCountdown;
productName = LeCountdown;
@ -206,6 +281,23 @@
productReference = C4060DDC297AE73D003FAB80 /* LeCountdownUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
C438C7CD2981216200BF3EF9 /* LaunchWidgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = C438C7E42981216300BF3EF9 /* Build configuration list for PBXNativeTarget "LaunchWidgetExtension" */;
buildPhases = (
C438C7CA2981216200BF3EF9 /* Sources */,
C438C7CB2981216200BF3EF9 /* Frameworks */,
C438C7CC2981216200BF3EF9 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = LaunchWidgetExtension;
productName = LaunchWidgetExtension;
productReference = C438C7CE2981216200BF3EF9 /* LaunchWidgetExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -227,6 +319,9 @@
CreatedOnToolsVersion = 14.2;
TestTargetID = C4060DBB297AE73B003FAB80;
};
C438C7CD2981216200BF3EF9 = {
CreatedOnToolsVersion = 14.2;
};
};
};
buildConfigurationList = C4060DB7297AE73B003FAB80 /* Build configuration list for PBXProject "LeCountdown" */;
@ -245,6 +340,7 @@
C4060DBB297AE73B003FAB80 /* LeCountdown */,
C4060DD1297AE73D003FAB80 /* LeCountdownTests */,
C4060DDB297AE73D003FAB80 /* LeCountdownUITests */,
C438C7CD2981216200BF3EF9 /* LaunchWidgetExtension */,
);
};
/* End PBXProject section */
@ -273,6 +369,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C438C7CC2981216200BF3EF9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C438C7DD2981216300BF3EF9 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -289,6 +393,7 @@
C4060DCC297AE73D003FAB80 /* LeCountdown.xcdatamodeld in Sources */,
C438C7C5298024E900BF3EF9 /* NSManagedContext+Extensions.swift in Sources */,
C4060DC0297AE73B003FAB80 /* LeCountdownApp.swift in Sources */,
C438C7E02981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -309,6 +414,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C438C7CA2981216200BF3EF9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C438C7D62981216200BF3EF9 /* LaunchWidgetBundle.swift in Sources */,
C438C7DF2981216300BF3EF9 /* LaunchWidget.intentdefinition in Sources */,
C438C7D82981216200BF3EF9 /* LaunchWidgetLiveActivity.swift in Sources */,
C438C7DA2981216200BF3EF9 /* LaunchWidget.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -322,6 +438,11 @@
target = C4060DBB297AE73B003FAB80 /* LeCountdown */;
targetProxy = C4060DDD297AE73D003FAB80 /* PBXContainerItemProxy */;
};
C438C7E22981216300BF3EF9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C438C7CD2981216200BF3EF9 /* LaunchWidgetExtension */;
targetProxy = C438C7E12981216300BF3EF9 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
@ -442,6 +563,7 @@
C4060DE7297AE73D003FAB80 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
@ -471,6 +593,7 @@
C4060DE8297AE73D003FAB80 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
@ -573,6 +696,60 @@
};
name = Release;
};
C438C7E52981216300BF3EF9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 526E96RFNP;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LaunchWidget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LaunchWidget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown.LaunchWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
C438C7E62981216300BF3EF9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 526E96RFNP;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LaunchWidget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LaunchWidget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown.LaunchWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -612,6 +789,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C438C7E42981216300BF3EF9 /* Build configuration list for PBXNativeTarget "LaunchWidgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C438C7E52981216300BF3EF9 /* Debug */,
C438C7E62981216300BF3EF9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */

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

@ -3,10 +3,8 @@
<entity name="Countdown" representedClassName="Countdown" syncable="YES" codeGenerationType="class">
<attribute name="duration" attributeType="Double" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="image" optional="YES" attributeType="String"/>
<attribute name="name" optional="YES" attributeType="String"/>
<attribute name="order" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sound" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
</entity>
<entity name="TestO" representedClassName="TestO" syncable="YES" codeGenerationType="class">
<attribute name="test" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
</entity>
</model>

@ -32,6 +32,7 @@ struct CountdownEditView : View {
@State var secondsString: String = ""
@State var minutesString: String = ""
@State var nameString: String = ""
@State var deleteConfirmationShown: Bool = false
@ -55,6 +56,11 @@ struct CountdownEditView : View {
.keyboardType(.numberPad)
.focused($textFieldIsFocused)
}
Section(header: Text("Name for tracking the activity")) {
TextField("name", text: $nameString)
.focused($textFieldIsFocused)
}
Section(header: Text("Properties")) {
Text("Image")
Text("Sound")
@ -120,6 +126,11 @@ struct CountdownEditView : View {
if seconds > 0 {
self.secondsString = self._numberFormatter.string(from: NSNumber(value: seconds)) ?? ""
}
if let name = self.countdown.name, !name.isEmpty {
self.nameString = name
}
}
fileprivate let _numberFormatter = NumberFormatter()
@ -145,6 +156,9 @@ struct CountdownEditView : View {
if temporary {
countdown.order = Int16(self.countdowns.count)
}
if !self.nameString.isEmpty {
countdown.name = self.nameString
}
self._saveContext()

@ -15,8 +15,9 @@ struct PersistenceController {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for i in 0..<3 {
let newItem = Countdown(context: viewContext)
newItem.order = Int16(i)
let countdown = Countdown(context: viewContext)
countdown.order = Int16(i)
countdown.name = "Tea"
}
do {
try viewContext.save()

Loading…
Cancel
Save