work around widgets ... not sure if they work
@@ -7,13 +7,14 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1C412080278E23CC00D9153A /* Charts in Frameworks */ = {isa = PBXBuildFile; productRef = 1C41207F278E23CC00D9153A /* Charts */; };
|
|
||||||
1C412082278F2B8800D9153A /* FilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C412081278F2B8800D9153A /* FilterView.swift */; };
|
1C412082278F2B8800D9153A /* FilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C412081278F2B8800D9153A /* FilterView.swift */; };
|
||||||
1C412083278F2B8800D9153A /* FilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C412081278F2B8800D9153A /* FilterView.swift */; };
|
1C412083278F2B8800D9153A /* FilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C412081278F2B8800D9153A /* FilterView.swift */; };
|
||||||
1C683FCA2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
1C683FCA2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
||||||
1C683FCB2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
1C683FCB2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
||||||
1C683FCC2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
1C683FCC2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
|
||||||
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C744F2B278CE15600953A57 /* AppDelegate.swift */; };
|
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C744F2B278CE15600953A57 /* AppDelegate.swift */; };
|
||||||
|
1CA2662A2793843200C0E12C /* Charts in Frameworks */ = {isa = PBXBuildFile; productRef = 1CA266292793843200C0E12C /* Charts */; };
|
||||||
|
1CA2662D2793908700C0E12C /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEF278C7DDF001C4FEA /* Persistence.swift */; };
|
||||||
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469A9278F30A0003E0C6E /* BGTask.swift */; };
|
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469A9278F30A0003E0C6E /* BGTask.swift */; };
|
||||||
1CC469AC27907D48003E0C6E /* CircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469AB27907D48003E0C6E /* CircleView.swift */; };
|
1CC469AC27907D48003E0C6E /* CircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469AB27907D48003E0C6E /* CircleView.swift */; };
|
||||||
1CD90B07278C7DE0001C4FEA /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B06278C7DE0001C4FEA /* Tests_iOS.swift */; };
|
1CD90B07278C7DE0001C4FEA /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B06278C7DE0001C4FEA /* Tests_iOS.swift */; };
|
||||||
@@ -25,7 +26,6 @@
|
|||||||
1CD90B18278C7DE0001C4FEA /* FeelsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AED278C7DDF001C4FEA /* FeelsApp.swift */; };
|
1CD90B18278C7DE0001C4FEA /* FeelsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AED278C7DDF001C4FEA /* FeelsApp.swift */; };
|
||||||
1CD90B19278C7DE0001C4FEA /* FeelsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AED278C7DDF001C4FEA /* FeelsApp.swift */; };
|
1CD90B19278C7DE0001C4FEA /* FeelsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AED278C7DDF001C4FEA /* FeelsApp.swift */; };
|
||||||
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEF278C7DDF001C4FEA /* Persistence.swift */; };
|
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEF278C7DDF001C4FEA /* Persistence.swift */; };
|
||||||
1CD90B1D278C7DE0001C4FEA /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEF278C7DDF001C4FEA /* Persistence.swift */; };
|
|
||||||
1CD90B1E278C7DE0001C4FEA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CD90AF0278C7DE0001C4FEA /* Assets.xcassets */; };
|
1CD90B1E278C7DE0001C4FEA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CD90AF0278C7DE0001C4FEA /* Assets.xcassets */; };
|
||||||
1CD90B1F278C7DE0001C4FEA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CD90AF0278C7DE0001C4FEA /* Assets.xcassets */; };
|
1CD90B1F278C7DE0001C4FEA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CD90AF0278C7DE0001C4FEA /* Assets.xcassets */; };
|
||||||
1CD90B37278C7E38001C4FEA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B32278C7E38001C4FEA /* SettingsView.swift */; };
|
1CD90B37278C7E38001C4FEA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B32278C7E38001C4FEA /* SettingsView.swift */; };
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
1CD90B52278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B4E278C7E7A001C4FEA /* FeelsWidget.intentdefinition */; };
|
1CD90B52278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B4E278C7E7A001C4FEA /* FeelsWidget.intentdefinition */; };
|
||||||
1CD90B53278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B4E278C7E7A001C4FEA /* FeelsWidget.intentdefinition */; };
|
1CD90B53278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B4E278C7E7A001C4FEA /* FeelsWidget.intentdefinition */; };
|
||||||
1CD90B56278C7E7A001C4FEA /* FeelsWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1CD90B45278C7E7A001C4FEA /* FeelsWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
1CD90B56278C7E7A001C4FEA /* FeelsWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1CD90B45278C7E7A001C4FEA /* FeelsWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
1CD90B5B278C7E91001C4FEA /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEF278C7DDF001C4FEA /* Persistence.swift */; };
|
|
||||||
1CD90B5D278C7EAD001C4FEA /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B5C278C7EAD001C4FEA /* Random.swift */; };
|
1CD90B5D278C7EAD001C4FEA /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B5C278C7EAD001C4FEA /* Random.swift */; };
|
||||||
1CD90B5E278C7EAD001C4FEA /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B5C278C7EAD001C4FEA /* Random.swift */; };
|
1CD90B5E278C7EAD001C4FEA /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B5C278C7EAD001C4FEA /* Random.swift */; };
|
||||||
1CD90B5F278C7EAD001C4FEA /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B5C278C7EAD001C4FEA /* Random.swift */; };
|
1CD90B5F278C7EAD001C4FEA /* Random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B5C278C7EAD001C4FEA /* Random.swift */; };
|
||||||
@@ -149,7 +148,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1CD90B6C278C7F78001C4FEA /* CloudKit.framework in Frameworks */,
|
1CD90B6C278C7F78001C4FEA /* CloudKit.framework in Frameworks */,
|
||||||
1C412080278E23CC00D9153A /* Charts in Frameworks */,
|
1CA2662A2793843200C0E12C /* Charts in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -324,7 +323,7 @@
|
|||||||
);
|
);
|
||||||
name = "Feels (iOS)";
|
name = "Feels (iOS)";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
1C41207F278E23CC00D9153A /* Charts */,
|
1CA266292793843200C0E12C /* Charts */,
|
||||||
);
|
);
|
||||||
productName = "Feels (iOS)";
|
productName = "Feels (iOS)";
|
||||||
productReference = 1CD90AF5278C7DE0001C4FEA /* Feels.app */;
|
productReference = 1CD90AF5278C7DE0001C4FEA /* Feels.app */;
|
||||||
@@ -439,7 +438,7 @@
|
|||||||
);
|
);
|
||||||
mainGroup = 1CD90AE5278C7DDF001C4FEA;
|
mainGroup = 1CD90AE5278C7DDF001C4FEA;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
1C41207E278E23CB00D9153A /* XCRemoteSwiftPackageReference "Charts" */,
|
1CA266282793843200C0E12C /* XCRemoteSwiftPackageReference "Charts" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 1CD90AF6278C7DE0001C4FEA /* Products */;
|
productRefGroup = 1CD90AF6278C7DE0001C4FEA /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@@ -535,7 +534,6 @@
|
|||||||
1CD90B38278C7E38001C4FEA /* SettingsView.swift in Sources */,
|
1CD90B38278C7E38001C4FEA /* SettingsView.swift in Sources */,
|
||||||
1CD90B67278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
1CD90B67278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
||||||
1CD90B77278C8119001C4FEA /* LocalNotification.swift in Sources */,
|
1CD90B77278C8119001C4FEA /* LocalNotification.swift in Sources */,
|
||||||
1CD90B1D278C7DE0001C4FEA /* Persistence.swift in Sources */,
|
|
||||||
1CD90B19278C7DE0001C4FEA /* FeelsApp.swift in Sources */,
|
1CD90B19278C7DE0001C4FEA /* FeelsApp.swift in Sources */,
|
||||||
1CD90B5E278C7EAD001C4FEA /* Random.swift in Sources */,
|
1CD90B5E278C7EAD001C4FEA /* Random.swift in Sources */,
|
||||||
);
|
);
|
||||||
@@ -565,8 +563,8 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1CD90B65278C7EBA001C4FEA /* Mood.swift in Sources */,
|
1CD90B65278C7EBA001C4FEA /* Mood.swift in Sources */,
|
||||||
|
1CA2662D2793908700C0E12C /* Persistence.swift in Sources */,
|
||||||
1CD90B5F278C7EAD001C4FEA /* Random.swift in Sources */,
|
1CD90B5F278C7EAD001C4FEA /* Random.swift in Sources */,
|
||||||
1CD90B5B278C7E91001C4FEA /* Persistence.swift in Sources */,
|
|
||||||
1CD90B68278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
1CD90B68278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
||||||
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */,
|
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */,
|
||||||
1C683FCB2792281400745862 /* Stats.swift in Sources */,
|
1C683FCB2792281400745862 /* Stats.swift in Sources */,
|
||||||
@@ -1040,7 +1038,7 @@
|
|||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
1C41207E278E23CB00D9153A /* XCRemoteSwiftPackageReference "Charts" */ = {
|
1CA266282793843200C0E12C /* XCRemoteSwiftPackageReference "Charts" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/danielgindi/Charts";
|
repositoryURL = "https://github.com/danielgindi/Charts";
|
||||||
requirement = {
|
requirement = {
|
||||||
@@ -1051,9 +1049,9 @@
|
|||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
1C41207F278E23CC00D9153A /* Charts */ = {
|
1CA266292793843200C0E12C /* Charts */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 1C41207E278E23CB00D9153A /* XCRemoteSwiftPackageReference "Charts" */;
|
package = 1CA266282793843200C0E12C /* XCRemoteSwiftPackageReference "Charts" */;
|
||||||
productName = Charts;
|
productName = Charts;
|
||||||
};
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
<key>Feels (iOS).xcscheme_^#shared#^_</key>
|
<key>Feels (iOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Feels (macOS).xcscheme_^#shared#^_</key>
|
<key>Feels (macOS).xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>FeelsWidgetExtension.xcscheme_^#shared#^_</key>
|
<key>FeelsWidgetExtension.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
24
FeelsWidget/Assets.xcassets/average.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "meh-regular.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
FeelsWidget/Assets.xcassets/average.imageset/meh-regular.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="meh" class="svg-inline--fa fa-meh fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 610 B |
24
FeelsWidget/Assets.xcassets/bad.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "frown-regular.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
FeelsWidget/Assets.xcassets/bad.imageset/frown-regular.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="frown" class="svg-inline--fa fa-frown fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 748 B |
24
FeelsWidget/Assets.xcassets/good.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "grin-regular.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
FeelsWidget/Assets.xcassets/good.imageset/grin-regular.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="grin" class="svg-inline--fa fa-grin fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm105.6-151.4c-25.9 8.3-64.4 13.1-105.6 13.1s-79.6-4.8-105.6-13.1c-9.9-3.1-19.4 5.4-17.7 15.3 7.9 47.1 71.3 80 123.3 80s115.3-32.9 123.3-80c1.6-9.8-7.7-18.4-17.7-15.3zM168 240c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 690 B |
24
FeelsWidget/Assets.xcassets/great.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "smile-beam-regular.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
FeelsWidget/Assets.xcassets/great.imageset/smile-beam-regular.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="smile-beam" class="svg-inline--fa fa-smile-beam fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm84-143.4c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.6-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.2-8.4-25.3-7.1-33.8 3.1zM136.5 211c7.7-13.7 19.2-21.6 31.5-21.6s23.8 7.9 31.5 21.6l9.5 17c2.1 3.7 6.2 4.7 9.3 3.7 3.6-1.1 6-4.5 5.7-8.3-3.3-42.1-32.2-71.4-56-71.4s-52.7 29.3-56 71.4c-.3 3.7 2.1 7.2 5.7 8.3 3.4 1.1 7.4-.5 9.3-3.7l9.5-17zM328 152c-23.8 0-52.7 29.3-56 71.4-.3 3.7 2.1 7.2 5.7 8.3 3.5 1.1 7.4-.5 9.3-3.7l9.5-17c7.7-13.7 19.2-21.6 31.5-21.6s23.8 7.9 31.5 21.6l9.5 17c2.1 3.7 6.2 4.7 9.3 3.7 3.6-1.1 6-4.5 5.7-8.3-3.3-42.1-32.2-71.4-56-71.4z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
24
FeelsWidget/Assets.xcassets/horrible.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "sad-tear-regular.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
FeelsWidget/Assets.xcassets/horrible.imageset/sad-tear-regular.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="sad-tear" class="svg-inline--fa fa-sad-tear fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm8-152c-13.2 0-24 10.8-24 24s10.8 24 24 24c23.8 0 46.3 10.5 61.6 28.8 8.1 9.8 23.2 11.9 33.8 3.1 10.2-8.5 11.6-23.6 3.1-33.8C330 320.8 294.1 304 256 304zm-88-64c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-165.6 98.8C151 290.1 126 325.4 126 342.9c0 22.7 18.8 41.1 42 41.1s42-18.4 42-41.1c0-17.5-25-52.8-36.4-68.1-2.8-3.7-8.4-3.7-11.2 0z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 817 B |
21
FeelsWidget/Assets.xcassets/missing.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "exclamation-solid.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
1
FeelsWidget/Assets.xcassets/missing.imageset/exclamation-solid.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="exclamation" class="svg-inline--fa fa-exclamation fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M176 432c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zM25.26 25.199l13.6 272C39.499 309.972 50.041 320 62.83 320h66.34c12.789 0 23.331-10.028 23.97-22.801l13.6-272C167.425 11.49 156.496 0 142.77 0H49.23C35.504 0 24.575 11.49 25.26 25.199z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 508 B |
@@ -10,39 +10,97 @@ import SwiftUI
|
|||||||
import Intents
|
import Intents
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
class WatchTimelineView: Identifiable {
|
||||||
|
let id = UUID()
|
||||||
|
let image: Image
|
||||||
|
let date: Date
|
||||||
|
let color: Color
|
||||||
|
|
||||||
|
init(image: Image, date: Date, color: Color) {
|
||||||
|
self.image = image
|
||||||
|
self.date = date
|
||||||
|
self.color = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TimeLineCreator {
|
||||||
|
static func getData() -> [MoodEntry] {
|
||||||
|
let dateAtEnd = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())!
|
||||||
|
var tenDaysAgo = Calendar.current.date(byAdding: .day, value: -10, to: dateAtEnd)!
|
||||||
|
tenDaysAgo = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: tenDaysAgo)!
|
||||||
|
let moodEntry = PersistenceController.shared.getData(startDate: tenDaysAgo, endDate: dateAtEnd, includedDays: [1,2,3,4,5,6,7])
|
||||||
|
return moodEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
static func createTimeLineViews(fromEntries: [MoodEntry]) -> [WatchTimelineView] {
|
||||||
|
var returnViews = [WatchTimelineView]()
|
||||||
|
|
||||||
|
for pastDays in 0...10 {
|
||||||
|
let pastDate = Calendar.current.date(byAdding: .day, value: -pastDays, to: Date())!
|
||||||
|
|
||||||
|
if let item = fromEntries.filter({ entry in
|
||||||
|
let components = Calendar.current.dateComponents([.day, .month, .year], from: pastDate)
|
||||||
|
let day = components.day
|
||||||
|
let month = components.month
|
||||||
|
let year = components.year
|
||||||
|
|
||||||
|
let entryComponents = Calendar.current.dateComponents([.day, .month, .year], from: entry.forDate!)
|
||||||
|
let entryDay = entryComponents.day
|
||||||
|
let entryMonth = entryComponents.month
|
||||||
|
let entryYear = entryComponents.year
|
||||||
|
|
||||||
|
return day == entryDay && month == entryMonth && year == entryYear
|
||||||
|
}).first {
|
||||||
|
let timeLineView = WatchTimelineView(image: item.mood.icon, date: pastDate, color: item.mood.color)
|
||||||
|
returnViews.append(timeLineView)
|
||||||
|
} else {
|
||||||
|
let timeLineView = WatchTimelineView(image: Mood.missing.icon, date: pastDate, color: Mood.missing.color)
|
||||||
|
returnViews.append(timeLineView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnViews
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Provider: IntentTimelineProvider {
|
struct Provider: IntentTimelineProvider {
|
||||||
/*
|
/*
|
||||||
placeholder for widget, no data
|
placeholder for widget, no data
|
||||||
gets redacted auto
|
gets redacted auto
|
||||||
*/
|
*/
|
||||||
func placeholder(in context: Context) -> SimpleEntry {
|
func placeholder(in context: Context) -> SimpleEntry {
|
||||||
let date = Date()
|
var sampleViews = [WatchTimelineView]()
|
||||||
let moodEntry = PersistenceController.shared.moodEntries(forStartDate: date, count: 10)
|
for pastDay in 0...10 {
|
||||||
return SimpleEntry(date: date, configuration: ConfigurationIntent(), mood: moodEntry)
|
let pastDate = Calendar.current.date(byAdding: .day, value: -pastDay, to: Date())!
|
||||||
|
let mood = Mood.allValues.randomElement()!
|
||||||
|
sampleViews.append( WatchTimelineView(image: mood.icon, date: pastDate, color: mood.color) )
|
||||||
|
}
|
||||||
|
return SimpleEntry(date: Date(), configuration: ConfigurationIntent(), timeLineViews: sampleViews)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
|
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
|
||||||
|
var timeLineViews = [WatchTimelineView]()
|
||||||
|
|
||||||
if context.isPreview {
|
if context.isPreview {
|
||||||
|
for pastDay in 0...10 {
|
||||||
|
let pastDate = Calendar.current.date(byAdding: .day, value: -pastDay, to: Date())!
|
||||||
|
let mood = Mood.allValues.randomElement()!
|
||||||
|
timeLineViews.append( WatchTimelineView(image: mood.icon, date: pastDate, color: mood.color) )
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let data = TimeLineCreator.getData()
|
||||||
|
timeLineViews = TimeLineCreator.createTimeLineViews(fromEntries: data)
|
||||||
}
|
}
|
||||||
|
|
||||||
var calendar = Calendar.current
|
let entry = SimpleEntry(date: Date(), configuration: configuration, timeLineViews: timeLineViews)
|
||||||
calendar.timeZone = NSTimeZone.local
|
|
||||||
let todayStart = calendar.startOfDay(for: Date())
|
|
||||||
let userEntries = PersistenceController.shared.moodEntries(forStartDate: todayStart, count: 10)
|
|
||||||
|
|
||||||
let entry = SimpleEntry(date: Date(), configuration: configuration, mood: userEntries)
|
|
||||||
completion(entry)
|
completion(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
||||||
var calendar = Calendar.current
|
let data = TimeLineCreator.getData()
|
||||||
calendar.timeZone = NSTimeZone.local
|
let views = TimeLineCreator.createTimeLineViews(fromEntries: data)
|
||||||
let todayStart = calendar.startOfDay(for: Date())
|
|
||||||
let userEntries = PersistenceController.shared.moodEntries(forStartDate: todayStart, count: 10)
|
|
||||||
|
|
||||||
let entry = SimpleEntry(date: Date(), configuration: configuration, mood: userEntries)
|
let entry = SimpleEntry(date: Date(), configuration: configuration, timeLineViews: views)
|
||||||
let timeline = Timeline(entries: [entry], policy: .after(Random.widgetUpdateTime))
|
let timeline = Timeline(entries: [entry], policy: .after(Random.tomorrowMidnightThirty))
|
||||||
completion(timeline)
|
completion(timeline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,13 +108,13 @@ struct Provider: IntentTimelineProvider {
|
|||||||
struct SimpleEntry: TimelineEntry {
|
struct SimpleEntry: TimelineEntry {
|
||||||
let date: Date
|
let date: Date
|
||||||
let configuration: ConfigurationIntent
|
let configuration: ConfigurationIntent
|
||||||
let mood: [MoodEntry]
|
let timeLineViews: [WatchTimelineView]
|
||||||
let showStats: Bool
|
let showStats: Bool
|
||||||
|
|
||||||
init(date: Date, configuration: ConfigurationIntent, mood: [MoodEntry], showStats: Bool = false) {
|
init(date: Date, configuration: ConfigurationIntent, timeLineViews: [WatchTimelineView], showStats: Bool = false) {
|
||||||
self.date = date
|
self.date = date
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.mood = mood
|
self.timeLineViews = timeLineViews
|
||||||
self.showStats = showStats
|
self.showStats = showStats
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,19 +129,21 @@ struct FeelsWidgetEntryView : View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(UIColor.systemBackground)
|
Color(UIColor.systemBackground)
|
||||||
|
|
||||||
switch family {
|
switch family {
|
||||||
case .systemSmall:
|
case .systemSmall:
|
||||||
SmallWidgetView(entry: entry)
|
SmallWidgetView(entry: entry)
|
||||||
case .systemMedium:
|
case .systemMedium:
|
||||||
MediumWidgetView(entry: entry)
|
MediumWidgetView(entry: entry)
|
||||||
case .systemLarge:
|
case .systemLarge:
|
||||||
LargeWidgetView(entry: entry)
|
MediumWidgetView(entry: entry)
|
||||||
case .systemExtraLarge:
|
case .systemExtraLarge:
|
||||||
LargeWidgetView(entry: entry)
|
MediumWidgetView(entry: entry)
|
||||||
@unknown default:
|
@unknown default:
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
}.onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
|
||||||
|
// make sure you don't call this too often
|
||||||
|
WidgetCenter.shared.reloadAllTimelines()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,14 +152,55 @@ struct SmallWidgetView: View {
|
|||||||
var entry: Provider.Entry
|
var entry: Provider.Entry
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
ZStack {
|
||||||
if let first = entry.mood.first {
|
Color(UIColor.secondarySystemBackground)
|
||||||
EntryCardCollectionView(moodEntries: Array([first]))
|
HStack {
|
||||||
.padding()
|
ForEach([entry.timeLineViews.first!]) { watchView in
|
||||||
} else {
|
EntryCard(timeLineView: watchView)
|
||||||
Text("🤷♂️")
|
}
|
||||||
.font(.system(size: 50))
|
|
||||||
}
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
|
||||||
|
.frame(minHeight: 0, maxHeight: 55)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TimeHeaderView: View {
|
||||||
|
let startDate: Date
|
||||||
|
let endDate: Date
|
||||||
|
|
||||||
|
var formatter: DateFormatter {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.dateStyle = .medium
|
||||||
|
return dateFormatter
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Text(startDate, formatter: formatter)
|
||||||
|
.font(.system(.footnote))
|
||||||
|
Text(" - ")
|
||||||
|
.font(.system(.footnote))
|
||||||
|
Text(endDate, formatter: formatter)
|
||||||
|
.font(.system(.footnote))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TimeBodyView: View {
|
||||||
|
let group: [WatchTimelineView]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
Color(UIColor.secondarySystemBackground)
|
||||||
|
HStack {
|
||||||
|
ForEach(group) { watchView in
|
||||||
|
EntryCard(timeLineView: watchView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,32 +208,20 @@ struct SmallWidgetView: View {
|
|||||||
struct MediumWidgetView: View {
|
struct MediumWidgetView: View {
|
||||||
var entry: Provider.Entry
|
var entry: Provider.Entry
|
||||||
|
|
||||||
var formatter: DateFormatter {
|
var firstGroup: [WatchTimelineView] {
|
||||||
let dateFormatter = DateFormatter()
|
Array(self.entry.timeLineViews.prefix(5))
|
||||||
dateFormatter.dateStyle = .medium
|
|
||||||
return dateFormatter
|
|
||||||
}
|
|
||||||
|
|
||||||
var firstGroup: [MoodEntry] {
|
|
||||||
Array(self.entry.mood.prefix(5))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
HStack {
|
TimeHeaderView(startDate: firstGroup.first!.date, endDate: firstGroup.last!.date)
|
||||||
Text(firstGroup.first?.forDate ?? Date(), formatter: formatter)
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
.font(.system(.footnote))
|
.multilineTextAlignment(.leading)
|
||||||
Text(" - ")
|
|
||||||
.font(.system(.footnote))
|
|
||||||
Text(firstGroup.last?.forDate ?? Date(), formatter: formatter)
|
|
||||||
.font(.system(.footnote))
|
|
||||||
}
|
|
||||||
.frame(minWidth: 0, maxWidth: .infinity)
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
|
|
||||||
EntryCardCollectionView(moodEntries: firstGroup)
|
TimeBodyView(group: firstGroup)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
|
||||||
.frame(minHeight: 0, maxHeight: 55)
|
.frame(minHeight: 0, maxHeight: 55)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
@@ -141,86 +230,47 @@ struct MediumWidgetView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LargeWidgetView: View {
|
//struct LargeWidgetView: View {
|
||||||
var entry: Provider.Entry
|
// var entry: Provider.Entry
|
||||||
|
//
|
||||||
var formatter: DateFormatter {
|
// var formatter: DateFormatter {
|
||||||
let dateFormatter = DateFormatter()
|
// let dateFormatter = DateFormatter()
|
||||||
dateFormatter.dateStyle = .medium
|
// dateFormatter.dateStyle = .medium
|
||||||
return dateFormatter
|
// return dateFormatter
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
var firstGroup: [MoodEntry] {
|
//
|
||||||
Array(self.entry.mood.prefix(5))
|
// var body: some View {
|
||||||
}
|
// VStack {
|
||||||
|
// Spacer()
|
||||||
var lastGroup: [MoodEntry] {
|
//
|
||||||
Array(self.entry.mood.suffix(5))
|
// ForEach([Array(self.entry.timeLineViews.prefix(5)), Array(self.entry.timeLineViews.suffix(5))]) { group in
|
||||||
}
|
//
|
||||||
|
// TimeHeaderView(startDate: group.first!, endDate: group.last!)
|
||||||
|
// .frame(minWidth: 0, maxWidth: .infinity)
|
||||||
var body: some View {
|
// .multilineTextAlignment(.leading)
|
||||||
VStack {
|
//
|
||||||
Spacer()
|
// TimeBodyView(group: group)
|
||||||
|
// .clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
|
||||||
HStack {
|
// .frame(minHeight: 0, maxHeight: 55)
|
||||||
Text(firstGroup.first?.forDate ?? Date(), formatter: formatter)
|
// .padding()
|
||||||
.font(.system(.footnote))
|
//
|
||||||
Text(" - ")
|
// Spacer()
|
||||||
.font(.system(.footnote))
|
// }
|
||||||
Text(firstGroup.last?.forDate ?? Date(), formatter: formatter)
|
// }
|
||||||
.font(.system(.footnote))
|
// }
|
||||||
}
|
//}
|
||||||
.frame(minWidth: 0, maxWidth: .infinity)
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
|
|
||||||
EntryCardCollectionView(moodEntries: firstGroup)
|
|
||||||
.frame(minHeight: 0, maxHeight: 55)
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Text(lastGroup.first?.forDate ?? Date(), formatter: formatter)
|
|
||||||
.font(.system(.footnote))
|
|
||||||
Text(" - ")
|
|
||||||
Text(lastGroup.last?.forDate ?? Date(), formatter: formatter)
|
|
||||||
.font(.system(.footnote))
|
|
||||||
}
|
|
||||||
.frame(minWidth: 0, maxWidth: .infinity)
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
|
|
||||||
EntryCardCollectionView(moodEntries: lastGroup)
|
|
||||||
.frame(minHeight: 0, maxHeight: 55)
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EntryCardCollectionView: View {
|
|
||||||
var moodEntries: [MoodEntry]
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ZStack {
|
|
||||||
Color(UIColor.secondarySystemBackground)
|
|
||||||
HStack {
|
|
||||||
ForEach(moodEntries) { mood in
|
|
||||||
EntryCard(moodEntry: mood)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EntryCard: View {
|
struct EntryCard: View {
|
||||||
var moodEntry: MoodEntry
|
var timeLineView: WatchTimelineView
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
moodEntry.mood.icon.font(.system(size: 50))
|
timeLineView.image
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 50, height: 50, alignment: .center)
|
||||||
|
.foregroundColor(timeLineView.color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,30 +286,37 @@ struct FeelsWidget: Widget {
|
|||||||
}
|
}
|
||||||
.configurationDisplayName("Feels")
|
.configurationDisplayName("Feels")
|
||||||
.description("")
|
.description("")
|
||||||
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
|
.supportedFamilies([.systemSmall, .systemMedium])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FeelsWidget_Previews: PreviewProvider {
|
struct FeelsWidget_Previews: PreviewProvider {
|
||||||
|
static var data: [WatchTimelineView] {
|
||||||
|
var data = PersistenceController.shared.randomEntries(count: 10)
|
||||||
|
data.remove(at: 2)
|
||||||
|
let views = TimeLineCreator.createTimeLineViews(fromEntries: data)
|
||||||
|
return views
|
||||||
|
}
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group {
|
Group {
|
||||||
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
configuration: ConfigurationIntent(),
|
configuration: ConfigurationIntent(),
|
||||||
mood: PersistenceController.shared.randomEntries(count: 1)))
|
timeLineViews: FeelsWidget_Previews.data))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
.environment(\.sizeCategory, .small)
|
.environment(\.sizeCategory, .small)
|
||||||
|
|
||||||
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
configuration: ConfigurationIntent(),
|
configuration: ConfigurationIntent(),
|
||||||
mood: PersistenceController.shared.randomEntries(count: 3)))
|
timeLineViews: FeelsWidget_Previews.data))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemMedium))
|
.previewContext(WidgetPreviewContext(family: .systemMedium))
|
||||||
.environment(\.sizeCategory, .medium)
|
.environment(\.sizeCategory, .medium)
|
||||||
|
//
|
||||||
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
configuration: ConfigurationIntent(),
|
// configuration: ConfigurationIntent(),
|
||||||
mood: PersistenceController.shared.randomEntries(count: 10)))
|
// timeLineViews: FeelsWidget_Previews.data))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemLarge))
|
// .previewContext(WidgetPreviewContext(family: .systemLarge))
|
||||||
.environment(\.sizeCategory, .large)
|
// .environment(\.sizeCategory, .large)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,21 +12,15 @@ import WidgetKit
|
|||||||
|
|
||||||
// AppDelegate.swift
|
// AppDelegate.swift
|
||||||
class AppDelegate: NSObject, UIApplicationDelegate {
|
class AppDelegate: NSObject, UIApplicationDelegate {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||||
// PersistenceController.shared.clearDB()
|
// PersistenceController.shared.clearDB()
|
||||||
NotificationCenter.default.addObserver(self,
|
|
||||||
selector: #selector(fetchChanges),
|
|
||||||
name: .NSPersistentStoreRemoteChange,
|
|
||||||
object: PersistenceController.shared.container.persistentStoreCoordinator)
|
|
||||||
|
|
||||||
application.registerForRemoteNotifications()
|
application.registerForRemoteNotifications()
|
||||||
UNUserNotificationCenter.current().delegate = self
|
UNUserNotificationCenter.current().delegate = self
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func fetchChanges(note: Notification) {
|
|
||||||
WidgetCenter.shared.reloadAllTimelines()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppDelegate: UNUserNotificationCenterDelegate {
|
extension AppDelegate: UNUserNotificationCenterDelegate {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Screen Shot 2022-01-13 at 5.02.34 PM.png",
|
"filename" : "exclamation-solid.svg",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 6.7 KiB |
1
Shared/Assets.xcassets/missing.imageset/exclamation-solid.svg
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="exclamation" class="svg-inline--fa fa-exclamation fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M176 432c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zM25.26 25.199l13.6 272C39.499 309.972 50.041 320 62.83 320h66.34c12.789 0 23.331-10.028 23.97-22.801l13.6-272C167.425 11.49 156.496 0 142.77 0H49.23C35.504 0 24.575 11.49 25.26 25.199z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 508 B |
@@ -6,8 +6,14 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import CoreData
|
import CoreData
|
||||||
|
import WidgetKit
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
struct PersistenceController {
|
class PersistenceController {
|
||||||
|
private var dataUpdateCall: (() -> Void)?
|
||||||
|
private let callDelay = 10
|
||||||
|
|
||||||
static let shared = PersistenceController.persistenceController
|
static let shared = PersistenceController.persistenceController
|
||||||
|
|
||||||
private static var persistenceController: PersistenceController {
|
private static var persistenceController: PersistenceController {
|
||||||
@@ -38,28 +44,6 @@ struct PersistenceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func moodEntries(forStartDate date: Date, count: Int) -> [MoodEntry] {
|
|
||||||
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
|
||||||
|
|
||||||
fetchRequest.fetchLimit = count
|
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: false)]
|
|
||||||
|
|
||||||
// var calendar = Calendar.current
|
|
||||||
// calendar.timeZone = NSTimeZone.local
|
|
||||||
// let dateFrom = calendar.startOfDay(for: Date())
|
|
||||||
// Set predicate as date being today's date
|
|
||||||
// let fromPredicate = NSPredicate(format: "date <= %@", dateFrom as NSDate)
|
|
||||||
// let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate])
|
|
||||||
// fetchRequest.predicate = datePredicate
|
|
||||||
let entries = try! viewContext.fetch(fetchRequest)
|
|
||||||
|
|
||||||
if entries.count >= count {
|
|
||||||
return Array(entries)
|
|
||||||
} else {
|
|
||||||
return entries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public var earliestEntry: MoodEntry? {
|
public var earliestEntry: MoodEntry? {
|
||||||
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)]
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)]
|
||||||
@@ -75,6 +59,14 @@ struct PersistenceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func getData(startDate: Date, endDate: Date, includedDays: [Int]) -> [MoodEntry] {
|
public func getData(startDate: Date, endDate: Date, includedDays: [Int]) -> [MoodEntry] {
|
||||||
|
try! viewContext.setQueryGenerationFrom(.current)
|
||||||
|
viewContext.refreshAllObjects()
|
||||||
|
|
||||||
|
let fakeRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
||||||
|
let fakeData = try! viewContext.fetch(fakeRequest)
|
||||||
|
for item in fakeData {
|
||||||
|
print(item.forDate!)
|
||||||
|
}
|
||||||
var includedDays16 = [Int16]()
|
var includedDays16 = [Int16]()
|
||||||
|
|
||||||
if includedDays.isEmpty {
|
if includedDays.isEmpty {
|
||||||
@@ -84,17 +76,16 @@ struct PersistenceController {
|
|||||||
Int16($0)
|
Int16($0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let predicate = NSPredicate(format: "%K >= %@ && %K <= %@ && weekDay IN %@",
|
let predicate = NSPredicate(format: "forDate >= %@ && forDate <= %@ && weekDay IN %@",
|
||||||
"forDate",
|
|
||||||
startDate as NSDate,
|
startDate as NSDate,
|
||||||
"forDate",
|
|
||||||
endDate as NSDate,
|
endDate as NSDate,
|
||||||
includedDays16)
|
includedDays16)
|
||||||
|
|
||||||
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
||||||
fetchRequest.predicate = predicate
|
fetchRequest.predicate = predicate
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)]
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)]
|
||||||
return try! viewContext.fetch(fetchRequest)
|
let data = try! viewContext.fetch(fetchRequest)
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateTestData() {
|
func populateTestData() {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class Random {
|
class Random {
|
||||||
static var widgetUpdateTime: Date {
|
static var tomorrowMidnightThirty: Date {
|
||||||
let components = DateComponents(hour: 0, minute: 30, second: 0)
|
let components = DateComponents(hour: 0, minute: 30, second: 0)
|
||||||
var updateTime = Date()
|
var updateTime = Date()
|
||||||
if let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date()),
|
if let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date()),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct AddMoodHeaderView: View {
|
|||||||
ForEach(Mood.allValues.reversed()) { mood in
|
ForEach(Mood.allValues.reversed()) { mood in
|
||||||
VStack {
|
VStack {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
addItem(withMoodValue: mood.rawValue)
|
addItem(withMood: mood)
|
||||||
}, label: {
|
}, label: {
|
||||||
mood.icon
|
mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
@@ -47,21 +47,9 @@ struct AddMoodHeaderView: View {
|
|||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addItem(withMoodValue moodValue: Int) {
|
private func addItem(withMood mood: Mood) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
let newItem = MoodEntry(context: viewContext)
|
PersistenceController.shared.add(mood: mood, forDate: Date())
|
||||||
newItem.timestamp = Date()
|
|
||||||
newItem.moodValue = Int16(moodValue)
|
|
||||||
newItem.forDate = Date()
|
|
||||||
|
|
||||||
do {
|
|
||||||
try viewContext.save()
|
|
||||||
} catch {
|
|
||||||
// Replace this implementation with code to handle the error appropriately.
|
|
||||||
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
|
||||||
let nsError = error as NSError
|
|
||||||
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ struct FilterView: View {
|
|||||||
|
|
||||||
for day in 1...numDays {
|
for day in 1...numDays {
|
||||||
if let item = monthEntries.filter({ entry in
|
if let item = monthEntries.filter({ entry in
|
||||||
let components = calendar.dateComponents([.day, .weekday], from: entry.forDate!)
|
let components = calendar.dateComponents([.day], from: entry.forDate!)
|
||||||
let date = components.day
|
let date = components.day
|
||||||
return day == date
|
return day == date
|
||||||
}).first {
|
}).first {
|
||||||
|
|||||||