everything changed
This commit is contained in:
@@ -7,12 +7,27 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1C02589C27B9677A00EB91AC /* CreateIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C02589B27B9677A00EB91AC /* CreateIconView.swift */; };
|
1C02589C27B9677A00EB91AC /* CreateWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C02589B27B9677A00EB91AC /* CreateWidgetView.swift */; };
|
||||||
1C02589E27B9821700EB91AC /* CenterTiledImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C02589D27B9821700EB91AC /* CenterTiledImage.swift */; };
|
1C04488727C1C81D00D22444 /* PersonalityPackable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04488627C1C81D00D22444 /* PersonalityPackable.swift */; };
|
||||||
|
1C04488827C1CD8C00D22444 /* PersonalityPackable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04488627C1C81D00D22444 /* PersonalityPackable.swift */; };
|
||||||
|
1C04488A27C2ABD500D22444 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04488927C2ABD500D22444 /* IconView.swift */; };
|
||||||
|
1C04488B27C2ABDE00D22444 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04488927C2ABD500D22444 /* IconView.swift */; };
|
||||||
|
1C04488D27C2ADDB00D22444 /* IconViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04488C27C2ADDB00D22444 /* IconViewModel.swift */; };
|
||||||
|
1C04488E27C2AE5200D22444 /* IconViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C04488C27C2ADDB00D22444 /* IconViewModel.swift */; };
|
||||||
|
1C04489627C2DB0100D22444 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FAC27ADD0C3002C83A6 /* Theme.swift */; };
|
||||||
|
1C04489727C2DB9B00D22444 /* BGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603127A5C1C800C520BD /* BGView.swift */; };
|
||||||
1C0DAB45279DB0FB003B1F21 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1C0DAB47279DB0FB003B1F21 /* Localizable.strings */; };
|
1C0DAB45279DB0FB003B1F21 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1C0DAB47279DB0FB003B1F21 /* Localizable.strings */; };
|
||||||
1C10E24E27A1AB110047948B /* UserDefaultsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */; };
|
1C10E24E27A1AB110047948B /* UserDefaultsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */; };
|
||||||
1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.swift */; };
|
1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.swift */; };
|
||||||
1C10E25127A1AB320047948B /* OnboardingTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03776279A295600D26164 /* OnboardingTitle.swift */; };
|
1C10E25127A1AB320047948B /* OnboardingTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03776279A295600D26164 /* OnboardingTitle.swift */; };
|
||||||
|
1C2162EB27C14EFA004353D1 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162EA27C14EFA004353D1 /* Date+Extensions.swift */; };
|
||||||
|
1C2162EC27C14FC5004353D1 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162EA27C14EFA004353D1 /* Date+Extensions.swift */; };
|
||||||
|
1C2162EE27C15191004353D1 /* MoodEntryFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162ED27C15191004353D1 /* MoodEntryFunctions.swift */; };
|
||||||
|
1C2162F227C156E6004353D1 /* CustomizeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162F127C156E6004353D1 /* CustomizeView.swift */; };
|
||||||
|
1C2162F427C1602D004353D1 /* MoodImagable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162F327C1602D004353D1 /* MoodImagable.swift */; };
|
||||||
|
1C2162F527C16061004353D1 /* MoodImagable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162F327C1602D004353D1 /* MoodImagable.swift */; };
|
||||||
|
1C2162F727C16D11004353D1 /* MoodTintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162F627C16D11004353D1 /* MoodTintable.swift */; };
|
||||||
|
1C2162F827C16E3C004353D1 /* MoodTintable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2162F627C16D11004353D1 /* MoodTintable.swift */; };
|
||||||
1C2618FA2795E41D00FDC148 /* Charts in Frameworks */ = {isa = PBXBuildFile; productRef = 1C2618F92795E41D00FDC148 /* Charts */; };
|
1C2618FA2795E41D00FDC148 /* Charts in Frameworks */ = {isa = PBXBuildFile; productRef = 1C2618F92795E41D00FDC148 /* Charts */; };
|
||||||
1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */; };
|
1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */; };
|
||||||
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C26190227960CE500FDC148 /* ChartDataBuildable.swift */; };
|
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C26190227960CE500FDC148 /* ChartDataBuildable.swift */; };
|
||||||
@@ -52,7 +67,7 @@
|
|||||||
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 */; };
|
||||||
1C747CC9279F06EB00762CBD /* CloudKitSyncMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 1C747CC8279F06EB00762CBD /* CloudKitSyncMonitor */; };
|
1C747CC9279F06EB00762CBD /* CloudKitSyncMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 1C747CC8279F06EB00762CBD /* CloudKitSyncMonitor */; };
|
||||||
1CA037702799FFA600D26164 /* ContentModeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */; };
|
1CA037702799FFA600D26164 /* HomeViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA0376F2799FFA600D26164 /* HomeViewViewModel.swift */; };
|
||||||
1CA03773279A293D00D26164 /* OnboardingTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03772279A293D00D26164 /* OnboardingTime.swift */; };
|
1CA03773279A293D00D26164 /* OnboardingTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03772279A293D00D26164 /* OnboardingTime.swift */; };
|
||||||
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.swift */; };
|
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.swift */; };
|
||||||
1CA03777279A295600D26164 /* OnboardingTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03776279A295600D26164 /* OnboardingTitle.swift */; };
|
1CA03777279A295600D26164 /* OnboardingTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03776279A295600D26164 /* OnboardingTitle.swift */; };
|
||||||
@@ -104,10 +119,10 @@
|
|||||||
1CD90B6E278C7F8B001C4FEA /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B6B278C7F78001C4FEA /* CloudKit.framework */; };
|
1CD90B6E278C7F8B001C4FEA /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B6B278C7F78001C4FEA /* CloudKit.framework */; };
|
||||||
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEB278C7DDF001C4FEA /* Feels.xcdatamodeld */; };
|
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEB278C7DDF001C4FEA /* Feels.xcdatamodeld */; };
|
||||||
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B75278C8119001C4FEA /* LocalNotification.swift */; };
|
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B75278C8119001C4FEA /* LocalNotification.swift */; };
|
||||||
1CEC966F27B9C29300CC8688 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* IconView.swift */; };
|
1CEC966F27B9C29300CC8688 /* CustomWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */; };
|
||||||
1CEC967127B9C2BB00CC8688 /* CustomIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */; };
|
1CEC967127B9C2BB00CC8688 /* CustomWidgetModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */; };
|
||||||
1CEC967227B9C9FB00CC8688 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* IconView.swift */; };
|
1CEC967227B9C9FB00CC8688 /* CustomWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */; };
|
||||||
1CEC967327B9CA0C00CC8688 /* CustomIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */; };
|
1CEC967327B9CA0C00CC8688 /* CustomWidgetModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -149,10 +164,17 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1C02589B27B9677A00EB91AC /* CreateIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateIconView.swift; sourceTree = "<group>"; };
|
1C02589B27B9677A00EB91AC /* CreateWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CreateWidgetView.swift; path = ../CustomIcon/CreateWidgetView.swift; sourceTree = "<group>"; };
|
||||||
1C02589D27B9821700EB91AC /* CenterTiledImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CenterTiledImage.swift; sourceTree = "<group>"; };
|
1C04488627C1C81D00D22444 /* PersonalityPackable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonalityPackable.swift; sourceTree = "<group>"; };
|
||||||
|
1C04488927C2ABD500D22444 /* IconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconView.swift; sourceTree = "<group>"; };
|
||||||
|
1C04488C27C2ADDB00D22444 /* IconViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconViewModel.swift; sourceTree = "<group>"; };
|
||||||
1C0DAB46279DB0FB003B1F21 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
1C0DAB46279DB0FB003B1F21 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
1C0DAB48279DB116003B1F21 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
|
1C0DAB48279DB116003B1F21 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
1C2162EA27C14EFA004353D1 /* Date+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
|
1C2162ED27C15191004353D1 /* MoodEntryFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoodEntryFunctions.swift; sourceTree = "<group>"; };
|
||||||
|
1C2162F127C156E6004353D1 /* CustomizeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomizeView.swift; sourceTree = "<group>"; };
|
||||||
|
1C2162F327C1602D004353D1 /* MoodImagable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoodImagable.swift; sourceTree = "<group>"; };
|
||||||
|
1C2162F627C16D11004353D1 /* MoodTintable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoodTintable.swift; sourceTree = "<group>"; };
|
||||||
1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewModel.swift; sourceTree = "<group>"; };
|
1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewModel.swift; sourceTree = "<group>"; };
|
||||||
1C26190227960CE500FDC148 /* ChartDataBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartDataBuildable.swift; sourceTree = "<group>"; };
|
1C26190227960CE500FDC148 /* ChartDataBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartDataBuildable.swift; sourceTree = "<group>"; };
|
||||||
1C26190627960DC900FDC148 /* ChartViewItemBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartViewItemBuildable.swift; sourceTree = "<group>"; };
|
1C26190627960DC900FDC148 /* ChartViewItemBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartViewItemBuildable.swift; sourceTree = "<group>"; };
|
||||||
@@ -179,7 +201,7 @@
|
|||||||
1C658D7627C0744D003231EE /* PersistenceUPDATE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceUPDATE.swift; sourceTree = "<group>"; };
|
1C658D7627C0744D003231EE /* PersistenceUPDATE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceUPDATE.swift; sourceTree = "<group>"; };
|
||||||
1C683FC92792281400745862 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
|
1C683FC92792281400745862 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
|
||||||
1C744F2B278CE15600953A57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
1C744F2B278CE15600953A57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentModeViewModel.swift; sourceTree = "<group>"; };
|
1CA0376F2799FFA600D26164 /* HomeViewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewViewModel.swift; sourceTree = "<group>"; };
|
||||||
1CA03772279A293D00D26164 /* OnboardingTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTime.swift; sourceTree = "<group>"; };
|
1CA03772279A293D00D26164 /* OnboardingTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTime.swift; sourceTree = "<group>"; };
|
||||||
1CA03774279A294800D26164 /* OnboardingDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDay.swift; sourceTree = "<group>"; };
|
1CA03774279A294800D26164 /* OnboardingDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDay.swift; sourceTree = "<group>"; };
|
||||||
1CA03776279A295600D26164 /* OnboardingTitle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTitle.swift; sourceTree = "<group>"; };
|
1CA03776279A295600D26164 /* OnboardingTitle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTitle.swift; sourceTree = "<group>"; };
|
||||||
@@ -230,8 +252,8 @@
|
|||||||
1CD90B6F278C8000001C4FEA /* FeelsWidgetExtensionDev.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = FeelsWidgetExtensionDev.entitlements; sourceTree = "<group>"; };
|
1CD90B6F278C8000001C4FEA /* FeelsWidgetExtensionDev.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = FeelsWidgetExtensionDev.entitlements; sourceTree = "<group>"; };
|
||||||
1CD90B70278C8000001C4FEA /* Feels (iOS)Dev.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Feels (iOS)Dev.entitlements"; sourceTree = "<group>"; };
|
1CD90B70278C8000001C4FEA /* Feels (iOS)Dev.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Feels (iOS)Dev.entitlements"; sourceTree = "<group>"; };
|
||||||
1CD90B75278C8119001C4FEA /* LocalNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalNotification.swift; sourceTree = "<group>"; };
|
1CD90B75278C8119001C4FEA /* LocalNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalNotification.swift; sourceTree = "<group>"; };
|
||||||
1CEC966E27B9C29300CC8688 /* IconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconView.swift; sourceTree = "<group>"; };
|
1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomWidgetView.swift; sourceTree = "<group>"; };
|
||||||
1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomIcon.swift; sourceTree = "<group>"; };
|
1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomWidgetModel.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -279,6 +301,68 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
1C04488F27C2CA9C00D22444 /* HomeView */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1CAD603227A5C1C800C520BD /* HomeView.swift */,
|
||||||
|
1CA0376F2799FFA600D26164 /* HomeViewViewModel.swift */,
|
||||||
|
1C361F1827C046E400E832FC /* HomeViewTwo */,
|
||||||
|
);
|
||||||
|
path = HomeView;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1C04489027C2CAAC00D22444 /* CustomIcon */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1C04488927C2ABD500D22444 /* IconView.swift */,
|
||||||
|
1C04488C27C2ADDB00D22444 /* IconViewModel.swift */,
|
||||||
|
);
|
||||||
|
path = CustomIcon;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1C04489127C2CAB100D22444 /* CustomWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */,
|
||||||
|
1C02589B27B9677A00EB91AC /* CreateWidgetView.swift */,
|
||||||
|
1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */,
|
||||||
|
);
|
||||||
|
path = CustomWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1C04489227C2CAB700D22444 /* CustomizeView */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1C2162F127C156E6004353D1 /* CustomizeView.swift */,
|
||||||
|
);
|
||||||
|
path = CustomizeView;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1C04489327C2CABF00D22444 /* SettingsView */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1CAD602C27A5C1C800C520BD /* SettingsView.swift */,
|
||||||
|
);
|
||||||
|
path = SettingsView;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1C04489427C2CAD100D22444 /* FilterView */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */,
|
||||||
|
1CAD602E27A5C1C800C520BD /* FilterView.swift */,
|
||||||
|
);
|
||||||
|
path = FilterView;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
1C04489527C2CB1A00D22444 /* Sharing */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1C358FB027B0AD87002C83A6 /* SharingListView.swift */,
|
||||||
|
);
|
||||||
|
path = Sharing;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
1C26190127960CDA00FDC148 /* Protocols */ = {
|
1C26190127960CDA00FDC148 /* Protocols */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -317,8 +401,8 @@
|
|||||||
1C4FF3C627BEE09E00BE8F34 /* PersistenceADD.swift */,
|
1C4FF3C627BEE09E00BE8F34 /* PersistenceADD.swift */,
|
||||||
1C4FF3C227BEE07200BE8F34 /* PersistenceDELETE.swift */,
|
1C4FF3C227BEE07200BE8F34 /* PersistenceDELETE.swift */,
|
||||||
1C4FF3BF27BEE06900BE8F34 /* PersistenceGET.swift */,
|
1C4FF3BF27BEE06900BE8F34 /* PersistenceGET.swift */,
|
||||||
1C4FF3BD27BEDF9100BE8F34 /* PersistenceHelper.swift */,
|
|
||||||
1C658D7627C0744D003231EE /* PersistenceUPDATE.swift */,
|
1C658D7627C0744D003231EE /* PersistenceUPDATE.swift */,
|
||||||
|
1C4FF3BD27BEDF9100BE8F34 /* PersistenceHelper.swift */,
|
||||||
);
|
);
|
||||||
path = Persisence;
|
path = Persisence;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -350,18 +434,19 @@
|
|||||||
1C358FB927B35252002C83A6 /* ActivityViewController.swift */,
|
1C358FB927B35252002C83A6 /* ActivityViewController.swift */,
|
||||||
1CAD602F27A5C1C800C520BD /* AddMoodHeaderView.swift */,
|
1CAD602F27A5C1C800C520BD /* AddMoodHeaderView.swift */,
|
||||||
1CAD603127A5C1C800C520BD /* BGView.swift */,
|
1CAD603127A5C1C800C520BD /* BGView.swift */,
|
||||||
1C02589B27B9677A00EB91AC /* CreateIconView.swift */,
|
1C04489027C2CAAC00D22444 /* CustomIcon */,
|
||||||
|
1C04489227C2CAB700D22444 /* CustomizeView */,
|
||||||
|
1C04489127C2CAB100D22444 /* CustomWidget */,
|
||||||
|
1CC469AB27907D48003E0C6E /* DayChartView.swift */,
|
||||||
1CB101C427B62A2D00D1C033 /* EmptyView.swift */,
|
1CB101C427B62A2D00D1C033 /* EmptyView.swift */,
|
||||||
1CAD602E27A5C1C800C520BD /* FilterView.swift */,
|
1C04489427C2CAD100D22444 /* FilterView */,
|
||||||
1CAD602D27A5C1C800C520BD /* GraphView.swift */,
|
1CAD602D27A5C1C800C520BD /* GraphView.swift */,
|
||||||
1CAD603027A5C1C800C520BD /* HeaderPercView.swift */,
|
1CAD603027A5C1C800C520BD /* HeaderPercView.swift */,
|
||||||
1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */,
|
1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */,
|
||||||
1CAD603227A5C1C800C520BD /* HomeView.swift */,
|
1C04488F27C2CA9C00D22444 /* HomeView */,
|
||||||
1C361F1827C046E400E832FC /* HomeViewTwo */,
|
|
||||||
1CEC966E27B9C29300CC8688 /* IconView.swift */,
|
|
||||||
1C361F0B27C0356B00E832FC /* MainTabView.swift */,
|
1C361F0B27C0356B00E832FC /* MainTabView.swift */,
|
||||||
1CAD602C27A5C1C800C520BD /* SettingsView.swift */,
|
1C04489327C2CABF00D22444 /* SettingsView */,
|
||||||
1C358FB027B0AD87002C83A6 /* SharingListView.swift */,
|
1C04489527C2CB1A00D22444 /* Sharing */,
|
||||||
1C358FB427B0ADF3002C83A6 /* SharingTemplates */,
|
1C358FB427B0ADF3002C83A6 /* SharingTemplates */,
|
||||||
1CAD602B27A5C1C800C520BD /* SmallRollUpHeaderView.swift */,
|
1CAD602B27A5C1C800C520BD /* SmallRollUpHeaderView.swift */,
|
||||||
1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */,
|
1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */,
|
||||||
@@ -397,6 +482,8 @@
|
|||||||
1CD90B75278C8119001C4FEA /* LocalNotification.swift */,
|
1CD90B75278C8119001C4FEA /* LocalNotification.swift */,
|
||||||
1C4FF3C527BEE07800BE8F34 /* Persisence */,
|
1C4FF3C527BEE07800BE8F34 /* Persisence */,
|
||||||
1CD90B5C278C7EAD001C4FEA /* Random.swift */,
|
1CD90B5C278C7EAD001C4FEA /* Random.swift */,
|
||||||
|
1C2162EA27C14EFA004353D1 /* Date+Extensions.swift */,
|
||||||
|
1C2162ED27C15191004353D1 /* MoodEntryFunctions.swift */,
|
||||||
1C683FC92792281400745862 /* Stats.swift */,
|
1C683FC92792281400745862 /* Stats.swift */,
|
||||||
1C4FF3BA27BEDDF000BE8F34 /* ShowBasedOnVoteLogics.swift */,
|
1C4FF3BA27BEDDF000BE8F34 /* ShowBasedOnVoteLogics.swift */,
|
||||||
1CA03771279A291F00D26164 /* Onboarding */,
|
1CA03771279A291F00D26164 /* Onboarding */,
|
||||||
@@ -471,15 +558,13 @@
|
|||||||
1CD90B60278C7EBA001C4FEA /* Models */ = {
|
1CD90B60278C7EBA001C4FEA /* Models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
1C02589D27B9821700EB91AC /* CenterTiledImage.swift */,
|
|
||||||
1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */,
|
|
||||||
1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */,
|
|
||||||
1CC469AB27907D48003E0C6E /* DayChartView.swift */,
|
|
||||||
1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */,
|
|
||||||
1CD90B61278C7EBA001C4FEA /* Mood.swift */,
|
1CD90B61278C7EBA001C4FEA /* Mood.swift */,
|
||||||
1CD90B62278C7EBA001C4FEA /* MoodEntryExtension.swift */,
|
1CD90B62278C7EBA001C4FEA /* MoodEntryExtension.swift */,
|
||||||
|
1C2162F327C1602D004353D1 /* MoodImagable.swift */,
|
||||||
1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */,
|
1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */,
|
||||||
|
1C2162F627C16D11004353D1 /* MoodTintable.swift */,
|
||||||
1C361F1327C03C8600E832FC /* OnboardingDataDataManager.swift */,
|
1C361F1327C03C8600E832FC /* OnboardingDataDataManager.swift */,
|
||||||
|
1C04488627C1C81D00D22444 /* PersonalityPackable.swift */,
|
||||||
1C358FAC27ADD0C3002C83A6 /* Theme.swift */,
|
1C358FAC27ADD0C3002C83A6 /* Theme.swift */,
|
||||||
1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */,
|
1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */,
|
||||||
);
|
);
|
||||||
@@ -685,7 +770,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1CA037702799FFA600D26164 /* ContentModeViewModel.swift in Sources */,
|
1CA037702799FFA600D26164 /* HomeViewViewModel.swift in Sources */,
|
||||||
1CA03773279A293D00D26164 /* OnboardingTime.swift in Sources */,
|
1CA03773279A293D00D26164 /* OnboardingTime.swift in Sources */,
|
||||||
1CAD603927A5C1C800C520BD /* HeaderPercView.swift in Sources */,
|
1CAD603927A5C1C800C520BD /* HeaderPercView.swift in Sources */,
|
||||||
1CAD603C27A5C1C800C520BD /* HeaderStatsView.swift in Sources */,
|
1CAD603C27A5C1C800C520BD /* HeaderStatsView.swift in Sources */,
|
||||||
@@ -694,11 +779,14 @@
|
|||||||
1C4FF3C327BEE07200BE8F34 /* PersistenceDELETE.swift in Sources */,
|
1C4FF3C327BEE07200BE8F34 /* PersistenceDELETE.swift in Sources */,
|
||||||
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */,
|
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */,
|
||||||
1CAD603727A5C1C800C520BD /* FilterView.swift in Sources */,
|
1CAD603727A5C1C800C520BD /* FilterView.swift in Sources */,
|
||||||
|
1C04488D27C2ADDB00D22444 /* IconViewModel.swift in Sources */,
|
||||||
|
1C2162F227C156E6004353D1 /* CustomizeView.swift in Sources */,
|
||||||
1C683FCA2792281400745862 /* Stats.swift in Sources */,
|
1C683FCA2792281400745862 /* Stats.swift in Sources */,
|
||||||
1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */,
|
1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */,
|
||||||
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */,
|
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */,
|
||||||
1C358FB627B0AE15002C83A6 /* AllMoodsTotalTemplate.swift in Sources */,
|
1C358FB627B0AE15002C83A6 /* AllMoodsTotalTemplate.swift in Sources */,
|
||||||
1CD90B16278C7DE0001C4FEA /* Feels.xcdatamodeld in Sources */,
|
1CD90B16278C7DE0001C4FEA /* Feels.xcdatamodeld in Sources */,
|
||||||
|
1C04488727C1C81D00D22444 /* PersonalityPackable.swift in Sources */,
|
||||||
1C4FF3BE27BEDF9100BE8F34 /* PersistenceHelper.swift in Sources */,
|
1C4FF3BE27BEDF9100BE8F34 /* PersistenceHelper.swift in Sources */,
|
||||||
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */,
|
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */,
|
||||||
1CAD603B27A5C1C800C520BD /* HomeView.swift in Sources */,
|
1CAD603B27A5C1C800C520BD /* HomeView.swift in Sources */,
|
||||||
@@ -707,7 +795,6 @@
|
|||||||
1CAD603A27A5C1C800C520BD /* BGView.swift in Sources */,
|
1CAD603A27A5C1C800C520BD /* BGView.swift in Sources */,
|
||||||
1C26190727960DC900FDC148 /* ChartViewItemBuildable.swift in Sources */,
|
1C26190727960DC900FDC148 /* ChartViewItemBuildable.swift in Sources */,
|
||||||
1CD90B5D278C7EAD001C4FEA /* Random.swift in Sources */,
|
1CD90B5D278C7EAD001C4FEA /* Random.swift in Sources */,
|
||||||
1C02589E27B9821700EB91AC /* CenterTiledImage.swift in Sources */,
|
|
||||||
1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */,
|
1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */,
|
||||||
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */,
|
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */,
|
||||||
1CD90B63278C7EBA001C4FEA /* Mood.swift in Sources */,
|
1CD90B63278C7EBA001C4FEA /* Mood.swift in Sources */,
|
||||||
@@ -720,7 +807,9 @@
|
|||||||
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */,
|
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */,
|
||||||
1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */,
|
1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */,
|
||||||
1CB101C727B81CAC00D1C033 /* MoodMetrics.swift in Sources */,
|
1CB101C727B81CAC00D1C033 /* MoodMetrics.swift in Sources */,
|
||||||
|
1C2162F427C1602D004353D1 /* MoodImagable.swift in Sources */,
|
||||||
1CAD603627A5C1C800C520BD /* GraphView.swift in Sources */,
|
1CAD603627A5C1C800C520BD /* GraphView.swift in Sources */,
|
||||||
|
1C2162F727C16D11004353D1 /* MoodTintable.swift in Sources */,
|
||||||
1C361F1727C046D800E832FC /* MonthDetailView.swift in Sources */,
|
1C361F1727C046D800E832FC /* MonthDetailView.swift in Sources */,
|
||||||
1CD90B66278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
1CD90B66278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
||||||
1C658D7727C0744D003231EE /* PersistenceUPDATE.swift in Sources */,
|
1C658D7727C0744D003231EE /* PersistenceUPDATE.swift in Sources */,
|
||||||
@@ -728,7 +817,7 @@
|
|||||||
1C358FB827B0AEE3002C83A6 /* LongestStreakTemplate.swift in Sources */,
|
1C358FB827B0AEE3002C83A6 /* LongestStreakTemplate.swift in Sources */,
|
||||||
1C358FB127B0AD87002C83A6 /* SharingListView.swift in Sources */,
|
1C358FB127B0AD87002C83A6 /* SharingListView.swift in Sources */,
|
||||||
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */,
|
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */,
|
||||||
1CEC966F27B9C29300CC8688 /* IconView.swift in Sources */,
|
1CEC966F27B9C29300CC8688 /* CustomWidgetView.swift in Sources */,
|
||||||
1CA0377A279A296E00D26164 /* OnboardingMain.swift in Sources */,
|
1CA0377A279A296E00D26164 /* OnboardingMain.swift in Sources */,
|
||||||
1C358FBA27B35252002C83A6 /* ActivityViewController.swift in Sources */,
|
1C358FBA27B35252002C83A6 /* ActivityViewController.swift in Sources */,
|
||||||
1C5F4978279C945E0092F1B4 /* UserDefaultsStore.swift in Sources */,
|
1C5F4978279C945E0092F1B4 /* UserDefaultsStore.swift in Sources */,
|
||||||
@@ -736,12 +825,15 @@
|
|||||||
1C358FC027B4D20C002C83A6 /* MonthTotalTemplate.swift in Sources */,
|
1C358FC027B4D20C002C83A6 /* MonthTotalTemplate.swift in Sources */,
|
||||||
1CA03777279A295600D26164 /* OnboardingTitle.swift in Sources */,
|
1CA03777279A295600D26164 /* OnboardingTitle.swift in Sources */,
|
||||||
1C4FF3C027BEE06900BE8F34 /* PersistenceGET.swift in Sources */,
|
1C4FF3C027BEE06900BE8F34 /* PersistenceGET.swift in Sources */,
|
||||||
|
1C04488A27C2ABD500D22444 /* IconView.swift in Sources */,
|
||||||
1C361F0C27C0356B00E832FC /* MainTabView.swift in Sources */,
|
1C361F0C27C0356B00E832FC /* MainTabView.swift in Sources */,
|
||||||
1CEC967127B9C2BB00CC8688 /* CustomIcon.swift in Sources */,
|
1CEC967127B9C2BB00CC8688 /* CustomWidgetModel.swift in Sources */,
|
||||||
|
1C2162EE27C15191004353D1 /* MoodEntryFunctions.swift in Sources */,
|
||||||
1C361F0A27C0356000E832FC /* HomeViewTwo.swift in Sources */,
|
1C361F0A27C0356000E832FC /* HomeViewTwo.swift in Sources */,
|
||||||
1C361F1427C03C8600E832FC /* OnboardingDataDataManager.swift in Sources */,
|
1C361F1427C03C8600E832FC /* OnboardingDataDataManager.swift in Sources */,
|
||||||
1C358FAD27ADD0C3002C83A6 /* Theme.swift in Sources */,
|
1C358FAD27ADD0C3002C83A6 /* Theme.swift in Sources */,
|
||||||
1C02589C27B9677A00EB91AC /* CreateIconView.swift in Sources */,
|
1C2162EB27C14EFA004353D1 /* Date+Extensions.swift in Sources */,
|
||||||
|
1C02589C27B9677A00EB91AC /* CreateWidgetView.swift in Sources */,
|
||||||
1C358FC227B4D227002C83A6 /* WeekTotalTemplate.swift in Sources */,
|
1C358FC227B4D227002C83A6 /* WeekTotalTemplate.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -781,8 +873,10 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1CD90B65278C7EBA001C4FEA /* Mood.swift in Sources */,
|
1CD90B65278C7EBA001C4FEA /* Mood.swift in Sources */,
|
||||||
|
1C04488B27C2ABDE00D22444 /* IconView.swift in Sources */,
|
||||||
1C361F1127C03C3D00E832FC /* OnboardingTime.swift in Sources */,
|
1C361F1127C03C3D00E832FC /* OnboardingTime.swift in Sources */,
|
||||||
1CEC967227B9C9FB00CC8688 /* IconView.swift in Sources */,
|
1CEC967227B9C9FB00CC8688 /* CustomWidgetView.swift in Sources */,
|
||||||
|
1C2162F827C16E3C004353D1 /* MoodTintable.swift in Sources */,
|
||||||
1C4FF3BC27BEDF6600BE8F34 /* ShowBasedOnVoteLogics.swift in Sources */,
|
1C4FF3BC27BEDF6600BE8F34 /* ShowBasedOnVoteLogics.swift in Sources */,
|
||||||
1C4FF3C927BEE0C300BE8F34 /* PersistenceHelper.swift in Sources */,
|
1C4FF3C927BEE0C300BE8F34 /* PersistenceHelper.swift in Sources */,
|
||||||
1CA2662D2793908700C0E12C /* Persistence.swift in Sources */,
|
1CA2662D2793908700C0E12C /* Persistence.swift in Sources */,
|
||||||
@@ -791,16 +885,22 @@
|
|||||||
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */,
|
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */,
|
||||||
1C658D7827C0744D003231EE /* PersistenceUPDATE.swift in Sources */,
|
1C658D7827C0744D003231EE /* PersistenceUPDATE.swift in Sources */,
|
||||||
1C10E25127A1AB320047948B /* OnboardingTitle.swift in Sources */,
|
1C10E25127A1AB320047948B /* OnboardingTitle.swift in Sources */,
|
||||||
|
1C04488E27C2AE5200D22444 /* IconViewModel.swift in Sources */,
|
||||||
|
1C04489727C2DB9B00D22444 /* BGView.swift in Sources */,
|
||||||
1CB101C827B81CAC00D1C033 /* MoodMetrics.swift in Sources */,
|
1CB101C827B81CAC00D1C033 /* MoodMetrics.swift in Sources */,
|
||||||
1C683FCB2792281400745862 /* Stats.swift in Sources */,
|
1C683FCB2792281400745862 /* Stats.swift in Sources */,
|
||||||
1CEC967327B9CA0C00CC8688 /* CustomIcon.swift in Sources */,
|
1CEC967327B9CA0C00CC8688 /* CustomWidgetModel.swift in Sources */,
|
||||||
1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */,
|
1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */,
|
||||||
|
1C04488827C1CD8C00D22444 /* PersonalityPackable.swift in Sources */,
|
||||||
1C4FF3C427BEE07200BE8F34 /* PersistenceDELETE.swift in Sources */,
|
1C4FF3C427BEE07200BE8F34 /* PersistenceDELETE.swift in Sources */,
|
||||||
1C4FF3C827BEE09E00BE8F34 /* PersistenceADD.swift in Sources */,
|
1C4FF3C827BEE09E00BE8F34 /* PersistenceADD.swift in Sources */,
|
||||||
|
1C2162F527C16061004353D1 /* MoodImagable.swift in Sources */,
|
||||||
|
1C2162EC27C14FC5004353D1 /* Date+Extensions.swift in Sources */,
|
||||||
1C4FF3C127BEE06900BE8F34 /* PersistenceGET.swift in Sources */,
|
1C4FF3C127BEE06900BE8F34 /* PersistenceGET.swift in Sources */,
|
||||||
1C361F0D27C03BDF00E832FC /* OnboardingData.swift in Sources */,
|
1C361F0D27C03BDF00E832FC /* OnboardingData.swift in Sources */,
|
||||||
1CD90B52278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */,
|
1CD90B52278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */,
|
||||||
1CD90B4D278C7E7A001C4FEA /* FeelsWidget.swift in Sources */,
|
1CD90B4D278C7E7A001C4FEA /* FeelsWidget.swift in Sources */,
|
||||||
|
1C04489627C2DB0100D22444 /* Theme.swift in Sources */,
|
||||||
1C361F0F27C03C0E00E832FC /* LocalNotification.swift in Sources */,
|
1C361F0F27C03C0E00E832FC /* LocalNotification.swift in Sources */,
|
||||||
1C10E24E27A1AB110047948B /* UserDefaultsStore.swift in Sources */,
|
1C10E24E27A1AB110047948B /* UserDefaultsStore.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,12 +16,14 @@ class WatchTimelineView: Identifiable {
|
|||||||
let graphic: Image
|
let graphic: Image
|
||||||
let date: Date
|
let date: Date
|
||||||
let color: Color
|
let color: Color
|
||||||
|
let secondaryColor: Color
|
||||||
|
|
||||||
init(image: Image, date: Date, color: Color, graphic: Image) {
|
init(image: Image, graphic: Image, date: Date, color: Color, secondaryColor: Color) {
|
||||||
self.image = image
|
self.image = image
|
||||||
self.date = date
|
self.date = date
|
||||||
self.color = color
|
self.color = color
|
||||||
self.graphic = graphic
|
self.graphic = graphic
|
||||||
|
self.secondaryColor = secondaryColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,17 +41,21 @@ struct TimeLineCreator {
|
|||||||
|
|
||||||
let dayStart = Calendar.current.startOfDay(for: day)
|
let dayStart = Calendar.current.startOfDay(for: day)
|
||||||
let dayEnd = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: dayStart)!
|
let dayEnd = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: dayStart)!
|
||||||
|
let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
|
||||||
|
let moodImages: MoodImagable.Type = UserDefaultsStore.moodMoodImagable()
|
||||||
|
|
||||||
if let todayEntry = PersistenceController.shared.getData(startDate: dayStart, endDate: dayEnd, includedDays: []).first {
|
if let todayEntry = PersistenceController.shared.getData(startDate: dayStart, endDate: dayEnd, includedDays: []).first {
|
||||||
timeLineView.append(WatchTimelineView(image: todayEntry.mood.icon,
|
timeLineView.append(WatchTimelineView(image: moodImages.icon(forMood: todayEntry.mood),
|
||||||
date: dayStart,
|
graphic: moodImages.icon(forMood: todayEntry.mood),
|
||||||
color: todayEntry.mood.color,
|
date: dayStart,
|
||||||
graphic: todayEntry.mood.graphic))
|
color: moodTint.color(forMood: todayEntry.mood),
|
||||||
|
secondaryColor: moodTint.secondary(forMood: todayEntry.mood)))
|
||||||
} else {
|
} else {
|
||||||
timeLineView.append(WatchTimelineView(image: Mood.missing.icon,
|
timeLineView.append(WatchTimelineView(image: moodImages.icon(forMood: .missing),
|
||||||
date: dayStart,
|
graphic: moodImages.icon(forMood: .missing),
|
||||||
color: Mood.missing.color,
|
date: Date(),
|
||||||
graphic: Mood.missing.graphic))
|
color: moodTint.color(forMood: .missing),
|
||||||
|
secondaryColor: moodTint.secondary(forMood: .missing)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timeLineView = timeLineView.sorted(by: { $0.date > $1.date })
|
timeLineView = timeLineView.sorted(by: { $0.date > $1.date })
|
||||||
@@ -72,7 +78,7 @@ struct Provider: IntentTimelineProvider {
|
|||||||
|
|
||||||
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
|
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
|
||||||
let entry = SimpleEntry(date: Date(),
|
let entry = SimpleEntry(date: Date(),
|
||||||
configuration: ConfigurationIntent(),
|
configuration: ConfigurationIntent(),
|
||||||
timeLineViews: Array(TimeLineCreator.createViews(daysBack: 11).prefix(10)))
|
timeLineViews: Array(TimeLineCreator.createViews(daysBack: 11).prefix(10)))
|
||||||
completion(entry)
|
completion(entry)
|
||||||
}
|
}
|
||||||
@@ -83,8 +89,8 @@ struct Provider: IntentTimelineProvider {
|
|||||||
timeLineViews: nil)
|
timeLineViews: nil)
|
||||||
|
|
||||||
let midNightEntry = SimpleEntry(date: Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())!,
|
let midNightEntry = SimpleEntry(date: Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())!,
|
||||||
configuration: ConfigurationIntent(),
|
configuration: ConfigurationIntent(),
|
||||||
timeLineViews: nil)
|
timeLineViews: nil)
|
||||||
|
|
||||||
let date = Calendar.current.date(byAdding: .second, value: 10, to: Date())!
|
let date = Calendar.current.date(byAdding: .second, value: 10, to: Date())!
|
||||||
let timeline = Timeline(entries: [entry, midNightEntry], policy: .after(date))
|
let timeline = Timeline(entries: [entry, midNightEntry], policy: .after(date))
|
||||||
@@ -164,7 +170,7 @@ struct SmallWidgetView: View {
|
|||||||
struct MediumWidgetView: View {
|
struct MediumWidgetView: View {
|
||||||
var entry: Provider.Entry
|
var entry: Provider.Entry
|
||||||
var timeLineView = [WatchTimelineView]()
|
var timeLineView = [WatchTimelineView]()
|
||||||
|
|
||||||
init(entry: Provider.Entry) {
|
init(entry: Provider.Entry) {
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
timeLineView = Array(TimeLineCreator.createViews(daysBack: 6).prefix(5))
|
timeLineView = Array(TimeLineCreator.createViews(daysBack: 6).prefix(5))
|
||||||
@@ -191,7 +197,7 @@ struct MediumWidgetView: View {
|
|||||||
struct LargeWidgetView: View {
|
struct LargeWidgetView: View {
|
||||||
var entry: Provider.Entry
|
var entry: Provider.Entry
|
||||||
var timeLineView = [WatchTimelineView]()
|
var timeLineView = [WatchTimelineView]()
|
||||||
|
|
||||||
init(entry: Provider.Entry) {
|
init(entry: Provider.Entry) {
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
timeLineView = Array(TimeLineCreator.createViews(daysBack: 11).prefix(10))
|
timeLineView = Array(TimeLineCreator.createViews(daysBack: 11).prefix(10))
|
||||||
@@ -241,26 +247,31 @@ struct FeelsGraphicWidgetEntryView : View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
SmallGraphicWidgetView(entry: entry)
|
SmallGraphicWidgetView(entry: entry)
|
||||||
.onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
|
.onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
|
||||||
// make sure you don't call this too often
|
// make sure you don't call this too often
|
||||||
WidgetCenter.shared.reloadAllTimelines()
|
WidgetCenter.shared.reloadAllTimelines()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SmallGraphicWidgetView: View {
|
struct SmallGraphicWidgetView: View {
|
||||||
var entry: Provider.Entry
|
var entry: Provider.Entry
|
||||||
var timeLineView = [WatchTimelineView]()
|
var timeLineView: [WatchTimelineView]
|
||||||
|
|
||||||
init(entry: Provider.Entry) {
|
init(entry: Provider.Entry) {
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
timeLineView = [TimeLineCreator.createViews(daysBack: 2).first!]
|
timeLineView = TimeLineCreator.createViews(daysBack: 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geo in
|
if let first = timeLineView.first {
|
||||||
timeLineView.first!.graphic
|
IconView(iconViewModel: IconViewModel(backgroundImage: first.graphic,
|
||||||
.resizable()
|
bgColor: first.color,
|
||||||
.scaledToFit()
|
bgOverlayColor: first.secondaryColor,
|
||||||
|
centerImage: first.graphic),
|
||||||
|
isPreview: true)
|
||||||
|
} else {
|
||||||
|
IconView(iconViewModel: IconViewModel.great,
|
||||||
|
isPreview: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,23 +418,49 @@ struct FeelsGraphicWidget: Widget {
|
|||||||
struct FeelsWidget_Previews: PreviewProvider {
|
struct FeelsWidget_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group {
|
Group {
|
||||||
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
FeelsGraphicWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
// configuration: ConfigurationIntent(),
|
configuration: ConfigurationIntent(),
|
||||||
// timeLineViews: FeelsWidget_Previews.data))
|
timeLineViews: [WatchTimelineView(image: HandEmojiMoodImages.icon(forMood: .great),
|
||||||
// .previewContext(WidgetPreviewContext(family: .systemSmall))
|
graphic: HandEmojiMoodImages.icon(forMood: .great),
|
||||||
// .environment(\.sizeCategory, .small)
|
date: Date(),
|
||||||
//
|
color: MoodTints.Neon.color(forMood: .great),
|
||||||
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
|
||||||
// configuration: ConfigurationIntent(),
|
secondaryColor: .white),
|
||||||
// timeLineViews: FeelsWidget_Previews.data))
|
WatchTimelineView(image: HandEmojiMoodImages.icon(forMood: .great),
|
||||||
// .previewContext(WidgetPreviewContext(family: .systemMedium))
|
graphic: HandEmojiMoodImages.icon(forMood: .great),
|
||||||
// .environment(\.sizeCategory, .medium)
|
date: Date(),
|
||||||
//
|
color: MoodTints.Neon.color(forMood: .great),
|
||||||
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
|
||||||
// configuration: ConfigurationIntent(),
|
secondaryColor: .white)]))
|
||||||
// timeLineViews: FeelsWidget_Previews.data))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
// .previewContext(WidgetPreviewContext(family: .systemLarge))
|
|
||||||
// .environment(\.sizeCategory, .large)
|
FeelsGraphicWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
|
configuration: ConfigurationIntent(),
|
||||||
|
timeLineViews: [WatchTimelineView(image: HandEmojiMoodImages.icon(forMood: .horrible),
|
||||||
|
graphic: HandEmojiMoodImages.icon(forMood: .horrible),
|
||||||
|
date: Date(),
|
||||||
|
color: MoodTints.Neon.color(forMood: .horrible),
|
||||||
|
|
||||||
|
secondaryColor: .white),
|
||||||
|
WatchTimelineView(image: HandEmojiMoodImages.icon(forMood: .horrible),
|
||||||
|
graphic: HandEmojiMoodImages.icon(forMood: .horrible),
|
||||||
|
date: Date(),
|
||||||
|
color: MoodTints.Neon.color(forMood: .horrible),
|
||||||
|
|
||||||
|
secondaryColor: .white)]))
|
||||||
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
|
|
||||||
|
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
|
// configuration: ConfigurationIntent(),
|
||||||
|
// timeLineViews: FeelsWidget_Previews.data))
|
||||||
|
// .previewContext(WidgetPreviewContext(family: .systemMedium))
|
||||||
|
// .environment(\.sizeCategory, .medium)
|
||||||
|
//
|
||||||
|
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
|
||||||
|
// configuration: ConfigurationIntent(),
|
||||||
|
// timeLineViews: FeelsWidget_Previews.data))
|
||||||
|
// .previewContext(WidgetPreviewContext(family: .systemLarge))
|
||||||
|
// .environment(\.sizeCategory, .large)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,20 @@ class AppDelegate: NSObject, UIApplicationDelegate {
|
|||||||
// PersistenceController.shared.clearDB()
|
// PersistenceController.shared.clearDB()
|
||||||
PersistenceController.shared.fillInMissingDates()
|
PersistenceController.shared.fillInMissingDates()
|
||||||
UNUserNotificationCenter.current().delegate = self
|
UNUserNotificationCenter.current().delegate = self
|
||||||
|
|
||||||
|
let theme = UserDefaultsStore.theme()
|
||||||
|
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.label
|
||||||
|
UIPageControl.appearance().pageIndicatorTintColor = UIColor.systemGray
|
||||||
|
UITabBar.appearance().backgroundColor = UIColor(cgColor: theme.currentTheme.secondaryBGColor.cgColor ?? UIColor.secondarySystemBackground.cgColor)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||||
PersistenceController.shared.fillInMissingDates()
|
PersistenceController.shared.fillInMissingDates()
|
||||||
|
|
||||||
|
// reschedule notifications so there's a new title next notification
|
||||||
|
LocalNotification.rescheduleNotifiations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
87
Shared/Date+Extensions.swift
Normal file
87
Shared/Date+Extensions.swift
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// Date+Extensions.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/19/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Date: RawRepresentable {
|
||||||
|
public var rawValue: String {
|
||||||
|
self.timeIntervalSinceReferenceDate.description
|
||||||
|
}
|
||||||
|
|
||||||
|
public init?(rawValue: String) {
|
||||||
|
self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var startOfDay: Date {
|
||||||
|
return Calendar.current.startOfDay(for: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
var startOfMonth: Date {
|
||||||
|
|
||||||
|
let calendar = Calendar(identifier: .gregorian)
|
||||||
|
let components = calendar.dateComponents([.year, .month], from: self)
|
||||||
|
|
||||||
|
return calendar.date(from: components)!
|
||||||
|
}
|
||||||
|
|
||||||
|
var endOfDay: Date {
|
||||||
|
var components = DateComponents()
|
||||||
|
components.day = 1
|
||||||
|
components.second = -1
|
||||||
|
return Calendar.current.date(byAdding: components, to: startOfDay)!
|
||||||
|
}
|
||||||
|
|
||||||
|
var endOfMonth: Date {
|
||||||
|
var components = DateComponents()
|
||||||
|
components.month = 1
|
||||||
|
components.second = -1
|
||||||
|
return Calendar(identifier: .gregorian).date(byAdding: components, to: startOfMonth)!
|
||||||
|
}
|
||||||
|
|
||||||
|
func toLocalTime() -> Date {
|
||||||
|
let timezone = TimeZone.current
|
||||||
|
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
|
||||||
|
return Date(timeInterval: seconds, since: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
var weekday: Int {
|
||||||
|
Calendar.current.component(.weekday, from: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstDayOfTheMonth: Date {
|
||||||
|
Calendar.current.dateComponents([.calendar, .year,.month], from: self).date!
|
||||||
|
}
|
||||||
|
|
||||||
|
static func dates(from fromDate: Date, to toDate: Date) -> [Date] {
|
||||||
|
var dates: [Date] = []
|
||||||
|
var date = fromDate
|
||||||
|
|
||||||
|
while date <= toDate {
|
||||||
|
dates.append(date)
|
||||||
|
guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
|
||||||
|
date = newDate
|
||||||
|
}
|
||||||
|
return dates
|
||||||
|
}
|
||||||
|
|
||||||
|
static func dateRange(monthInt: Int, yearInt: Int) -> (startDate: Date, endDate: Date) {
|
||||||
|
var dateComponents = DateComponents()
|
||||||
|
dateComponents.year = yearInt
|
||||||
|
dateComponents.month = monthInt
|
||||||
|
dateComponents.day = 3
|
||||||
|
dateComponents.hour = 12
|
||||||
|
var userCalendar = Calendar(identifier: .gregorian)
|
||||||
|
userCalendar.timeZone = TimeZone(secondsFromGMT: 0)!
|
||||||
|
let someDateTime = userCalendar.date(from: dateComponents)!
|
||||||
|
|
||||||
|
let startDate = someDateTime.startOfMonth
|
||||||
|
var endDate = someDateTime.endOfMonth
|
||||||
|
endDate = Calendar.current.date(byAdding: .hour, value: -8, to: endDate)!
|
||||||
|
|
||||||
|
return (startDate, endDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,14 @@ class LocalNotification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class func rescheduleNotifiations() {
|
||||||
|
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.savedOnboardingData.rawValue) as? Data,
|
||||||
|
let model = try? JSONDecoder().decode(OnboardingData.self, from: data) {
|
||||||
|
LocalNotification.scheduleReminder(atTime: model.date,
|
||||||
|
withTitle: model.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class func scheduleReminder(atTime time: Date, withTitle title: String) {
|
public class func scheduleReminder(atTime time: Date, withTitle title: String) {
|
||||||
self.removeNotificaiton()
|
self.removeNotificaiton()
|
||||||
|
|
||||||
@@ -37,7 +45,7 @@ class LocalNotification {
|
|||||||
let _ = LocalNotification.createNotificationCategory()
|
let _ = LocalNotification.createNotificationCategory()
|
||||||
|
|
||||||
let notificationContent = UNMutableNotificationContent()
|
let notificationContent = UNMutableNotificationContent()
|
||||||
notificationContent.title = title
|
notificationContent.title = UserDefaultsStore.personalityPackable().randomPushNotificationTitle()
|
||||||
|
|
||||||
notificationContent.badge = NSNumber(value: 1)
|
notificationContent.badge = NSNumber(value: 1)
|
||||||
notificationContent.sound = .default
|
notificationContent.sound = .default
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
//
|
|
||||||
// CenterTiledImage.swift
|
|
||||||
// Feels (iOS)
|
|
||||||
//
|
|
||||||
// Created by Trey Tartt on 2/13/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct CenterTiledImage: View {
|
|
||||||
let imageName: String
|
|
||||||
let imageSize: CGSize
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
GeometryReader { geoReader in
|
|
||||||
let horizontalTilesNeeded = ceil(geoReader.size.width / imageSize.width / 2) * 2 + 1
|
|
||||||
let verticalTilesNeeded = ceil(geoReader.size.height / imageSize.height / 2) * 2 + 1
|
|
||||||
|
|
||||||
Image(imageName)
|
|
||||||
.resizable(resizingMode: .tile)
|
|
||||||
.frame(
|
|
||||||
width: horizontalTilesNeeded * imageSize.width,
|
|
||||||
height: verticalTilesNeeded * imageSize.height
|
|
||||||
)
|
|
||||||
.position(x: geoReader.size.width * 0.5, y: geoReader.size.height * 0.5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init?(imageName: String) {
|
|
||||||
guard let imageSize = UIImage(named: imageName)?.size else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
self.imageName = imageName
|
|
||||||
self.imageSize = imageSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -37,22 +37,8 @@ enum Mood: Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var color: Color {
|
var color: Color {
|
||||||
switch self {
|
let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
|
||||||
case .horrible:
|
return moodTint.color(forMood: self)
|
||||||
return .red
|
|
||||||
case .bad:
|
|
||||||
return .orange
|
|
||||||
case .average:
|
|
||||||
return .blue
|
|
||||||
case .good:
|
|
||||||
return .yellow
|
|
||||||
case .great:
|
|
||||||
return .green
|
|
||||||
case .missing:
|
|
||||||
return Color(uiColor: UIColor.systemGray2)
|
|
||||||
case .placeholder:
|
|
||||||
return .clear
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static var allValues: [Mood] {
|
static var allValues: [Mood] {
|
||||||
@@ -60,23 +46,8 @@ enum Mood: Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var icon: Image {
|
var icon: Image {
|
||||||
switch self {
|
let moodImages: MoodImagable.Type = UserDefaultsStore.moodMoodImagable()
|
||||||
|
return moodImages.icon(forMood: self)
|
||||||
case .horrible:
|
|
||||||
return Image("horrible", bundle: .main)
|
|
||||||
case .bad:
|
|
||||||
return Image("bad", bundle: .main)
|
|
||||||
case .average:
|
|
||||||
return Image("average", bundle: .main)
|
|
||||||
case .good:
|
|
||||||
return Image("good", bundle: .main)
|
|
||||||
case .great:
|
|
||||||
return Image("great", bundle: .main)
|
|
||||||
case .missing:
|
|
||||||
return Image("missing", bundle: .main)
|
|
||||||
case .placeholder:
|
|
||||||
return Image("missing", bundle: .main)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var graphic: Image {
|
var graphic: Image {
|
||||||
|
|||||||
104
Shared/Models/MoodImagable.swift
Normal file
104
Shared/Models/MoodImagable.swift
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
//
|
||||||
|
// MoodImagable.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/19/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
protocol MoodImagable {
|
||||||
|
static func icon(forMood mood: Mood) -> Image
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MoodImages: Int, CaseIterable {
|
||||||
|
case FontAwesome
|
||||||
|
case Emoji
|
||||||
|
case HandEmjoi
|
||||||
|
|
||||||
|
func icon(forMood mood: Mood) -> Image {
|
||||||
|
switch self {
|
||||||
|
|
||||||
|
case .FontAwesome:
|
||||||
|
return FontAwesomeMoodImages.icon(forMood: mood)
|
||||||
|
case .Emoji:
|
||||||
|
return EmojiMoodImages.icon(forMood: mood)
|
||||||
|
case .HandEmjoi:
|
||||||
|
return HandEmojiMoodImages.icon(forMood: mood)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var moodImages: MoodImagable.Type {
|
||||||
|
switch self {
|
||||||
|
case .FontAwesome:
|
||||||
|
return FontAwesomeMoodImages.self
|
||||||
|
case .Emoji:
|
||||||
|
return EmojiMoodImages.self
|
||||||
|
case .HandEmjoi:
|
||||||
|
return HandEmojiMoodImages.self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class FontAwesomeMoodImages: MoodImagable {
|
||||||
|
static func icon(forMood mood: Mood) -> Image {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Image("horrible", bundle: .main)
|
||||||
|
case .bad:
|
||||||
|
return Image("bad", bundle: .main)
|
||||||
|
case .average:
|
||||||
|
return Image("average", bundle: .main)
|
||||||
|
case .good:
|
||||||
|
return Image("good", bundle: .main)
|
||||||
|
case .great:
|
||||||
|
return Image("great", bundle: .main)
|
||||||
|
case .missing:
|
||||||
|
return Image("missing", bundle: .main)
|
||||||
|
case .placeholder:
|
||||||
|
return Image("missing", bundle: .main)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class EmojiMoodImages: MoodImagable {
|
||||||
|
static func icon(forMood mood: Mood) -> Image {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Image(uiImage: "💩".textToImage()!)
|
||||||
|
case .bad:
|
||||||
|
return Image(uiImage: "😕".textToImage()!)
|
||||||
|
case .average:
|
||||||
|
return Image(uiImage: "😑".textToImage()!)
|
||||||
|
case .good:
|
||||||
|
return Image(uiImage: "🙂".textToImage()!)
|
||||||
|
case .great:
|
||||||
|
return Image(uiImage: "😀".textToImage()!)
|
||||||
|
case .missing:
|
||||||
|
return Image(uiImage: "x".textToImage()!)
|
||||||
|
case .placeholder:
|
||||||
|
return Image(uiImage: "x".textToImage()!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class HandEmojiMoodImages: MoodImagable {
|
||||||
|
static func icon(forMood mood: Mood) -> Image {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Image(uiImage: "🖕".textToImage()!)
|
||||||
|
case .bad:
|
||||||
|
return Image(uiImage: "👎".textToImage()!)
|
||||||
|
case .average:
|
||||||
|
return Image(uiImage: "🖖".textToImage()!)
|
||||||
|
case .good:
|
||||||
|
return Image(uiImage: "👍".textToImage()!)
|
||||||
|
case .great:
|
||||||
|
return Image(uiImage: "🙏".textToImage()!)
|
||||||
|
case .missing:
|
||||||
|
return Image(uiImage: "x".textToImage()!)
|
||||||
|
case .placeholder:
|
||||||
|
return Image(uiImage: "x".textToImage()!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
266
Shared/Models/MoodTintable.swift
Normal file
266
Shared/Models/MoodTintable.swift
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
//
|
||||||
|
// MoodTintable.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/19/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
protocol MoodTintable {
|
||||||
|
static func color(forMood mood: Mood) -> Color
|
||||||
|
static func secondary(forMood mood: Mood) -> Color
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MoodTints: Int, CaseIterable {
|
||||||
|
case Default
|
||||||
|
case AllRed
|
||||||
|
case Neon
|
||||||
|
case MonoChrome
|
||||||
|
case Pastel
|
||||||
|
|
||||||
|
func color(forMood mood: Mood) -> Color {
|
||||||
|
switch self {
|
||||||
|
case .Default:
|
||||||
|
return DefaultMoodTint.color(forMood: mood)
|
||||||
|
case .AllRed:
|
||||||
|
return AllRedMoodTint.color(forMood: mood)
|
||||||
|
case .Neon:
|
||||||
|
return NeonMoodTint.color(forMood: mood)
|
||||||
|
case .MonoChrome:
|
||||||
|
return MonoChromeTint.color(forMood: mood)
|
||||||
|
case .Pastel:
|
||||||
|
return PastelTint.color(forMood: mood)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func secondary(forMood mood: Mood) -> Color {
|
||||||
|
switch self {
|
||||||
|
case .Default:
|
||||||
|
return DefaultMoodTint.secondary(forMood: mood)
|
||||||
|
case .AllRed:
|
||||||
|
return AllRedMoodTint.secondary(forMood: mood)
|
||||||
|
case .Neon:
|
||||||
|
return NeonMoodTint.secondary(forMood: mood)
|
||||||
|
case .MonoChrome:
|
||||||
|
return MonoChromeTint.secondary(forMood: mood)
|
||||||
|
case .Pastel:
|
||||||
|
return PastelTint.secondary(forMood: mood)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var moodTints: MoodTintable.Type {
|
||||||
|
switch self {
|
||||||
|
case .Default:
|
||||||
|
return DefaultMoodTint.self
|
||||||
|
case .AllRed:
|
||||||
|
return AllRedMoodTint.self
|
||||||
|
case .Neon:
|
||||||
|
return NeonMoodTint.self
|
||||||
|
case .MonoChrome:
|
||||||
|
return MonoChromeTint.self
|
||||||
|
case .Pastel:
|
||||||
|
return PastelTint.self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class DefaultMoodTint: MoodTintable {
|
||||||
|
static func color(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Color(hex: "ff453a")
|
||||||
|
case .bad:
|
||||||
|
return Color(hex: "ff9e0b")
|
||||||
|
case .average:
|
||||||
|
return Color(hex: "0b84ff")
|
||||||
|
case .good:
|
||||||
|
return Color(hex: "ffd709")
|
||||||
|
case .great:
|
||||||
|
return Color(hex: "31d158")
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray4)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func secondary(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Color(hex: "a92b26")
|
||||||
|
case .bad:
|
||||||
|
return Color(hex: "a06407")
|
||||||
|
case .average:
|
||||||
|
return Color(hex: "074f9a")
|
||||||
|
case .good:
|
||||||
|
return Color(hex: "9d8405")
|
||||||
|
case .great:
|
||||||
|
return Color(hex: "208939")
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class AllRedMoodTint: MoodTintable {
|
||||||
|
static func color(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return .red
|
||||||
|
case .bad:
|
||||||
|
return .red
|
||||||
|
case .average:
|
||||||
|
return .red
|
||||||
|
case .good:
|
||||||
|
return .red
|
||||||
|
case .great:
|
||||||
|
return .red
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func secondary(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return .red
|
||||||
|
case .bad:
|
||||||
|
return .red
|
||||||
|
case .average:
|
||||||
|
return .red
|
||||||
|
case .good:
|
||||||
|
return .red
|
||||||
|
case .great:
|
||||||
|
return .red
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class NeonMoodTint: MoodTintable {
|
||||||
|
static func color(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Color(hex: "#ff1818")
|
||||||
|
case .bad:
|
||||||
|
return Color(hex: "#FF5F1F")
|
||||||
|
case .average:
|
||||||
|
return Color(hex: "#1F51FF")
|
||||||
|
case .good:
|
||||||
|
return Color(hex: "#FFF01F")
|
||||||
|
case .great:
|
||||||
|
return Color(hex: "#39FF14")
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func secondary(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Color(hex: "#8b1113")
|
||||||
|
case .bad:
|
||||||
|
return Color(hex: "#893315")
|
||||||
|
case .average:
|
||||||
|
return Color(hex: "#0f2a85")
|
||||||
|
case .good:
|
||||||
|
return Color(hex: "#807a18")
|
||||||
|
case .great:
|
||||||
|
return Color(hex: "#218116")
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class MonoChromeTint: MoodTintable {
|
||||||
|
static func color(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return .black
|
||||||
|
case .bad:
|
||||||
|
return Color(uiColor: UIColor.systemGray)
|
||||||
|
case .average:
|
||||||
|
return Color(uiColor: UIColor.systemGray)
|
||||||
|
case .good:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .great:
|
||||||
|
return Color(uiColor: UIColor.systemGray3)
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func secondary(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return .black
|
||||||
|
case .bad:
|
||||||
|
return Color(uiColor: UIColor.systemGray)
|
||||||
|
case .average:
|
||||||
|
return Color(uiColor: UIColor.systemGray)
|
||||||
|
case .good:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .great:
|
||||||
|
return Color(uiColor: UIColor.systemGray3)
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class PastelTint: MoodTintable {
|
||||||
|
static func color(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Color(hex: "#FF6961")
|
||||||
|
case .bad:
|
||||||
|
return Color(hex: "#ffb347")
|
||||||
|
case .average:
|
||||||
|
return Color(hex: "#A7C7E7")
|
||||||
|
case .good:
|
||||||
|
return Color(hex: "#fdfd96")
|
||||||
|
case .great:
|
||||||
|
return Color(hex: "#C1E1C1")
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func secondary(forMood mood: Mood) -> Color {
|
||||||
|
switch mood {
|
||||||
|
case .horrible:
|
||||||
|
return Color(hex: "#893734")
|
||||||
|
case .bad:
|
||||||
|
return Color(hex: "#855d28")
|
||||||
|
case .average:
|
||||||
|
return Color(hex: "#5d6e83")
|
||||||
|
case .good:
|
||||||
|
return Color(hex: "#7f804f")
|
||||||
|
case .great:
|
||||||
|
return Color(hex: "#6b7e6d")
|
||||||
|
case .missing:
|
||||||
|
return Color(uiColor: UIColor.systemGray2)
|
||||||
|
case .placeholder:
|
||||||
|
return Color(uiColor: UIColor.systemGray4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,13 +7,14 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class OnboardingDataDataManager {
|
final class OnboardingDataDataManager: ObservableObject {
|
||||||
static let shared = OnboardingDataDataManager()
|
static let shared = OnboardingDataDataManager()
|
||||||
|
|
||||||
@Published public private(set) var savedOnboardingData = UserDefaultsStore.getOnboarding()
|
@Published public private(set) var savedOnboardingData = UserDefaultsStore.getOnboarding()
|
||||||
|
|
||||||
public func updateOnboardingData(onboardingData: OnboardingData) {
|
public func updateOnboardingData(onboardingData: OnboardingData) {
|
||||||
let onboardingData = UserDefaultsStore.saveOnboarding(onboardingData: onboardingData)
|
let onboardingData = UserDefaultsStore.saveOnboarding(onboardingData: onboardingData)
|
||||||
|
savedOnboardingData = onboardingData
|
||||||
LocalNotification.scheduleReminder(atTime: onboardingData.date, withTitle: onboardingData.title)
|
LocalNotification.scheduleReminder(atTime: onboardingData.date, withTitle: onboardingData.title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
91
Shared/Models/PersonalityPackable.swift
Normal file
91
Shared/Models/PersonalityPackable.swift
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// NotificationTitles.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/19/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol PersonalityPackable {
|
||||||
|
static var notificationTitlesToday: [String] { get }
|
||||||
|
static var notificationTitlesYesterday: [String] { get }
|
||||||
|
static var notificationTitlesTwoDaysAgo: [String] { get }
|
||||||
|
|
||||||
|
static var title: String { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PersonalityPack: Int, CaseIterable {
|
||||||
|
case Default
|
||||||
|
case Rude
|
||||||
|
|
||||||
|
func randomPushNotificationTitle() -> String {
|
||||||
|
switch self {
|
||||||
|
case .Default:
|
||||||
|
return DefaultTitles.notificationTitlesToday.randomElement()!
|
||||||
|
case .Rude:
|
||||||
|
return RudeTitles.notificationTitlesToday.randomElement()!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func title() -> String {
|
||||||
|
switch self {
|
||||||
|
case .Default:
|
||||||
|
return DefaultTitles.title
|
||||||
|
case .Rude:
|
||||||
|
return RudeTitles.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class DefaultTitles: PersonalityPackable {
|
||||||
|
static var title = "Nice"
|
||||||
|
|
||||||
|
static var notificationTitlesToday: [String] {
|
||||||
|
[
|
||||||
|
"How was your day",
|
||||||
|
"Don't forget to rate your day",
|
||||||
|
"Please rate your day"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static var notificationTitlesYesterday: [String] {
|
||||||
|
[
|
||||||
|
"How was your day",
|
||||||
|
"Don't forget to rate your day"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static var notificationTitlesTwoDaysAgo: [String] {
|
||||||
|
[
|
||||||
|
"How was your day",
|
||||||
|
"Don't forget to rate your day"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class RudeTitles: PersonalityPackable {
|
||||||
|
static var title = "Rude"
|
||||||
|
|
||||||
|
static var notificationTitlesToday: [String] {
|
||||||
|
[
|
||||||
|
"How the fuck was your day",
|
||||||
|
"Hey asshat, tell me how your day was",
|
||||||
|
"Hey, lazy dickbag, rate your day"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static var notificationTitlesYesterday: [String] {
|
||||||
|
[
|
||||||
|
"How was your day",
|
||||||
|
"Don't forget to rate your day"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static var notificationTitlesTwoDaysAgo: [String] {
|
||||||
|
[
|
||||||
|
"How was your day",
|
||||||
|
"Don't forget to rate your day"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ struct ThemeConstants {
|
|||||||
enum Theme: Int, CaseIterable {
|
enum Theme: Int, CaseIterable {
|
||||||
case system
|
case system
|
||||||
case iFeel
|
case iFeel
|
||||||
|
case dark
|
||||||
|
case light
|
||||||
|
|
||||||
var title: String {
|
var title: String {
|
||||||
switch self {
|
switch self {
|
||||||
@@ -21,6 +23,10 @@ enum Theme: Int, CaseIterable {
|
|||||||
return SystemTheme.title
|
return SystemTheme.title
|
||||||
case .iFeel:
|
case .iFeel:
|
||||||
return IFeelTheme.title
|
return IFeelTheme.title
|
||||||
|
case .dark:
|
||||||
|
return AlwaysDark.title
|
||||||
|
case .light:
|
||||||
|
return AlwaysLight.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,24 +37,33 @@ enum Theme: Int, CaseIterable {
|
|||||||
return SystemTheme()
|
return SystemTheme()
|
||||||
case .iFeel:
|
case .iFeel:
|
||||||
return IFeelTheme()
|
return IFeelTheme()
|
||||||
|
case .dark:
|
||||||
|
return AlwaysDark()
|
||||||
|
case .light:
|
||||||
|
return AlwaysLight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol Themeable {
|
protocol Themeable {
|
||||||
static var title: String { get }
|
static var title: String { get }
|
||||||
var secondaryBGColor: UIColor { get }
|
var secondaryBGColor: Color { get }
|
||||||
var bg: AnyView { get }
|
var bg: AnyView { get }
|
||||||
var preview: AnyView { get }
|
var preview: AnyView { get }
|
||||||
|
var labelColor: Color { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IFeelTheme: Themeable {
|
struct IFeelTheme: Themeable {
|
||||||
static var title: String {
|
var labelColor: Color {
|
||||||
return "iFeel Theme"
|
return Color(uiColor: UIColor.label)
|
||||||
}
|
}
|
||||||
|
|
||||||
var secondaryBGColor: UIColor {
|
static var title: String {
|
||||||
return UIColor.systemBackground
|
return "iFeel"
|
||||||
|
}
|
||||||
|
|
||||||
|
var secondaryBGColor: Color {
|
||||||
|
return Color(uiColor: UIColor.systemBackground)
|
||||||
}
|
}
|
||||||
|
|
||||||
var bg: AnyView {
|
var bg: AnyView {
|
||||||
@@ -69,12 +84,16 @@ struct IFeelTheme: Themeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct SystemTheme: Themeable {
|
struct SystemTheme: Themeable {
|
||||||
|
var labelColor: Color {
|
||||||
|
return Color(uiColor: UIColor.label)
|
||||||
|
}
|
||||||
|
|
||||||
static var title: String {
|
static var title: String {
|
||||||
return "System"
|
return "System"
|
||||||
}
|
}
|
||||||
|
|
||||||
var secondaryBGColor: UIColor {
|
var secondaryBGColor: Color {
|
||||||
return UIColor.secondarySystemBackground
|
return Color(uiColor: UIColor.secondarySystemBackground)
|
||||||
}
|
}
|
||||||
|
|
||||||
var bg: AnyView {
|
var bg: AnyView {
|
||||||
@@ -97,3 +116,71 @@ struct SystemTheme: Themeable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AlwaysDark: Themeable {
|
||||||
|
var labelColor: Color {
|
||||||
|
return .white
|
||||||
|
}
|
||||||
|
|
||||||
|
static var title: String {
|
||||||
|
return "Dark"
|
||||||
|
}
|
||||||
|
|
||||||
|
var secondaryBGColor: Color {
|
||||||
|
return Color(uiColor: UIColor.secondarySystemBackground.resolvedColor(with: .init(userInterfaceStyle: .dark)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var bg: AnyView {
|
||||||
|
return AnyView(
|
||||||
|
ZStack {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color(UIColor.systemBackground.resolvedColor(with: .init(userInterfaceStyle: .dark))))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var preview: AnyView {
|
||||||
|
return AnyView(
|
||||||
|
ZStack {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color(UIColor.secondarySystemBackground.resolvedColor(with: .init(userInterfaceStyle: .dark))))
|
||||||
|
.frame(width: ThemeConstants.iconSize, height: ThemeConstants.iconSize)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AlwaysLight: Themeable {
|
||||||
|
var labelColor: Color {
|
||||||
|
return .black
|
||||||
|
}
|
||||||
|
|
||||||
|
static var title: String {
|
||||||
|
return "Light"
|
||||||
|
}
|
||||||
|
|
||||||
|
var secondaryBGColor: Color {
|
||||||
|
return Color(uiColor: UIColor.secondarySystemBackground.resolvedColor(with: .init(userInterfaceStyle: .light)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var bg: AnyView {
|
||||||
|
return AnyView(
|
||||||
|
ZStack {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color(UIColor.systemBackground.resolvedColor(with: .init(userInterfaceStyle: .light))))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var preview: AnyView {
|
||||||
|
return AnyView(
|
||||||
|
ZStack {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color(UIColor.secondarySystemBackground.resolvedColor(with: .init(userInterfaceStyle: .light))))
|
||||||
|
.frame(width: ThemeConstants.iconSize, height: ThemeConstants.iconSize)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ class UserDefaultsStore {
|
|||||||
case deleteEnable
|
case deleteEnable
|
||||||
case mainViewTopHeaderIndex
|
case mainViewTopHeaderIndex
|
||||||
case theme
|
case theme
|
||||||
|
case moodImages
|
||||||
|
case moodTint
|
||||||
|
case personalityPack
|
||||||
case customIcon
|
case customIcon
|
||||||
|
|
||||||
case contentViewCurrentSelectedHeaderViewBackDays
|
case contentViewCurrentSelectedHeaderViewBackDays
|
||||||
@@ -43,4 +45,41 @@ class UserDefaultsStore {
|
|||||||
fatalError("error saving")
|
fatalError("error saving")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func moodMoodImagable() -> MoodImagable.Type {
|
||||||
|
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.moodImages.rawValue) as? Int,
|
||||||
|
let model = MoodImages.init(rawValue: data) {
|
||||||
|
return model.moodImages
|
||||||
|
} else {
|
||||||
|
return MoodImages.FontAwesome.moodImages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func moodTintable() -> MoodTintable.Type {
|
||||||
|
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.moodTint.rawValue) as? Int,
|
||||||
|
let model = MoodTints.init(rawValue: data) {
|
||||||
|
return model.moodTints
|
||||||
|
} else {
|
||||||
|
return MoodTints.Default.moodTints
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func personalityPackable() -> PersonalityPack {
|
||||||
|
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.personalityPack.rawValue) as? Int,
|
||||||
|
let model = PersonalityPack.init(rawValue: data) {
|
||||||
|
return model
|
||||||
|
} else {
|
||||||
|
return PersonalityPack.Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func theme() -> Theme {
|
||||||
|
if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.theme.rawValue) as? Int,
|
||||||
|
let model = Theme.init(rawValue: data) {
|
||||||
|
return model
|
||||||
|
} else {
|
||||||
|
return Theme.system
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
66
Shared/MoodEntryFunctions.swift
Normal file
66
Shared/MoodEntryFunctions.swift
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// MoodEntryFunctions.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/19/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class MoodEntryFunctions {
|
||||||
|
static func padMoodEntriesForCalendar(entries grouped: [Int: [Int: [MoodEntry]]]) -> [Int: [Int: [MoodEntry]]] {
|
||||||
|
var newGrouped = [Int: [Int: [MoodEntry]]]()
|
||||||
|
|
||||||
|
let allYears = grouped.keys.sorted(by: > )
|
||||||
|
for year in allYears {
|
||||||
|
var newMonth = [Int: [MoodEntry]]()
|
||||||
|
|
||||||
|
let oldMonths = grouped[year]!
|
||||||
|
let monthKeys = oldMonths.keys.sorted(by: > )
|
||||||
|
for key in monthKeys {
|
||||||
|
if let entries = oldMonths[key] {
|
||||||
|
newMonth[key] = MoodEntryFunctions.padMoodEntriesMonth(monthEntries: entries)
|
||||||
|
}
|
||||||
|
newGrouped[year] = newMonth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newGrouped
|
||||||
|
}
|
||||||
|
|
||||||
|
static func padMoodEntriesMonth(monthEntries entries: [MoodEntry]) -> [MoodEntry] {
|
||||||
|
let sortedEntries = entries.sorted(by: { $0.forDate! < $1.forDate! })
|
||||||
|
var mutableEntries = sortedEntries
|
||||||
|
|
||||||
|
if let firstDate = sortedEntries.first {
|
||||||
|
let date = firstDate.forDate!
|
||||||
|
|
||||||
|
// if the first entry for a month is in the middle of the month we
|
||||||
|
// need to add in the missing entries, as placeholders, to the beignning to get
|
||||||
|
// the entries on the right day. think user downloads in the middle of the month
|
||||||
|
// and entry is on the 13th ... this needs to show on the 13th entry spot
|
||||||
|
var startOfMonth = date.startOfMonth
|
||||||
|
startOfMonth = Calendar.current.date(byAdding: .hour, value: 9, to: startOfMonth)!
|
||||||
|
let lastMissingDate = mutableEntries.first?.forDate ?? date.endOfMonth
|
||||||
|
var missingDates = Date.dates(from: startOfMonth, to: lastMissingDate)
|
||||||
|
missingDates = missingDates.dropLast()
|
||||||
|
|
||||||
|
for date in missingDates {
|
||||||
|
mutableEntries.insert(PersistenceController.shared.generateObjectNotInArray(forDate: date, withMood: .placeholder), at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutableEntries = mutableEntries.sorted(by: {
|
||||||
|
$0.forDate! < $1.forDate!
|
||||||
|
})
|
||||||
|
|
||||||
|
// fill in calendar day offset .. if month starts on wed we need to
|
||||||
|
// pad the beginning sun, mon, tues
|
||||||
|
if let firstDate = mutableEntries.first?.forDate {
|
||||||
|
let weekday = Int16(Calendar.current.component(.weekday, from: firstDate))
|
||||||
|
for _ in 1..<weekday {
|
||||||
|
mutableEntries.insert(PersistenceController.shared.generateObjectNotInArray(withMood: .placeholder), at: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mutableEntries
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,7 +32,8 @@ extension PersistenceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fillInMissingDates() {
|
func fillInMissingDates() {
|
||||||
let endDate = ShowBasedOnVoteLogics.getLastDateVoteShouldExist()
|
let currentOnboarding = UserDefaultsStore.getOnboarding()
|
||||||
|
let endDate = ShowBasedOnVoteLogics.getLastDateVoteShouldExist(onboardingData: currentOnboarding)
|
||||||
|
|
||||||
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: false)]
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: false)]
|
||||||
|
|||||||
@@ -73,13 +73,12 @@ extension PersistenceController {
|
|||||||
var components = DateComponents()
|
var components = DateComponents()
|
||||||
components.month = month
|
components.month = month
|
||||||
components.year = year
|
components.year = year
|
||||||
|
components.day = 1
|
||||||
let startDateOfMonth = Calendar.current.date(from: components)!
|
let startDateOfMonth = Calendar.current.date(from: components)!
|
||||||
|
|
||||||
let items = data.filter({ entry in
|
let items = PersistenceController.shared.getData(startDate: startDateOfMonth,
|
||||||
let components = calendar.dateComponents([.month, .year], from: startDateOfMonth)
|
endDate: startDateOfMonth.endOfMonth,
|
||||||
let entryComponents = calendar.dateComponents([.month, .year], from: entry.forDate!)
|
includedDays: [1,2,3,4,5,6,7])
|
||||||
return (components.month == entryComponents.month && components.year == entryComponents.year)
|
|
||||||
})
|
|
||||||
if !items.isEmpty {
|
if !items.isEmpty {
|
||||||
allMonths[month] = items
|
allMonths[month] = items
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,11 +51,11 @@ extension PersistenceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateObjectNotInArray() -> MoodEntry {
|
func generateObjectNotInArray(forDate date: Date = Date(), withMood mood: Mood = .placeholder) -> MoodEntry {
|
||||||
let newItem = MoodEntry(context: childContext)
|
let newItem = MoodEntry(context: childContext)
|
||||||
newItem.timestamp = Date()
|
newItem.timestamp = Date()
|
||||||
newItem.moodValue = Int16(Mood.placeholder.rawValue)
|
newItem.moodValue = Int16(mood.rawValue)
|
||||||
newItem.forDate = Date()
|
newItem.forDate = date
|
||||||
newItem.weekDay = Int16(Calendar.current.component(.weekday, from: Date()))
|
newItem.weekDay = Int16(Calendar.current.component(.weekday, from: Date()))
|
||||||
newItem.canEdit = false
|
newItem.canEdit = false
|
||||||
newItem.canDelete = false
|
newItem.canDelete = false
|
||||||
|
|||||||
@@ -77,7 +77,9 @@ extension ChartDataBuildable {
|
|||||||
let date = components.day
|
let date = components.day
|
||||||
return day == date
|
return day == date
|
||||||
}).first {
|
}).first {
|
||||||
let view = ChartType(color: item.mood.color,
|
let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
|
||||||
|
|
||||||
|
let view = ChartType(color: moodTint.color(forMood: item.mood),
|
||||||
weekDay: Int(item.weekDay),
|
weekDay: Int(item.weekDay),
|
||||||
viewType: .square)
|
viewType: .square)
|
||||||
filledOutArray.append(view)
|
filledOutArray.append(view)
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ struct GroupUserDefaults {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias MoodGroupingMetrics = (mood: Mood, total: Int, percent: Float)
|
|
||||||
|
|
||||||
class Random {
|
class Random {
|
||||||
static var tomorrowMidnightThirty: Date {
|
static var tomorrowMidnightThirty: Date {
|
||||||
let components = DateComponents(hour: 0, minute: 30, second: 0)
|
let components = DateComponents(hour: 0, minute: 30, second: 0)
|
||||||
@@ -52,61 +50,29 @@ class Random {
|
|||||||
return formatter.string(from: NSNumber(integerLiteral: day)) ?? ""
|
return formatter.string(from: NSNumber(integerLiteral: day)) ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
static func createTotalPerc(fromEntries entries: [MoodEntry]) -> [MoodGroupingMetrics] {
|
static func createTotalPerc(fromEntries entries: [MoodEntry]) -> [MoodMetrics] {
|
||||||
var returnData = [MoodGroupingMetrics]()
|
let filteredEntries = entries.filter({
|
||||||
|
return ![.missing, .placeholder].contains($0.mood)
|
||||||
|
})
|
||||||
|
var returnData = [MoodMetrics]()
|
||||||
|
|
||||||
for (_, mood) in Mood.allValues.enumerated() {
|
for (_, mood) in Mood.allValues.enumerated() {
|
||||||
let moodEntries = entries.filter({
|
let moodEntries = filteredEntries.filter({
|
||||||
Int($0.moodValue) == mood.rawValue
|
Int($0.moodValue) == mood.rawValue
|
||||||
})
|
})
|
||||||
let total = moodEntries.count
|
let total = moodEntries.count
|
||||||
let perc = (Float(total) / Float(entries.count)) * 100
|
let perc = (Float(total) / Float(filteredEntries.count)) * 100
|
||||||
returnData.append((mood, total, perc))
|
returnData.append(MoodMetrics(mood: mood, total: total, percent: perc))
|
||||||
}
|
}
|
||||||
|
|
||||||
returnData = returnData.sorted(by: {
|
returnData = returnData.sorted(by: {
|
||||||
$0.0.rawValue > $1.0.rawValue
|
$0.mood.rawValue > $1.mood.rawValue
|
||||||
})
|
})
|
||||||
|
|
||||||
return returnData
|
return returnData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Date: RawRepresentable {
|
|
||||||
public var rawValue: String {
|
|
||||||
self.timeIntervalSinceReferenceDate.description
|
|
||||||
}
|
|
||||||
|
|
||||||
public init?(rawValue: String) {
|
|
||||||
self = Date(timeIntervalSinceReferenceDate: Double(rawValue) ?? 0.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func startOfMonth() -> Date {
|
|
||||||
let interval = Calendar.current.dateInterval(of: .month, for: self)
|
|
||||||
return (interval?.start.toLocalTime())! // Without toLocalTime it give last months last date
|
|
||||||
}
|
|
||||||
|
|
||||||
func endOfMonth() -> Date {
|
|
||||||
let interval = Calendar.current.dateInterval(of: .month, for: self)
|
|
||||||
return interval!.end
|
|
||||||
}
|
|
||||||
|
|
||||||
func toLocalTime() -> Date {
|
|
||||||
let timezone = TimeZone.current
|
|
||||||
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
|
|
||||||
return Date(timeInterval: seconds, since: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
var weekday: Int {
|
|
||||||
Calendar.current.component(.weekday, from: self)
|
|
||||||
}
|
|
||||||
|
|
||||||
var firstDayOfTheMonth: Date {
|
|
||||||
Calendar.current.dateComponents([.calendar, .year,.month], from: self).date!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct RoundedCorner: Shape {
|
struct RoundedCorner: Shape {
|
||||||
|
|
||||||
var radius: CGFloat = .infinity
|
var radius: CGFloat = .infinity
|
||||||
@@ -153,20 +119,6 @@ extension UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Date {
|
|
||||||
static func dates(from fromDate: Date, to toDate: Date) -> [Date] {
|
|
||||||
var dates: [Date] = []
|
|
||||||
var date = fromDate
|
|
||||||
|
|
||||||
while date <= toDate {
|
|
||||||
dates.append(date)
|
|
||||||
guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
|
|
||||||
date = newDate
|
|
||||||
}
|
|
||||||
return dates
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Color {
|
extension Color {
|
||||||
static func random() -> Self {
|
static func random() -> Self {
|
||||||
Self(
|
Self(
|
||||||
@@ -175,4 +127,47 @@ extension Color {
|
|||||||
blue: .random(in: 0...1)
|
blue: .random(in: 0...1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init(hex: String) {
|
||||||
|
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
||||||
|
var int: UInt64 = 0
|
||||||
|
Scanner(string: hex).scanHexInt64(&int)
|
||||||
|
let a, r, g, b: UInt64
|
||||||
|
switch hex.count {
|
||||||
|
case 3: // RGB (12-bit)
|
||||||
|
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
|
||||||
|
case 6: // RGB (24-bit)
|
||||||
|
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
|
||||||
|
case 8: // ARGB (32-bit)
|
||||||
|
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
|
||||||
|
default:
|
||||||
|
(a, r, g, b) = (1, 1, 1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
.sRGB,
|
||||||
|
red: Double(r) / 255,
|
||||||
|
green: Double(g) / 255,
|
||||||
|
blue: Double(b) / 255,
|
||||||
|
opacity: Double(a) / 255
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
func textToImage() -> UIImage? {
|
||||||
|
let nsString = (self as NSString)
|
||||||
|
let font = UIFont.systemFont(ofSize: 100) // you can change your font size here
|
||||||
|
let stringAttributes = [NSAttributedString.Key.font: font]
|
||||||
|
let imageSize = nsString.size(withAttributes: stringAttributes)
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContextWithOptions(imageSize, false, 0) // begin image context
|
||||||
|
UIColor.clear.set() // clear background
|
||||||
|
UIRectFill(CGRect(origin: CGPoint(), size: imageSize)) // set rect size
|
||||||
|
nsString.draw(at: CGPoint.zero, withAttributes: stringAttributes) // draw text within rect
|
||||||
|
let image = UIGraphicsGetImageFromCurrentImageContext() // create image from context
|
||||||
|
UIGraphicsEndImageContext() // end image context
|
||||||
|
|
||||||
|
return image ?? UIImage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,17 +18,13 @@ import SwiftUI
|
|||||||
// today at 11 am -> How as 2 days ago
|
// today at 11 am -> How as 2 days ago
|
||||||
// today at 1 pm -> How was yesterday
|
// today at 1 pm -> How was yesterday
|
||||||
class ShowBasedOnVoteLogics {
|
class ShowBasedOnVoteLogics {
|
||||||
private static var currentVoting: (passTimeToVote: Bool, dayOptions: DayOptions) {
|
static func isMissingCurrentVote(onboardingData: OnboardingData) -> Bool {
|
||||||
let passedTimeToVote = UserDefaultsStore.getOnboarding().ableToVoteBasedOnCurentTime()
|
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
|
||||||
let inputDay = UserDefaultsStore.getOnboarding().inputDay
|
let inputDay = onboardingData.inputDay
|
||||||
|
|
||||||
return (passedTimeToVote, inputDay)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func isMissingCurrentVote() -> Bool {
|
|
||||||
var startDate: Date?
|
var startDate: Date?
|
||||||
|
|
||||||
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
|
switch (passedTimeToVote, inputDay) {
|
||||||
case (true, .Previous):
|
case (true, .Previous):
|
||||||
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
||||||
startDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
|
startDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
|
||||||
@@ -57,8 +53,11 @@ class ShowBasedOnVoteLogics {
|
|||||||
return entries < 1
|
return entries < 1
|
||||||
}
|
}
|
||||||
|
|
||||||
static func getVotingTitle() -> String {
|
static func getVotingTitle(onboardingData: OnboardingData) -> String {
|
||||||
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
|
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
|
||||||
|
let inputDay = onboardingData.inputDay
|
||||||
|
|
||||||
|
switch (passedTimeToVote, inputDay) {
|
||||||
case (true, .Previous):
|
case (true, .Previous):
|
||||||
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
||||||
return "how was yesterday"
|
return "how was yesterday"
|
||||||
@@ -67,7 +66,7 @@ class ShowBasedOnVoteLogics {
|
|||||||
return "how is today"
|
return "how is today"
|
||||||
case (false, .Previous):
|
case (false, .Previous):
|
||||||
// if we're passed time to vote and the voting type is previous - last vote should be -2
|
// if we're passed time to vote and the voting type is previous - last vote should be -2
|
||||||
let lastDayVoteShouldExist = ShowBasedOnVoteLogics.getLastDateVoteShouldExist()
|
let lastDayVoteShouldExist = ShowBasedOnVoteLogics.getLastDateVoteShouldExist(onboardingData: onboardingData)
|
||||||
return "how was \(Random.weekdayName(fromDate: lastDayVoteShouldExist))"
|
return "how was \(Random.weekdayName(fromDate: lastDayVoteShouldExist))"
|
||||||
case (false, .Today):
|
case (false, .Today):
|
||||||
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
||||||
@@ -75,10 +74,13 @@ class ShowBasedOnVoteLogics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func dateForHeaderVote() -> Date? {
|
static func dateForHeaderVote(onboardingData: OnboardingData) -> Date? {
|
||||||
|
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
|
||||||
|
let inputDay = onboardingData.inputDay
|
||||||
|
|
||||||
var date: Date?
|
var date: Date?
|
||||||
|
|
||||||
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
|
switch (passedTimeToVote, inputDay) {
|
||||||
case (true, .Previous):
|
case (true, .Previous):
|
||||||
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
// if we're passed time to vote and the voting type is previous - last vote should be -1
|
||||||
date = Calendar.current.date(byAdding: .day, value: -1, to: Date())
|
date = Calendar.current.date(byAdding: .day, value: -1, to: Date())
|
||||||
@@ -100,10 +102,13 @@ class ShowBasedOnVoteLogics {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
static func getLastDateVoteShouldExist() -> Date {
|
static func getLastDateVoteShouldExist(onboardingData: OnboardingData) -> Date {
|
||||||
|
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
|
||||||
|
let inputDay = onboardingData.inputDay
|
||||||
|
|
||||||
var endDate: Date?
|
var endDate: Date?
|
||||||
|
|
||||||
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
|
switch (passedTimeToVote, inputDay) {
|
||||||
case (true, .Previous):
|
case (true, .Previous):
|
||||||
// if we're passed time to vote and the voting type is previous - last vote should -1
|
// if we're passed time to vote and the voting type is previous - last vote should -1
|
||||||
endDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
|
endDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import SwiftUI
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
struct AddMoodHeaderView: View {
|
struct AddMoodHeaderView: View {
|
||||||
private let savedOnboardingData = UserDefaultsStore.getOnboarding()
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
|
@State var onboardingData = OnboardingDataDataManager.shared.savedOnboardingData
|
||||||
|
|
||||||
let addItemHeaderClosure: ((Mood, Date) -> Void)
|
let addItemHeaderClosure: ((Mood, Date) -> Void)
|
||||||
|
|
||||||
@@ -22,12 +24,12 @@ struct AddMoodHeaderView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Text(ShowBasedOnVoteLogics.getVotingTitle())
|
Text(ShowBasedOnVoteLogics.getVotingTitle(onboardingData: onboardingData))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.padding()
|
.padding()
|
||||||
HStack{
|
HStack{
|
||||||
ForEach(Mood.allValues) { mood in
|
ForEach(Mood.allValues) { mood in
|
||||||
@@ -38,7 +40,7 @@ struct AddMoodHeaderView: View {
|
|||||||
mood.icon
|
mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: CGFloat(50), height: CGFloat(50), alignment: .center)
|
.frame(width: CGFloat(50), height: CGFloat(50), alignment: .center)
|
||||||
.foregroundColor(mood.color)
|
.foregroundColor(moodTint.color(forMood: mood))
|
||||||
})
|
})
|
||||||
|
|
||||||
//Text(mood.strValue)
|
//Text(mood.strValue)
|
||||||
@@ -49,7 +51,7 @@ struct AddMoodHeaderView: View {
|
|||||||
.padding([.leading, .trailing, .bottom])
|
.padding([.leading, .trailing, .bottom])
|
||||||
}
|
}
|
||||||
.background(
|
.background(
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
.frame(minHeight: 88, maxHeight: 150)
|
.frame(minHeight: 88, maxHeight: 150)
|
||||||
@@ -57,7 +59,7 @@ struct AddMoodHeaderView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func addItem(withMood mood: Mood) {
|
private func addItem(withMood mood: Mood) {
|
||||||
if let date = ShowBasedOnVoteLogics.dateForHeaderVote() {
|
if let date = ShowBasedOnVoteLogics.dateForHeaderVote(onboardingData: onboardingData) {
|
||||||
addItemHeaderClosure(mood, date)
|
addItemHeaderClosure(mood, date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,16 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct BGViewItem: View {
|
struct BGViewItem: View {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
let mood: Mood
|
let mood: Mood
|
||||||
let size: CGSize
|
let size: CGSize
|
||||||
var color: Color
|
var color: Color
|
||||||
let animate: Bool
|
let animate: Bool
|
||||||
let yRowPosition: Float
|
let yRowPosition: Float
|
||||||
|
|
||||||
init(mood: Mood, size: CGSize, animate: Bool, yRowPosition: Float) {
|
init(mood: Mood, size: CGSize, animate: Bool, yRowPosition: Float, color: Color) {
|
||||||
color = mood.color
|
self.color = color
|
||||||
self.mood = mood
|
self.mood = mood
|
||||||
self.size = size
|
self.size = size
|
||||||
self.yRowPosition = yRowPosition
|
self.yRowPosition = yRowPosition
|
||||||
@@ -23,16 +25,18 @@ struct BGViewItem: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Mood.allValues.randomElement()?.icon
|
FontAwesomeMoodImages.icon(forMood: mood)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: size.width, height: size.height)
|
.frame(width: size.width, height: size.height)
|
||||||
.foregroundColor(color)
|
.foregroundColor(DefaultMoodTint.color(forMood: mood))
|
||||||
// .blur(radius: 3)
|
// .blur(radius: 3)
|
||||||
.opacity(0.1)
|
.opacity(0.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BGView: View, Equatable {
|
struct BGView: View, Equatable {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
var numAcross: Int
|
var numAcross: Int
|
||||||
var numDown: Int
|
var numDown: Int
|
||||||
let iconSize = 35
|
let iconSize = 35
|
||||||
@@ -45,15 +49,22 @@ struct BGView: View, Equatable {
|
|||||||
numDown = Int(screenHeight)/iconSize
|
numDown = Int(screenHeight)/iconSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var randomMood: Mood? {
|
||||||
|
return Mood.allValues.randomElement()
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
ForEach(0...numDown, id: \.self) { row in
|
ForEach(0...numDown, id: \.self) { row in
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(0...numAcross, id: \.self) { _ in
|
ForEach(0...numAcross, id: \.self) { _ in
|
||||||
BGViewItem(mood: Mood.allValues.randomElement()!,
|
if let randomMood = randomMood {
|
||||||
size: .init(width: iconSize,height: iconSize),
|
BGViewItem(mood: randomMood,
|
||||||
animate: false,
|
size: .init(width: iconSize,height: iconSize),
|
||||||
yRowPosition: Float(row)/Float(numDown))
|
animate: false,
|
||||||
|
yRowPosition: Float(row)/Float(numDown),
|
||||||
|
color: moodTint.color(forMood:randomMood))
|
||||||
|
}
|
||||||
}.frame(minWidth: 0, maxWidth: .infinity)
|
}.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
.padding([.trailing, .leading], 13.5)
|
.padding([.trailing, .leading], 13.5)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,47 +7,47 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct CreateIconView: View {
|
struct CreateWidgetView: View {
|
||||||
@AppStorage(UserDefaultsStore.Keys.customIcon.rawValue, store: GroupUserDefaults.groupDefaults) private var savedCustomIcon = Data()
|
@AppStorage(UserDefaultsStore.Keys.customIcon.rawValue, store: GroupUserDefaults.groupDefaults) private var savedCustomIcon = Data()
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
static var iconViewBGs: [(BackGroundOptions, UUID)] = {
|
static var iconViewBGs: [(CustomWidgetBackGroundOptions, UUID)] = {
|
||||||
var blah = [(BackGroundOptions, UUID)]()
|
var blah = [(CustomWidgetBackGroundOptions, UUID)]()
|
||||||
for _ in 0...99 {
|
for _ in 0...99 {
|
||||||
blah.append((BackGroundOptions.selectable.randomElement()!, UUID()))
|
blah.append((CustomWidgetBackGroundOptions.selectable.randomElement()!, UUID()))
|
||||||
}
|
}
|
||||||
return blah
|
return blah
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@State private var mouth: MouthOptions = MouthOptions.defaultOption
|
@State private var mouth: CustomWidgetMouthOptions = CustomWidgetMouthOptions.defaultOption
|
||||||
@StateObject private var customIcon = CustomIcon(leftEye: EyeOptions.defaultOption,
|
@StateObject private var customIcon = CustomWidgetModel(leftEye: CustomWidgetEyeOptions.defaultOption,
|
||||||
rightEye: EyeOptions.defaultOption,
|
rightEye: CustomWidgetEyeOptions.defaultOption,
|
||||||
mouth: MouthOptions.defaultOption,
|
mouth: CustomWidgetMouthOptions.defaultOption,
|
||||||
background: CreateIconView.iconViewBGs,
|
background: CreateWidgetView.iconViewBGs,
|
||||||
bgColor: .red,
|
bgColor: .red,
|
||||||
innerColor: .green,
|
innerColor: .green,
|
||||||
bgOverlayColor: .black,
|
bgOverlayColor: .black,
|
||||||
rightEyeColor: .orange,
|
rightEyeColor: .orange,
|
||||||
leftEyeColor: .yellow,
|
leftEyeColor: .yellow,
|
||||||
mouthColor: .purple,
|
mouthColor: .purple,
|
||||||
circleStrokeColor: .pink)
|
circleStrokeColor: .pink)
|
||||||
private var randomElements: [AnyView] = [
|
private var randomElements: [AnyView] = [
|
||||||
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
|
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 20, height: 20)),
|
.frame(width: 20, height: 20)),
|
||||||
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
|
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 20, height: 20)),
|
.frame(width: 20, height: 20)),
|
||||||
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
|
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 20, height: 20)),
|
.frame(width: 20, height: 20)),
|
||||||
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
|
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 20, height: 20))
|
.frame(width: 20, height: 20))
|
||||||
]
|
]
|
||||||
|
|
||||||
func update(eye: Eyes, eyeOption: EyeOptions) {
|
func update(eye: CustomWidgetEyes, eyeOption: CustomWidgetEyeOptions) {
|
||||||
switch eye {
|
switch eye {
|
||||||
case .left:
|
case .left:
|
||||||
customIcon.leftEye = eyeOption
|
customIcon.leftEye = eyeOption
|
||||||
@@ -65,27 +65,27 @@ struct CreateIconView: View {
|
|||||||
customIcon.rightEyeColor = Color.random()
|
customIcon.rightEyeColor = Color.random()
|
||||||
customIcon.mouthColor = Color.random()
|
customIcon.mouthColor = Color.random()
|
||||||
|
|
||||||
update(eye: .left, eyeOption: EyeOptions.allCases.randomElement()!)
|
update(eye: .left, eyeOption: CustomWidgetEyeOptions.allCases.randomElement()!)
|
||||||
update(eye: .right, eyeOption: EyeOptions.allCases.randomElement()!)
|
update(eye: .right, eyeOption: CustomWidgetEyeOptions.allCases.randomElement()!)
|
||||||
update(mouthOption: MouthOptions.allCases.randomElement()!)
|
update(mouthOption: CustomWidgetMouthOptions.allCases.randomElement()!)
|
||||||
|
|
||||||
update(background: BackGroundOptions.allCases.randomElement()!)
|
update(background: CustomWidgetBackGroundOptions.allCases.randomElement()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(mouthOption: MouthOptions) {
|
func update(mouthOption: CustomWidgetMouthOptions) {
|
||||||
customIcon.mouth = mouthOption
|
customIcon.mouth = mouthOption
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(background: BackGroundOptions) {
|
func update(background: CustomWidgetBackGroundOptions) {
|
||||||
customIcon.background.removeAll()
|
customIcon.background.removeAll()
|
||||||
|
|
||||||
if background == .random {
|
if background == .random {
|
||||||
for _ in 0...CustomIcon.numberOfBGItems {
|
for _ in 0...CustomWidgetModel.numberOfBGItems {
|
||||||
customIcon.background.append((BackGroundOptions.selectable.randomElement()!, UUID()))
|
customIcon.background.append((CustomWidgetBackGroundOptions.selectable.randomElement()!, UUID()))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _ in 0...CustomIcon.numberOfBGItems {
|
for _ in 0...CustomWidgetModel.numberOfBGItems {
|
||||||
customIcon.background.append((background, UUID()))
|
customIcon.background.append((background, UUID()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,16 +103,16 @@ struct CreateIconView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var iconView: some View {
|
var widgetView: some View {
|
||||||
IconView(customIcon: customIcon, isPreview: true)
|
CustomWidgetView(customWidgetModel: customIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
iconView
|
widgetView
|
||||||
.frame(width: 256, height: 256)
|
// .frame(width: 256, height: 256)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
.padding(.top)
|
.padding()
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ struct CreateIconView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Menu("Left Eye") {
|
Menu("Left Eye") {
|
||||||
ForEach(EyeOptions.allCases, id: \.self) { option in
|
ForEach(CustomWidgetEyeOptions.allCases, id: \.self) { option in
|
||||||
Button(action: {
|
Button(action: {
|
||||||
update(eye: .left, eyeOption: option)
|
update(eye: .left, eyeOption: option)
|
||||||
}, label: {
|
}, label: {
|
||||||
@@ -131,12 +131,12 @@ struct CreateIconView: View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Menu("Right Eye") {
|
Menu("Right Eye") {
|
||||||
ForEach(EyeOptions.allCases, id: \.self) { option in
|
ForEach(CustomWidgetEyeOptions.allCases, id: \.self) { option in
|
||||||
Button(action: {
|
Button(action: {
|
||||||
update(eye: .right, eyeOption: option)
|
update(eye: .right, eyeOption: option)
|
||||||
}, label: {
|
}, label: {
|
||||||
@@ -144,12 +144,12 @@ struct CreateIconView: View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Menu("Mouth") {
|
Menu("Mouth") {
|
||||||
ForEach(MouthOptions.allCases, id: \.self) { option in
|
ForEach(CustomWidgetMouthOptions.allCases, id: \.self) { option in
|
||||||
Button(action: {
|
Button(action: {
|
||||||
update(mouthOption: option)
|
update(mouthOption: option)
|
||||||
}, label: {
|
}, label: {
|
||||||
@@ -157,13 +157,13 @@ struct CreateIconView: View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(
|
.background(
|
||||||
Color(uiColor: theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ struct CreateIconView: View {
|
|||||||
|
|
||||||
Group {
|
Group {
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(BackGroundOptions.selectable, id: \.self) { bg in
|
ForEach(CustomWidgetBackGroundOptions.selectable, id: \.self) { bg in
|
||||||
Image(bg.rawValue, bundle: .main)
|
Image(bg.rawValue, bundle: .main)
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fill)
|
.aspectRatio(contentMode: .fill)
|
||||||
@@ -191,7 +191,7 @@ struct CreateIconView: View {
|
|||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(
|
.background(
|
||||||
Color(uiColor: theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ struct CreateIconView: View {
|
|||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.background(
|
.background(
|
||||||
Color(uiColor: theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ struct CreateIconView: View {
|
|||||||
.background(.blue)
|
.background(.blue)
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
let bigIconView = IconView(customIcon: customIcon, isPreview: false)
|
let bigIconView = CustomWidgetView(customWidgetModel: customIcon)
|
||||||
.frame(width: 512, height: 512, alignment: .center)
|
.frame(width: 512, height: 512, alignment: .center)
|
||||||
.aspectRatio(contentMode: .fill)
|
.aspectRatio(contentMode: .fill)
|
||||||
let icon = bigIconView.snapshot()
|
let icon = bigIconView.snapshot()
|
||||||
@@ -297,9 +297,9 @@ struct CreateIconView: View {
|
|||||||
struct CreateIconView_Previews: PreviewProvider {
|
struct CreateIconView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group {
|
Group {
|
||||||
CreateIconView()
|
CreateWidgetView()
|
||||||
|
|
||||||
CreateIconView()
|
CreateWidgetView()
|
||||||
.preferredColorScheme(.dark)
|
.preferredColorScheme(.dark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
124
Shared/views/CustomIcon/IconView.swift
Normal file
124
Shared/views/CustomIcon/IconView.swift
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// IconView.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/20/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct IconView: View {
|
||||||
|
@State public var iconViewModel: IconViewModel
|
||||||
|
|
||||||
|
private let facePercSize = 0.6
|
||||||
|
public let isPreview: Bool
|
||||||
|
|
||||||
|
private var gridXOffset: CGFloat {
|
||||||
|
if isPreview {
|
||||||
|
return CGFloat(0)
|
||||||
|
}
|
||||||
|
return CGFloat(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var gridYOffset: CGFloat {
|
||||||
|
if isPreview {
|
||||||
|
return CGFloat(0)
|
||||||
|
}
|
||||||
|
return CGFloat(-8)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var entireFuckingViewOffset: CGFloat {
|
||||||
|
if isPreview {
|
||||||
|
return CGFloat(0)
|
||||||
|
}
|
||||||
|
return CGFloat(25)
|
||||||
|
}
|
||||||
|
|
||||||
|
let columns = [
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
GeometryReader { geo in
|
||||||
|
ZStack {
|
||||||
|
Rectangle()
|
||||||
|
.fill(
|
||||||
|
iconViewModel.bgColor
|
||||||
|
)
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
|
||||||
|
LazyVGrid(columns: columns, alignment: .leading, spacing: 0) {
|
||||||
|
ForEach(iconViewModel.background, id: \.self.1) { (bgOption, uuid) in
|
||||||
|
bgOption
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(1, contentMode: .fill)
|
||||||
|
.foregroundColor(iconViewModel.bgOverlayColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scaleEffect(1.1)
|
||||||
|
.clipped()
|
||||||
|
.background(
|
||||||
|
.clear
|
||||||
|
)
|
||||||
|
|
||||||
|
Circle()
|
||||||
|
.strokeBorder(iconViewModel.bgColor, lineWidth: geo.size.width * 0.045)
|
||||||
|
.background(Circle().fill(iconViewModel.bgColor))
|
||||||
|
.frame(width: geo.size.width*facePercSize,
|
||||||
|
height: geo.size.height*facePercSize,
|
||||||
|
alignment: .center)
|
||||||
|
.position(x: geo.size.width/2, y: geo.size.height/2)
|
||||||
|
|
||||||
|
iconViewModel.centerImage
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(width: geo.size.width*facePercSize,
|
||||||
|
height: geo.size.height*facePercSize,
|
||||||
|
alignment: .center)
|
||||||
|
.foregroundColor(iconViewModel.bgOverlayColor)
|
||||||
|
.position(x: geo.size.width/2, y: geo.size.height/2)
|
||||||
|
|
||||||
|
}
|
||||||
|
.position(x: geo.size.width/2,
|
||||||
|
y: geo.size.height/2 - entireFuckingViewOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IconView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
Group {
|
||||||
|
IconView(iconViewModel: IconViewModel.great, isPreview: false)
|
||||||
|
.frame(width: 256, height: 256, alignment: .center)
|
||||||
|
|
||||||
|
// IconView(iconViewModel: IconViewModel.good, isPreview: true)
|
||||||
|
// .frame(width: 256, height: 256, alignment: .center)
|
||||||
|
//
|
||||||
|
// IconView(iconViewModel: IconViewModel.average, isPreview: true)
|
||||||
|
// .frame(width: 256, height: 256, alignment: .center)
|
||||||
|
//
|
||||||
|
// IconView(iconViewModel: IconViewModel.bad, isPreview: true)
|
||||||
|
// .frame(width: 256, height: 256, alignment: .center)
|
||||||
|
//
|
||||||
|
// IconView(iconViewModel: IconViewModel.horrible, isPreview: true)
|
||||||
|
// .frame(width: 256, height: 256, alignment: .center)
|
||||||
|
//
|
||||||
|
// IconView(iconViewModel: IconViewModel(backgroundImage: EmojiMoodImages.icon(forMood: .horrible),
|
||||||
|
// bgColor: MoodTints.Neon.color(forMood: .horrible),
|
||||||
|
// bgOverlayColor: MoodTints.Neon.color(forMood: .horrible),
|
||||||
|
// centerImage: EmojiMoodImages.icon(forMood: .horrible)),
|
||||||
|
// isPreview: true)
|
||||||
|
// .frame(width: 256, height: 256, alignment: .center)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
80
Shared/views/CustomIcon/IconViewModel.swift
Normal file
80
Shared/views/CustomIcon/IconViewModel.swift
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// CustomIcon.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/20/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
class IconViewModel: ObservableObject {
|
||||||
|
static let numberOfBGItems = 109
|
||||||
|
|
||||||
|
static let great = IconViewModel(backgroundImage: MoodImages.FontAwesome.icon(forMood: .great),
|
||||||
|
bgColor: Color(hex: "31d158"),
|
||||||
|
bgOverlayColor: Color(hex: "208939"),
|
||||||
|
centerImage: MoodImages.FontAwesome.icon(forMood: .great))
|
||||||
|
|
||||||
|
static let good = IconViewModel(backgroundImage: MoodImages.FontAwesome.icon(forMood: .good),
|
||||||
|
bgColor: Color(hex: "ffd709"),
|
||||||
|
bgOverlayColor: Color(hex: "9d8405"),
|
||||||
|
centerImage: MoodImages.FontAwesome.icon(forMood: .good))
|
||||||
|
|
||||||
|
static let average = IconViewModel(backgroundImage: MoodImages.FontAwesome.icon(forMood: .average),
|
||||||
|
bgColor: Color(hex: "0b84ff"),
|
||||||
|
bgOverlayColor: Color(hex: "074f9a"),
|
||||||
|
centerImage: MoodImages.FontAwesome.icon(forMood: .average))
|
||||||
|
|
||||||
|
static let bad = IconViewModel(backgroundImage: MoodImages.FontAwesome.icon(forMood: .bad),
|
||||||
|
bgColor: Color(hex: "ff9f0b"),
|
||||||
|
bgOverlayColor: Color(hex: "a06407"),
|
||||||
|
centerImage: MoodImages.FontAwesome.icon(forMood: .bad))
|
||||||
|
|
||||||
|
static let horrible = IconViewModel(backgroundImage: MoodImages.FontAwesome.icon(forMood: .horrible),
|
||||||
|
bgColor: Color(hex: "fe5257"),
|
||||||
|
bgOverlayColor: Color(hex: "a92b26"),
|
||||||
|
centerImage: MoodImages.FontAwesome.icon(forMood: .horrible))
|
||||||
|
|
||||||
|
init(backgroundImage: Image,
|
||||||
|
bgColor: Color,
|
||||||
|
bgOverlayColor: Color,
|
||||||
|
centerImage: Image
|
||||||
|
) {
|
||||||
|
|
||||||
|
var blah = [(Image, UUID)]()
|
||||||
|
for _ in 0...IconViewModel.numberOfBGItems {
|
||||||
|
blah.append((backgroundImage, UUID()))
|
||||||
|
}
|
||||||
|
|
||||||
|
self.background = blah
|
||||||
|
self.bgColor = bgColor
|
||||||
|
self.bgOverlayColor = bgOverlayColor
|
||||||
|
self.centerImage = centerImage
|
||||||
|
}
|
||||||
|
|
||||||
|
@Published var background: [(Image, UUID)]
|
||||||
|
@Published var bgColor: Color
|
||||||
|
@Published var bgOverlayColor: Color
|
||||||
|
@Published var centerImage: Image
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CustomIconBackGroundOptions: String, CaseIterable, Codable {
|
||||||
|
case horrible
|
||||||
|
case bad
|
||||||
|
case average
|
||||||
|
case good
|
||||||
|
case great
|
||||||
|
case random
|
||||||
|
|
||||||
|
static var selectable: [CustomIconBackGroundOptions] {
|
||||||
|
return [.great, .good, .average, .bad, .horrible]
|
||||||
|
}
|
||||||
|
|
||||||
|
static public var defaultOption: CustomIconBackGroundOptions {
|
||||||
|
CustomIconBackGroundOptions.random
|
||||||
|
}
|
||||||
|
|
||||||
|
public var image: Image {
|
||||||
|
return Image(self.rawValue, bundle: .main)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,26 +7,26 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
class CustomIcon: ObservableObject {
|
class CustomWidgetModel: ObservableObject {
|
||||||
static let numberOfBGItems = 99
|
static let numberOfBGItems = 109
|
||||||
|
|
||||||
static let defaultCustomIcon = CustomIcon(leftEye: EyeOptions.defaultOption,
|
static let defaultCustomIcon = CustomWidgetModel(leftEye: CustomWidgetEyeOptions.defaultOption,
|
||||||
rightEye: EyeOptions.defaultOption,
|
rightEye: CustomWidgetEyeOptions.defaultOption,
|
||||||
mouth: MouthOptions.defaultOption,
|
mouth: CustomWidgetMouthOptions.defaultOption,
|
||||||
background: IconView_Previews.backgrounds,
|
background: WidgetView_Previews.backgrounds,
|
||||||
bgColor: .red,
|
bgColor: .red,
|
||||||
innerColor: .green,
|
innerColor: .green,
|
||||||
bgOverlayColor: .orange,
|
bgOverlayColor: .orange,
|
||||||
rightEyeColor: .orange,
|
rightEyeColor: .orange,
|
||||||
leftEyeColor: .yellow,
|
leftEyeColor: .yellow,
|
||||||
mouthColor: .green,
|
mouthColor: .green,
|
||||||
circleStrokeColor: .pink)
|
circleStrokeColor: .pink)
|
||||||
|
|
||||||
|
|
||||||
init(leftEye: EyeOptions,
|
init(leftEye: CustomWidgetEyeOptions,
|
||||||
rightEye: EyeOptions,
|
rightEye: CustomWidgetEyeOptions,
|
||||||
mouth: MouthOptions,
|
mouth: CustomWidgetMouthOptions,
|
||||||
background: [(BackGroundOptions, UUID)],
|
background: [(CustomWidgetBackGroundOptions, UUID)],
|
||||||
bgColor: Color,
|
bgColor: Color,
|
||||||
innerColor: Color,
|
innerColor: Color,
|
||||||
bgOverlayColor: Color,
|
bgOverlayColor: Color,
|
||||||
@@ -48,11 +48,11 @@ class CustomIcon: ObservableObject {
|
|||||||
self.circleStrokeColor = circleStrokeColor
|
self.circleStrokeColor = circleStrokeColor
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published var leftEye: EyeOptions
|
@Published var leftEye: CustomWidgetEyeOptions
|
||||||
@Published var rightEye: EyeOptions
|
@Published var rightEye: CustomWidgetEyeOptions
|
||||||
@Published var mouth: MouthOptions
|
@Published var mouth: CustomWidgetMouthOptions
|
||||||
|
|
||||||
@Published var background: [(BackGroundOptions, UUID)]
|
@Published var background: [(CustomWidgetBackGroundOptions, UUID)]
|
||||||
@Published var bgColor: Color
|
@Published var bgColor: Color
|
||||||
@Published var innerColor: Color
|
@Published var innerColor: Color
|
||||||
@Published var bgOverlayColor: Color
|
@Published var bgOverlayColor: Color
|
||||||
@@ -64,7 +64,7 @@ class CustomIcon: ObservableObject {
|
|||||||
@Published var circleStrokeColor: Color
|
@Published var circleStrokeColor: Color
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BackGroundOptions: String, CaseIterable, Codable {
|
enum CustomWidgetBackGroundOptions: String, CaseIterable, Codable {
|
||||||
case horrible
|
case horrible
|
||||||
case bad
|
case bad
|
||||||
case average
|
case average
|
||||||
@@ -72,12 +72,12 @@ enum BackGroundOptions: String, CaseIterable, Codable {
|
|||||||
case great
|
case great
|
||||||
case random
|
case random
|
||||||
|
|
||||||
static var selectable: [BackGroundOptions] {
|
static var selectable: [CustomWidgetBackGroundOptions] {
|
||||||
return [.great, .good, .average, .bad, .horrible]
|
return [.great, .good, .average, .bad, .horrible]
|
||||||
}
|
}
|
||||||
|
|
||||||
static public var defaultOption: BackGroundOptions {
|
static public var defaultOption: CustomWidgetBackGroundOptions {
|
||||||
BackGroundOptions.random
|
CustomWidgetBackGroundOptions.random
|
||||||
}
|
}
|
||||||
|
|
||||||
public var image: Image {
|
public var image: Image {
|
||||||
@@ -85,12 +85,12 @@ enum BackGroundOptions: String, CaseIterable, Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Eyes: String, Codable {
|
enum CustomWidgetEyes: String, Codable {
|
||||||
case left
|
case left
|
||||||
case right
|
case right
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EyeOptions: String, CaseIterable, Codable {
|
enum CustomWidgetEyeOptions: String, CaseIterable, Codable {
|
||||||
case fire = "fire"
|
case fire = "fire"
|
||||||
case bolt = "bolt2"
|
case bolt = "bolt2"
|
||||||
case dollar = "dollar"
|
case dollar = "dollar"
|
||||||
@@ -109,8 +109,8 @@ enum EyeOptions: String, CaseIterable, Codable {
|
|||||||
case skull2 = "skull2"
|
case skull2 = "skull2"
|
||||||
case poo = "poo"
|
case poo = "poo"
|
||||||
|
|
||||||
static public var defaultOption: EyeOptions {
|
static public var defaultOption: CustomWidgetEyeOptions {
|
||||||
EyeOptions.fire
|
CustomWidgetEyeOptions.fire
|
||||||
}
|
}
|
||||||
|
|
||||||
public var image: Image {
|
public var image: Image {
|
||||||
@@ -118,7 +118,7 @@ enum EyeOptions: String, CaseIterable, Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MouthOptions: String, CaseIterable, Codable {
|
enum CustomWidgetMouthOptions: String, CaseIterable, Codable {
|
||||||
case fire = "fire"
|
case fire = "fire"
|
||||||
case bolt = "bolt2"
|
case bolt = "bolt2"
|
||||||
case dollar = "dollar"
|
case dollar = "dollar"
|
||||||
@@ -137,8 +137,8 @@ enum MouthOptions: String, CaseIterable, Codable {
|
|||||||
case skull2 = "skull2"
|
case skull2 = "skull2"
|
||||||
case poo = "poo"
|
case poo = "poo"
|
||||||
|
|
||||||
static public var defaultOption: MouthOptions {
|
static public var defaultOption: CustomWidgetMouthOptions {
|
||||||
MouthOptions.bomb
|
CustomWidgetMouthOptions.bomb
|
||||||
}
|
}
|
||||||
|
|
||||||
public var image: Image {
|
public var image: Image {
|
||||||
@@ -7,32 +7,31 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct IconView: View {
|
struct CustomWidgetView: View {
|
||||||
@State public var customIcon: CustomIcon
|
@State public var customWidgetModel: CustomWidgetModel
|
||||||
|
|
||||||
private let facePercSize = 0.6
|
private let facePercSize = 0.6
|
||||||
public let isPreview: Bool
|
|
||||||
|
|
||||||
private var gridXOffset: CGFloat {
|
// private var gridXOffset: CGFloat {
|
||||||
if isPreview {
|
// if isPreview {
|
||||||
return CGFloat(0)
|
// return CGFloat(0)
|
||||||
}
|
// }
|
||||||
return CGFloat(6)
|
// return CGFloat(6)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private var gridYOffset: CGFloat {
|
// private var gridYOffset: CGFloat {
|
||||||
if isPreview {
|
// if isPreview {
|
||||||
return CGFloat(0)
|
// return CGFloat(0)
|
||||||
}
|
// }
|
||||||
return CGFloat(-8)
|
// return CGFloat(-8)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private var entireFuckingViewOffset: CGFloat {
|
// private var entireFuckingViewOffset: CGFloat {
|
||||||
if isPreview {
|
// if isPreview {
|
||||||
return CGFloat(0)
|
// return CGFloat(0)
|
||||||
}
|
// }
|
||||||
return CGFloat(25)
|
// return CGFloat(25)
|
||||||
}
|
// }
|
||||||
|
|
||||||
let columns = [
|
let columns = [
|
||||||
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
GridItem(.flexible(minimum: 1, maximum: 100), spacing: 1),
|
||||||
@@ -52,32 +51,33 @@ struct IconView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(
|
.fill(
|
||||||
customIcon.bgColor
|
customWidgetModel.bgColor
|
||||||
)
|
)
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
|
||||||
LazyVGrid(columns: columns, alignment: .leading, spacing: 0) {
|
LazyVGrid(columns: columns, alignment: .leading, spacing: 0) {
|
||||||
ForEach(customIcon.background, id: \.self.1) { (bgOption, uuid) in
|
ForEach(customWidgetModel.background, id: \.self.1) { (bgOption, uuid) in
|
||||||
bgOption.image
|
bgOption.image
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(1, contentMode: .fill)
|
.aspectRatio(1, contentMode: .fill)
|
||||||
.foregroundColor(customIcon.bgOverlayColor)
|
.foregroundColor(customWidgetModel.bgOverlayColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.scaleEffect(1.1)
|
||||||
|
.clipped()
|
||||||
.background(
|
.background(
|
||||||
.clear
|
.clear
|
||||||
)
|
)
|
||||||
|
|
||||||
Circle()
|
Circle()
|
||||||
.strokeBorder(customIcon.circleStrokeColor, lineWidth: geo.size.width * 0.045)
|
.strokeBorder(customWidgetModel.circleStrokeColor, lineWidth: geo.size.width * 0.045)
|
||||||
.background(Circle().fill(customIcon.innerColor))
|
.background(Circle().fill(customWidgetModel.innerColor))
|
||||||
.frame(width: geo.size.width*facePercSize,
|
.frame(width: geo.size.width*facePercSize,
|
||||||
height: geo.size.height*facePercSize,
|
height: geo.size.height*facePercSize,
|
||||||
alignment: .center)
|
alignment: .center)
|
||||||
.position(x: geo.size.width/2, y: geo.size.height/2)
|
.position(x: geo.size.width/2, y: geo.size.height/2)
|
||||||
|
|
||||||
customIcon.leftEye.image
|
customWidgetModel.leftEye.image
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: geo.size.width*0.12,
|
.frame(width: geo.size.width*0.12,
|
||||||
@@ -85,9 +85,9 @@ struct IconView: View {
|
|||||||
alignment: .center)
|
alignment: .center)
|
||||||
.position(x: geo.size.width*0.4,
|
.position(x: geo.size.width*0.4,
|
||||||
y: geo.size.height*0.4)
|
y: geo.size.height*0.4)
|
||||||
.foregroundColor(customIcon.leftEyeColor)
|
.foregroundColor(customWidgetModel.leftEyeColor)
|
||||||
|
|
||||||
customIcon.rightEye.image
|
customWidgetModel.rightEye.image
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: geo.size.width*0.12,
|
.frame(width: geo.size.width*0.12,
|
||||||
@@ -95,9 +95,9 @@ struct IconView: View {
|
|||||||
alignment: .center)
|
alignment: .center)
|
||||||
.position(x: geo.size.width*0.6,
|
.position(x: geo.size.width*0.6,
|
||||||
y: geo.size.height*0.4)
|
y: geo.size.height*0.4)
|
||||||
.foregroundColor(customIcon.rightEyeColor)
|
.foregroundColor(customWidgetModel.rightEyeColor)
|
||||||
|
|
||||||
customIcon.mouth.image
|
customWidgetModel.mouth.image
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: geo.size.width*0.12,
|
.frame(width: geo.size.width*0.12,
|
||||||
@@ -105,26 +105,25 @@ struct IconView: View {
|
|||||||
alignment: .center)
|
alignment: .center)
|
||||||
.position(x: geo.size.width*0.5,
|
.position(x: geo.size.width*0.5,
|
||||||
y: geo.size.height*0.59)
|
y: geo.size.height*0.59)
|
||||||
.foregroundColor(customIcon.mouthColor)
|
.foregroundColor(customWidgetModel.mouthColor)
|
||||||
}
|
}
|
||||||
.position(x: geo.size.width/2,
|
.position(x: geo.size.width/2,
|
||||||
y: geo.size.height/2 - entireFuckingViewOffset)
|
y: geo.size.height/2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IconView_Previews: PreviewProvider {
|
struct WidgetView_Previews: PreviewProvider {
|
||||||
static var backgrounds: [(BackGroundOptions, UUID)] = {
|
static var backgrounds: [(CustomWidgetBackGroundOptions, UUID)] = {
|
||||||
var blah = [(BackGroundOptions, UUID)]()
|
var blah = [(CustomWidgetBackGroundOptions, UUID)]()
|
||||||
for _ in 0...CustomIcon.numberOfBGItems {
|
for _ in 0...CustomWidgetModel.numberOfBGItems {
|
||||||
blah.append((BackGroundOptions.selectable.randomElement()!, UUID()))
|
blah.append((CustomWidgetBackGroundOptions.selectable.randomElement()!, UUID()))
|
||||||
}
|
}
|
||||||
return blah
|
return blah
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
IconView(customIcon: CustomIcon.defaultCustomIcon,
|
CustomWidgetView(customWidgetModel: CustomWidgetModel.defaultCustomIcon)
|
||||||
isPreview: true)
|
|
||||||
.frame(width: 256, height: 256, alignment: .center)
|
.frame(width: 256, height: 256, alignment: .center)
|
||||||
|
|
||||||
}
|
}
|
||||||
239
Shared/views/CustomizeView/CustomizeView.swift
Normal file
239
Shared/views/CustomizeView/CustomizeView.swift
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
//
|
||||||
|
// CustomizeView.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/19/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct CustomizeView: View {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodImages.rawValue, store: GroupUserDefaults.groupDefaults) private var imagePack: MoodImages = .FontAwesome
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.personalityPack.rawValue, store: GroupUserDefaults.groupDefaults) private var personalityPack: PersonalityPack = .Default
|
||||||
|
|
||||||
|
@State private var showCreateCustomWidget = false
|
||||||
|
|
||||||
|
let iconSets: [(String,String)] = [
|
||||||
|
("PurpleFeelsAppIcon", "PurpleAppIcon"),
|
||||||
|
("RedFeelsAppIcon", "RedAppIcon")
|
||||||
|
]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
VStack {
|
||||||
|
Text(String(localized: "customize_view_title"))
|
||||||
|
.font(.title)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
.padding([.trailing, .leading], 55)
|
||||||
|
.padding([.top], 15)
|
||||||
|
|
||||||
|
createCustomWidget
|
||||||
|
changeIcon
|
||||||
|
themePicker
|
||||||
|
pickMoodImagePack
|
||||||
|
pickMoodTintPack
|
||||||
|
pickPeronsalityPack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.sheet(isPresented: $showCreateCustomWidget) {
|
||||||
|
CreateWidgetView()
|
||||||
|
}
|
||||||
|
.background(
|
||||||
|
theme.currentTheme.bg
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var changeIcon: some View {
|
||||||
|
ZStack {
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
VStack {
|
||||||
|
Text(String(localized: "settings_view_change_icon"))
|
||||||
|
HStack {
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
UIApplication.shared.setAlternateIconName(nil)
|
||||||
|
}, label: {
|
||||||
|
Image("FeelsAppIcon", bundle: .main)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 50, height:50)
|
||||||
|
.cornerRadius(10)
|
||||||
|
})
|
||||||
|
.padding()
|
||||||
|
|
||||||
|
ForEach(iconSets, id: \.self.0){ iconSet in
|
||||||
|
Button(action: {
|
||||||
|
UIApplication.shared.setAlternateIconName(iconSet.1) { (error) in
|
||||||
|
// FIXME: Handle error
|
||||||
|
}
|
||||||
|
}, label: {
|
||||||
|
Image(iconSet.0, bundle: .main)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 50, height:50)
|
||||||
|
.cornerRadius(10)
|
||||||
|
})
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
|
||||||
|
private var themePicker: some View {
|
||||||
|
ZStack {
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
VStack {
|
||||||
|
Text(String(localized: "settings_background_title"))
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
ForEach(Theme.allCases, id:\.rawValue) { aTheme in
|
||||||
|
Button(action: {
|
||||||
|
theme = aTheme
|
||||||
|
}, label: {
|
||||||
|
VStack {
|
||||||
|
aTheme.currentTheme.preview
|
||||||
|
.overlay(
|
||||||
|
Circle()
|
||||||
|
.stroke(Color(UIColor.systemGray), style: StrokeStyle(lineWidth: 2))
|
||||||
|
)
|
||||||
|
Text(aTheme.title)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.top)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
|
||||||
|
private var createCustomWidget: some View {
|
||||||
|
ZStack {
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
Button(action: {
|
||||||
|
showCreateCustomWidget = true
|
||||||
|
}, label: {
|
||||||
|
Text("Create Custom Widget")
|
||||||
|
})
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
|
||||||
|
private var pickMoodImagePack: some View {
|
||||||
|
ZStack {
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
VStack {
|
||||||
|
ForEach(MoodImages.allCases, id: \.rawValue) { images in
|
||||||
|
HStack {
|
||||||
|
ForEach(Mood.allValues, id: \.self) { mood in
|
||||||
|
images.icon(forMood: mood)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 35, height: 35)
|
||||||
|
.foregroundColor(
|
||||||
|
moodTint.color(forMood: mood)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
|
.onTapGesture {
|
||||||
|
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
|
impactMed.impactOccurred()
|
||||||
|
imagePack = images
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if images.rawValue != (MoodImages.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 {
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
|
||||||
|
private var pickMoodTintPack: some View {
|
||||||
|
ZStack {
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
VStack {
|
||||||
|
ForEach(MoodTints.allCases, id: \.rawValue) { tint in
|
||||||
|
HStack {
|
||||||
|
ForEach(Mood.allValues, id: \.self) { mood in
|
||||||
|
Circle()
|
||||||
|
.frame(width: 35, height: 35)
|
||||||
|
.foregroundColor(
|
||||||
|
tint.color(forMood: mood)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
|
.onTapGesture {
|
||||||
|
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
|
impactMed.impactOccurred()
|
||||||
|
moodTint = tint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tint.rawValue != (MoodTints.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 {
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
|
||||||
|
private var pickPeronsalityPack: some View {
|
||||||
|
ZStack {
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
VStack {
|
||||||
|
ForEach(PersonalityPack.allCases, id: \.self) { aPack in
|
||||||
|
VStack(spacing: 10) {
|
||||||
|
Text(String(aPack.title()))
|
||||||
|
.font(.title)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
|
||||||
|
|
||||||
|
Text(aPack.randomPushNotificationTitle())
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(Color(UIColor.systemGray))
|
||||||
|
}
|
||||||
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
|
.padding()
|
||||||
|
.onTapGesture {
|
||||||
|
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||||
|
impactMed.impactOccurred()
|
||||||
|
personalityPack = aPack
|
||||||
|
LocalNotification.rescheduleNotifiations()
|
||||||
|
|
||||||
|
UITabBar.appearance().backgroundColor = UIColor(cgColor: theme.currentTheme.secondaryBGColor.cgColor ?? UIColor.secondarySystemBackground.cgColor)
|
||||||
|
}
|
||||||
|
if aPack.rawValue != (PersonalityPack.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 {
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CustomizeView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
CustomizeView()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,21 +10,21 @@ import SwiftUI
|
|||||||
struct EmptyHomeView: View {
|
struct EmptyHomeView: View {
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
let viewModel: ContentModeViewModel
|
let viewModel: HomeViewViewModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Text(String(localized: "content_view_empty_title"))
|
Text(String(localized: "content_view_empty_title"))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
Text(String(localized: "content_view_empty_title"))
|
Text(String(localized: "content_view_empty_title"))
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.padding()
|
.padding()
|
||||||
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
|
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
|
||||||
withAnimation {
|
withAnimation {
|
||||||
@@ -40,6 +40,6 @@ struct EmptyHomeView: View {
|
|||||||
|
|
||||||
struct EmptyHomeView_Previews: PreviewProvider {
|
struct EmptyHomeView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
EmptyHomeView(viewModel: ContentModeViewModel(addMonthStartWeekdayPadding: false))
|
EmptyHomeView(viewModel: HomeViewViewModel(addMonthStartWeekdayPadding: false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ struct FilterView: View {
|
|||||||
private var items: FetchedResults<MoodEntry>
|
private var items: FetchedResults<MoodEntry>
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
@StateObject private var viewModel = FilterViewModel()
|
@StateObject private var viewModel = FilterViewModel()
|
||||||
//[
|
//[
|
||||||
// 2001: [0: [], 1: [], 2: []],
|
// 2001: [0: [], 1: [], 2: []],
|
||||||
@@ -54,6 +55,7 @@ struct FilterView: View {
|
|||||||
|
|
||||||
Text(String(localized: "filter_view_total") + ": \(self.viewModel.numberOfRatings)")
|
Text(String(localized: "filter_view_total") + ": \(self.viewModel.numberOfRatings)")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
|
||||||
if showFilter {
|
if showFilter {
|
||||||
filterView
|
filterView
|
||||||
@@ -80,13 +82,16 @@ struct FilterView: View {
|
|||||||
Text(showFilter ? String(localized: "filter_view_hide_filters") : String(localized: "filter_view_show_filters"))
|
Text(showFilter ? String(localized: "filter_view_hide_filters") : String(localized: "filter_view_show_filters"))
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: 44)
|
.frame(height: 44)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.background(Color(theme.currentTheme.secondaryBGColor))
|
.background(theme.currentTheme.secondaryBGColor)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
}).frame(maxWidth: .infinity)
|
}).frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StatsSubView: View {
|
struct StatsSubView: View {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
let data: [MoodEntry]
|
let data: [MoodEntry]
|
||||||
let mood: Mood
|
let mood: Mood
|
||||||
|
|
||||||
@@ -95,15 +100,16 @@ struct FilterView: View {
|
|||||||
Text(String(Stats.getCountFor(moodType: mood,
|
Text(String(Stats.getCountFor(moodType: mood,
|
||||||
inData: data)))
|
inData: data)))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
Text(mood.strValue)
|
Text(mood.strValue)
|
||||||
.foregroundColor(mood.color)
|
.foregroundColor(moodTint.color(forMood: mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var statsView: some View {
|
private var statsView: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -120,7 +126,7 @@ struct FilterView: View {
|
|||||||
VStack {
|
VStack {
|
||||||
VStack {
|
VStack {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
DatePicker(
|
DatePicker(
|
||||||
String(localized: "filter_view_begin_date"),
|
String(localized: "filter_view_begin_date"),
|
||||||
selection: $viewModel.entryStartDate,
|
selection: $viewModel.entryStartDate,
|
||||||
@@ -133,9 +139,10 @@ struct FilterView: View {
|
|||||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44)
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing])
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
DatePicker(
|
DatePicker(
|
||||||
String(localized: "filter_view_end_date"),
|
String(localized: "filter_view_end_date"),
|
||||||
selection: $viewModel.entryEndDate,
|
selection: $viewModel.entryEndDate,
|
||||||
@@ -148,9 +155,10 @@ struct FilterView: View {
|
|||||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44)
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing])
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
ForEach(weekdays.indices, id: \.self) { dayIdx in
|
ForEach(weekdays.indices, id: \.self) { dayIdx in
|
||||||
@@ -186,6 +194,7 @@ struct FilterView: View {
|
|||||||
ForEach(months, id: \.self.0) { item in
|
ForEach(months, id: \.self.0) { item in
|
||||||
Text(item.1)
|
Text(item.1)
|
||||||
.textCase(.uppercase)
|
.textCase(.uppercase)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
}
|
}
|
||||||
}.padding([.leading, .trailing, .top])
|
}.padding([.leading, .trailing, .top])
|
||||||
}
|
}
|
||||||
@@ -202,9 +211,10 @@ struct FilterView: View {
|
|||||||
let yearData = self.viewModel.data[yearKey]!
|
let yearData = self.viewModel.data[yearKey]!
|
||||||
Text(String(yearKey))
|
Text(String(yearKey))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
yearGridView(yearData: yearData, columns: columns)
|
yearGridView(yearData: yearData, columns: columns)
|
||||||
.background(
|
.background(
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
}
|
}
|
||||||
@@ -13,8 +13,9 @@ enum PercViewType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct HeaderPercView: View {
|
struct HeaderPercView: View {
|
||||||
typealias model = (mood: Mood, total: Int, percent: Float)
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
var entries = [model]()
|
|
||||||
|
var entries = [MoodMetrics]()
|
||||||
let backDays: Int
|
let backDays: Int
|
||||||
let type: PercViewType
|
let type: PercViewType
|
||||||
|
|
||||||
@@ -32,44 +33,34 @@ struct HeaderPercView: View {
|
|||||||
moodEntries = PersistenceController.shared.getData(startDate: daysAgo, endDate: Date(), includedDays: [1,2,3,4,5,6,7])
|
moodEntries = PersistenceController.shared.getData(startDate: daysAgo, endDate: Date(), includedDays: [1,2,3,4,5,6,7])
|
||||||
}
|
}
|
||||||
|
|
||||||
let totalEntryCount = moodEntries?.count ?? 0
|
|
||||||
|
|
||||||
if let moodEntries = moodEntries {
|
if let moodEntries = moodEntries {
|
||||||
for (_, mood) in Mood.allValues.enumerated() {
|
entries = Random.createTotalPerc(fromEntries: moodEntries)
|
||||||
|
|
||||||
let moodEntries = moodEntries.filter({
|
entries = entries.sorted(by: {
|
||||||
Int($0.moodValue) == mood.rawValue
|
$0.mood.rawValue > $1.mood.rawValue
|
||||||
})
|
})
|
||||||
let total = moodEntries.count
|
|
||||||
let perc = (Float(total) / Float(totalEntryCount)) * 100
|
|
||||||
entries.append((mood, total, perc))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entries = entries.sorted(by: {
|
|
||||||
$0.0.rawValue > $1.0.rawValue
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var textViews: some View {
|
private var textViews: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(entries.prefix(3), id: \.0) { model in
|
ForEach(entries.prefix(3), id: \.id) { model in
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.foregroundColor(model.mood.color)
|
.foregroundColor(moodTint.color(forMood: model.mood))
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(entries.suffix(2), id: \.0) { model in
|
ForEach(entries.suffix(2), id: \.id) { model in
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.foregroundColor(model.mood.color)
|
.foregroundColor(moodTint.color(forMood: model.mood))
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,27 +72,27 @@ struct HeaderPercView: View {
|
|||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(entries.prefix(3), id: \.0) { model in
|
ForEach(entries.prefix(3), id: \.id) { model in
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding()
|
.padding()
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Circle().fill(model.mood.color))
|
.background(Circle().fill(moodTint.color(forMood: model.mood)))
|
||||||
.foregroundColor(Color(UIColor.white))
|
.foregroundColor(Color(UIColor.white))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(entries.suffix(2), id: \.0) { model in
|
ForEach(entries.suffix(2), id: \.id) { model in
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding()
|
.padding()
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background(Circle().fill(model.mood.color))
|
.background(Circle().fill(moodTint.color(forMood: model.mood)))
|
||||||
.foregroundColor(Color(UIColor.white))
|
.foregroundColor(Color(UIColor.white))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import Charts
|
|||||||
struct HeaderStatsView : UIViewRepresentable {
|
struct HeaderStatsView : UIViewRepresentable {
|
||||||
//Bar chart accepts data as array of BarChartDataEntry objects
|
//Bar chart accepts data as array of BarChartDataEntry objects
|
||||||
var entries : [BarChartDataEntry]
|
var entries : [BarChartDataEntry]
|
||||||
|
var moodTint: MoodTints
|
||||||
|
|
||||||
init(fakeData: Bool, backDays: Int) {
|
init(fakeData: Bool, backDays: Int, moodTint: MoodTints) {
|
||||||
|
self.moodTint = moodTint
|
||||||
entries = [BarChartDataEntry]()
|
entries = [BarChartDataEntry]()
|
||||||
|
|
||||||
var moodEntries: [MoodEntry]?
|
var moodEntries: [MoodEntry]?
|
||||||
@@ -96,7 +98,7 @@ struct HeaderStatsView : UIViewRepresentable {
|
|||||||
let dataSet = BarChartDataSet(entries: entries)
|
let dataSet = BarChartDataSet(entries: entries)
|
||||||
|
|
||||||
// change bars color to green
|
// change bars color to green
|
||||||
dataSet.colors = Mood.allValues.map({ NSUIColor( $0.color ) })
|
dataSet.colors = Mood.allValues.map({ NSUIColor( moodTint.color(forMood: $0) ) })
|
||||||
dataSet.secondaryTextColor = UIColor.systemGray
|
dataSet.secondaryTextColor = UIColor.systemGray
|
||||||
dataSet.valueColors = [.white]
|
dataSet.valueColors = [.white]
|
||||||
dataSet.highlightAlpha = 0.0
|
dataSet.highlightAlpha = 0.0
|
||||||
@@ -120,6 +122,6 @@ struct HeaderStatsView : UIViewRepresentable {
|
|||||||
|
|
||||||
struct HeaderStatsView_Previews: PreviewProvider {
|
struct HeaderStatsView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
HeaderStatsView(fakeData: true, backDays: 30).frame(minHeight: 85, maxHeight: 90)
|
HeaderStatsView(fakeData: true, backDays: 30, moodTint: .Default).frame(minHeight: 85, maxHeight: 90)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ struct HomeView: View {
|
|||||||
@AppStorage(UserDefaultsStore.Keys.deleteEnable.rawValue, store: GroupUserDefaults.groupDefaults) private var deleteEnabled = true
|
@AppStorage(UserDefaultsStore.Keys.deleteEnable.rawValue, store: GroupUserDefaults.groupDefaults) private var deleteEnabled = true
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodImages.rawValue, store: GroupUserDefaults.groupDefaults) private var imagePack: MoodImages = .FontAwesome
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
// MARK: top header storage
|
// MARK: top header storage
|
||||||
@AppStorage(UserDefaultsStore.Keys.contentViewCurrentSelectedHeaderViewBackDays.rawValue, store: GroupUserDefaults.groupDefaults) private var currentSelectedHeaderViewBackDays: Int = 30
|
@AppStorage(UserDefaultsStore.Keys.contentViewCurrentSelectedHeaderViewBackDays.rawValue, store: GroupUserDefaults.groupDefaults) private var currentSelectedHeaderViewBackDays: Int = 30
|
||||||
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTagViewOneViewType.rawValue, store: GroupUserDefaults.groupDefaults) private var firstSwichableHeaderViewType: MainSwitchableViewType = .total
|
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTagViewOneViewType.rawValue, store: GroupUserDefaults.groupDefaults) private var firstSwichableHeaderViewType: MainSwitchableViewType = .total
|
||||||
@@ -37,6 +40,7 @@ struct HomeView: View {
|
|||||||
// MARK: ?? properties
|
// MARK: ?? properties
|
||||||
@State private var showTodayInput = true
|
@State private var showTodayInput = true
|
||||||
@State private var showUpdateEntryAlert = false
|
@State private var showUpdateEntryAlert = false
|
||||||
|
@StateObject private var onboardingData = OnboardingDataDataManager.shared
|
||||||
|
|
||||||
// MARK: header properties
|
// MARK: header properties
|
||||||
@State private var headerHeight: CGFloat = HomeViewConstants.maxHeaderHeight
|
@State private var headerHeight: CGFloat = HomeViewConstants.maxHeaderHeight
|
||||||
@@ -44,17 +48,11 @@ struct HomeView: View {
|
|||||||
@State private var headerOpacity: Double = 1.0
|
@State private var headerOpacity: Double = 1.0
|
||||||
//
|
//
|
||||||
|
|
||||||
@ObservedObject var viewModel = ContentModeViewModel(addMonthStartWeekdayPadding: false)
|
@ObservedObject var viewModel = HomeViewViewModel(addMonthStartWeekdayPadding: false)
|
||||||
|
|
||||||
init(){
|
|
||||||
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.label
|
|
||||||
UIPageControl.appearance().pageIndicatorTintColor = UIColor.systemGray
|
|
||||||
UITabBar.appearance().backgroundColor = UIColor.secondarySystemBackground
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
mainView
|
mainView
|
||||||
.alert(ContentModeViewModel.updateTitleHeader(forEntry: selectedEntry),
|
.alert(HomeViewViewModel.updateTitleHeader(forEntry: selectedEntry),
|
||||||
isPresented: $showUpdateEntryAlert) {
|
isPresented: $showUpdateEntryAlert) {
|
||||||
ForEach(Mood.allValues) { mood in
|
ForEach(Mood.allValues) { mood in
|
||||||
Button(mood.strValue, action: {
|
Button(mood.strValue, action: {
|
||||||
@@ -130,11 +128,12 @@ struct HomeView: View {
|
|||||||
VStack {
|
VStack {
|
||||||
SmallRollUpHeaderView(entries: getBackEntries(),
|
SmallRollUpHeaderView(entries: getBackEntries(),
|
||||||
viewType: $currentSelectedHeaderViewViewType)
|
viewType: $currentSelectedHeaderViewViewType)
|
||||||
|
.frame(height: HomeViewConstants.minHeaderHeight)
|
||||||
|
.padding([.trailing, .leading])
|
||||||
.background(
|
.background(
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
.padding([.top, .bottom], 5)
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
@@ -173,8 +172,6 @@ struct HomeView: View {
|
|||||||
withAnimation{
|
withAnimation{
|
||||||
viewModel.updateData()
|
viewModel.updateData()
|
||||||
}
|
}
|
||||||
}, updateBoardingDataClosure: { onboardingData in
|
|
||||||
OnboardingDataDataManager.shared.updateOnboardingData(onboardingData: onboardingData)
|
|
||||||
})
|
})
|
||||||
}.padding(.trailing)
|
}.padding(.trailing)
|
||||||
}
|
}
|
||||||
@@ -182,7 +179,7 @@ struct HomeView: View {
|
|||||||
|
|
||||||
private var headerView: some View {
|
private var headerView: some View {
|
||||||
VStack {
|
VStack {
|
||||||
if ShowBasedOnVoteLogics.isMissingCurrentVote() {
|
if ShowBasedOnVoteLogics.isMissingCurrentVote(onboardingData: onboardingData.savedOnboardingData) {
|
||||||
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
|
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
|
||||||
withAnimation {
|
withAnimation {
|
||||||
viewModel.add(mood: mood, forDate: date, entryType: .header)
|
viewModel.add(mood: mood, forDate: date, entryType: .header)
|
||||||
@@ -255,7 +252,7 @@ struct HomeView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
.background(
|
.background(
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
.coordinateSpace(name: "scroll")
|
.coordinateSpace(name: "scroll")
|
||||||
.onPreferenceChange(ViewOffsetKey.self) { value in
|
.onPreferenceChange(ViewOffsetKey.self) { value in
|
||||||
@@ -281,11 +278,11 @@ extension HomeView {
|
|||||||
private func SectionHeaderView(month: Int, year: Int) -> some View {
|
private func SectionHeaderView(month: Int, year: Int) -> some View {
|
||||||
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
|
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.padding()
|
.padding()
|
||||||
.background(
|
.background(
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,23 +304,23 @@ extension HomeView {
|
|||||||
|
|
||||||
private func entryListView(entry: MoodEntry) -> some View {
|
private func entryListView(entry: MoodEntry) -> some View {
|
||||||
HStack {
|
HStack {
|
||||||
entry.mood.icon
|
imagePack.icon(forMood: entry.mood)
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: 40, height: 40, alignment: .center)
|
.frame(width: 40, height: 40, alignment: .center)
|
||||||
.foregroundColor(entry.mood.color)
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
.padding(.leading, 5)
|
.padding(.leading, 5)
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
Text(Random.weekdayName(fromDate:entry.forDate!))
|
Text(Random.weekdayName(fromDate:entry.forDate!))
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
Text(" - ")
|
Text(" - ")
|
||||||
.padding([.leading, .trailing], -10)
|
.padding([.leading, .trailing], -10)
|
||||||
Text(Random.dayFormat(fromDate:entry.forDate!))
|
Text(Random.dayFormat(fromDate:entry.forDate!))
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
170
Shared/views/HomeView/HomeViewTwo/HomeViewTwo.swift
Normal file
170
Shared/views/HomeView/HomeViewTwo/HomeViewTwo.swift
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
//
|
||||||
|
// HomeViewTwo.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/18/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct HomeViewTwo: View {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.needsOnboarding.rawValue, store: GroupUserDefaults.groupDefaults) private var needsOnboarding = true
|
||||||
|
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
|
@ObservedObject var viewModel = HomeViewViewModel(addMonthStartWeekdayPadding: true)
|
||||||
|
|
||||||
|
@StateObject private var selectedDetail = StupidAssDetailViewObservableObject()
|
||||||
|
@State private var showingSheet = false
|
||||||
|
@StateObject private var onboardingData = OnboardingDataDataManager.shared
|
||||||
|
|
||||||
|
class StupidAssDetailViewObservableObject: ObservableObject {
|
||||||
|
@Published var fuckingWrapped: MonthDetailView? = nil
|
||||||
|
@Published var showFuckingSheet = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let columns = [
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 400))
|
||||||
|
]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
if viewModel.hasNoData {
|
||||||
|
settingsButtonView
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
EmptyHomeView(viewModel: viewModel)
|
||||||
|
.padding()
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ScrollView {
|
||||||
|
ZStack {
|
||||||
|
topView
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.frame(height: 250)
|
||||||
|
.background(
|
||||||
|
.blue
|
||||||
|
)
|
||||||
|
settingsButtonView
|
||||||
|
}
|
||||||
|
LazyVStack(spacing: 5, pinnedViews: [.sectionHeaders]) {
|
||||||
|
ForEach(viewModel.grouped.sorted(by: { $0.key > $1.key }), id: \.key) { year, months in
|
||||||
|
|
||||||
|
// for reach month
|
||||||
|
ForEach(months.sorted(by: { $0.key > $1.key }), id: \.key) { month, entries in
|
||||||
|
Section() {
|
||||||
|
homeViewTwoMonthListView(month: month, year: year, entries: entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.bottom)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.foregroundColor(
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.padding([.leading, .trailing])
|
||||||
|
}.sheet(isPresented: $selectedDetail.showFuckingSheet,
|
||||||
|
onDismiss: didDismiss) {
|
||||||
|
selectedDetail.fuckingWrapped
|
||||||
|
}
|
||||||
|
.edgesIgnoringSafeArea(.top)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background(
|
||||||
|
theme.currentTheme.bg
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func didDismiss() {
|
||||||
|
selectedDetail.showFuckingSheet = false
|
||||||
|
selectedDetail.fuckingWrapped = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HomeViewTwo {
|
||||||
|
private var topView: some View {
|
||||||
|
VStack {
|
||||||
|
if ShowBasedOnVoteLogics.isMissingCurrentVote(onboardingData: onboardingData.savedOnboardingData) {
|
||||||
|
Text("Vote")
|
||||||
|
}
|
||||||
|
Text("dis top")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var settingsButtonView: some View {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
VStack {
|
||||||
|
Button(action: {
|
||||||
|
showingSheet.toggle()
|
||||||
|
}, label: {
|
||||||
|
Image(systemName: "gear")
|
||||||
|
.foregroundColor(Color(UIColor.darkGray))
|
||||||
|
.font(.system(size: 20))
|
||||||
|
}).sheet(isPresented: $showingSheet) {
|
||||||
|
SettingsView(editedDataClosure: {
|
||||||
|
withAnimation{
|
||||||
|
viewModel.updateData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.padding(.top, 60)
|
||||||
|
.padding(.trailing)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// view that make up the list body
|
||||||
|
extension HomeViewTwo {
|
||||||
|
private func homeViewTwoSectionHeaderView(month: Int, year: Int) -> some View {
|
||||||
|
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func homeViewTwoMonthListView(month: Int, year: Int, entries: [MoodEntry]) -> some View {
|
||||||
|
VStack {
|
||||||
|
homeViewTwoSectionHeaderView(month: month, year: year)
|
||||||
|
Divider()
|
||||||
|
LazyVGrid(columns: columns, spacing: 15) {
|
||||||
|
ForEach(entries, id: \.self) { entry in
|
||||||
|
Circle()
|
||||||
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
|
.frame(minHeight: 5, idealHeight: 20, maxHeight: 50, alignment: .center)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onTapGesture{
|
||||||
|
let deailView = MonthDetailView(monthInt: month,
|
||||||
|
yearInt: year,
|
||||||
|
entries: entries,
|
||||||
|
parentViewModel: viewModel)
|
||||||
|
|
||||||
|
selectedDetail.fuckingWrapped = deailView
|
||||||
|
selectedDetail.showFuckingSheet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HomeViewTwo_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
HomeViewTwo()
|
||||||
|
}
|
||||||
|
}
|
||||||
171
Shared/views/HomeView/HomeViewTwo/MonthDetailView.swift
Normal file
171
Shared/views/HomeView/HomeViewTwo/MonthDetailView.swift
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
//
|
||||||
|
// MonthDetailView.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/18/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MonthDetailView: View {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.deleteEnable.rawValue, store: GroupUserDefaults.groupDefaults) private var deleteEnabled = true
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
|
@State private var showingSheet = false
|
||||||
|
@State private var selectedEntry: MoodEntry?
|
||||||
|
@State private var showingUpdateEntryAlert = false
|
||||||
|
@State private var showUpdateEntryAlert = false
|
||||||
|
|
||||||
|
let monthInt: Int
|
||||||
|
let yearInt: Int
|
||||||
|
@State var entries: [MoodEntry]
|
||||||
|
var parentViewModel: HomeViewViewModel
|
||||||
|
|
||||||
|
let columns = [
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50)),
|
||||||
|
GridItem(.flexible(minimum: 5, maximum: 50))
|
||||||
|
]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
Text("\(Random.monthName(fromMonthInt: monthInt)) \(String(yearInt))")
|
||||||
|
.font(.title)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding()
|
||||||
|
.background(
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
)
|
||||||
|
|
||||||
|
createListView()
|
||||||
|
.padding([.leading, .trailing])
|
||||||
|
.background(
|
||||||
|
theme.currentTheme.bg
|
||||||
|
)
|
||||||
|
|
||||||
|
monthDetails
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.background(
|
||||||
|
theme.currentTheme.secondaryBGColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.alert(HomeViewViewModel.updateTitleHeader(forEntry: selectedEntry),
|
||||||
|
isPresented: $showUpdateEntryAlert) {
|
||||||
|
ForEach(Mood.allValues) { mood in
|
||||||
|
Button(mood.strValue, action: {
|
||||||
|
if let selectedEntry = selectedEntry {
|
||||||
|
PersistenceController.shared.update(entryDate: selectedEntry.forDate!, withModd: mood)
|
||||||
|
}
|
||||||
|
updateEntries()
|
||||||
|
showUpdateEntryAlert = false
|
||||||
|
selectedEntry = nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if let selectedEntry = selectedEntry,
|
||||||
|
deleteEnabled,
|
||||||
|
selectedEntry.mood != .missing {
|
||||||
|
Button(String(localized: "content_view_delete_entry"), action: {
|
||||||
|
updateEntries()
|
||||||
|
PersistenceController.shared.update(entryDate: selectedEntry.forDate!, withModd: .missing)
|
||||||
|
showUpdateEntryAlert = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(String(localized: "content_view_fill_in_missing_entry_cancel"), role: .cancel, action: {
|
||||||
|
updateEntries()
|
||||||
|
selectedEntry = nil
|
||||||
|
showUpdateEntryAlert = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.background(
|
||||||
|
theme.currentTheme.bg
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createListView() -> some View {
|
||||||
|
ScrollView {
|
||||||
|
LazyVGrid(columns: columns, spacing: 25) {
|
||||||
|
ForEach(entries, id: \.self) { entry in
|
||||||
|
listViewEntry(forEntry: entry)
|
||||||
|
.onTapGesture(perform: {
|
||||||
|
if entry.canEdit {
|
||||||
|
selectedEntry = entry
|
||||||
|
showUpdateEntryAlert = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func listViewEntry(forEntry entry: MoodEntry) -> some View {
|
||||||
|
VStack {
|
||||||
|
if entry.mood == .placeholder {
|
||||||
|
Text(" ")
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundColor(Mood.placeholder.color)
|
||||||
|
} else {
|
||||||
|
Text(entry.forDate!,
|
||||||
|
format: Date.FormatStyle().day())
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.mood == .placeholder {
|
||||||
|
Circle()
|
||||||
|
.frame(minWidth: 5,
|
||||||
|
maxWidth: 50,
|
||||||
|
minHeight: 5,
|
||||||
|
maxHeight: 50,
|
||||||
|
alignment: .center)
|
||||||
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
|
} else {
|
||||||
|
entry.mood.icon
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(minWidth: 5,
|
||||||
|
maxWidth: 50,
|
||||||
|
minHeight: 5,
|
||||||
|
maxHeight: 50,
|
||||||
|
alignment: .center)
|
||||||
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateEntries() {
|
||||||
|
parentViewModel.updateData()
|
||||||
|
let (startDate, endDate) = Date.dateRange(monthInt: monthInt, yearInt: yearInt)
|
||||||
|
let updatedEntries = PersistenceController.shared.getData(startDate: startDate, endDate: endDate, includedDays: [1,2,3,4,5,6,7])
|
||||||
|
let padded = MoodEntryFunctions.padMoodEntriesMonth(monthEntries: updatedEntries)
|
||||||
|
entries = padded
|
||||||
|
}
|
||||||
|
|
||||||
|
private var monthDetails: some View {
|
||||||
|
VStack {
|
||||||
|
SmallRollUpHeaderView(entries: entries,
|
||||||
|
viewType: .constant(.total))
|
||||||
|
|
||||||
|
SmallRollUpHeaderView(entries: entries,
|
||||||
|
viewType: .constant(.percentageCircle))
|
||||||
|
.padding(.top, -20)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MonthDetailView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
MonthDetailView(monthInt: 5, yearInt: 2022, entries:
|
||||||
|
PersistenceController.shared.randomEntries(count: 30).sorted(by: {
|
||||||
|
$0.forDate! < $1.forDate!
|
||||||
|
}), parentViewModel: HomeViewViewModel(addMonthStartWeekdayPadding: true))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
class ContentModeViewModel: ObservableObject {
|
class HomeViewViewModel: ObservableObject {
|
||||||
@Published var grouped = [Int: [Int: [MoodEntry]]]()
|
@Published var grouped = [Int: [Int: [MoodEntry]]]()
|
||||||
@Published var numberOfItems = 0
|
@Published var numberOfItems = 0
|
||||||
|
|
||||||
@@ -50,33 +50,7 @@ class ContentModeViewModel: ObservableObject {
|
|||||||
grouped = PersistenceController.shared.splitIntoYearMonth()
|
grouped = PersistenceController.shared.splitIntoYearMonth()
|
||||||
|
|
||||||
if addMonthStartWeekdayPadding {
|
if addMonthStartWeekdayPadding {
|
||||||
var newGrouped = [Int: [Int: [MoodEntry]]]()
|
grouped = MoodEntryFunctions.padMoodEntriesForCalendar(entries: grouped)
|
||||||
|
|
||||||
let allYears = grouped.keys.sorted(by: > )
|
|
||||||
for year in allYears {
|
|
||||||
var newMonth = [Int: [MoodEntry]]()
|
|
||||||
|
|
||||||
let oldMonths = grouped[year]!
|
|
||||||
let monthKeys = oldMonths.keys.sorted(by: > )
|
|
||||||
for key in monthKeys {
|
|
||||||
if let entries = oldMonths[key] {
|
|
||||||
let sortedEntries = entries.sorted(by: { $0.forDate! < $1.forDate! })
|
|
||||||
var mutableEntries = sortedEntries
|
|
||||||
|
|
||||||
if let firstDate = sortedEntries.first {
|
|
||||||
let date = firstDate.forDate!
|
|
||||||
let weekday = Int16(Calendar.current.component(.weekday, from: date))
|
|
||||||
for _ in 1..<weekday {
|
|
||||||
mutableEntries.insert(PersistenceController.shared.generateObjectNotInArray(), at: 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newMonth[key] = mutableEntries
|
|
||||||
}
|
|
||||||
newGrouped[year] = newMonth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grouped = newGrouped
|
|
||||||
}
|
}
|
||||||
|
|
||||||
numberOfItems = numberOfEntries
|
numberOfItems = numberOfEntries
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
//
|
|
||||||
// HomeViewTwo.swift
|
|
||||||
// Feels (iOS)
|
|
||||||
//
|
|
||||||
// Created by Trey Tartt on 2/18/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct HomeViewTwo: View {
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.needsOnboarding.rawValue, store: GroupUserDefaults.groupDefaults) private var needsOnboarding = true
|
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
|
||||||
|
|
||||||
@ObservedObject var viewModel = ContentModeViewModel(addMonthStartWeekdayPadding: true)
|
|
||||||
|
|
||||||
@StateObject private var selectedDetail = StupidAssDetailViewObservableObject()
|
|
||||||
|
|
||||||
class StupidAssDetailViewObservableObject: ObservableObject {
|
|
||||||
@Published var fuckingWrapped: MonthDetailView? = nil
|
|
||||||
@Published var showFuckingSheet = false
|
|
||||||
}
|
|
||||||
|
|
||||||
let columns = [
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 400))
|
|
||||||
]
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ScrollView {
|
|
||||||
topView
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.frame(height: 200)
|
|
||||||
.background(
|
|
||||||
.blue
|
|
||||||
)
|
|
||||||
LazyVStack(spacing: 5, pinnedViews: [.sectionHeaders]) {
|
|
||||||
ForEach(viewModel.grouped.sorted(by: { $0.key > $1.key }), id: \.key) { year, months in
|
|
||||||
|
|
||||||
// for reach month
|
|
||||||
ForEach(months.sorted(by: { $0.key > $1.key }), id: \.key) { month, entries in
|
|
||||||
Section(header: homeViewTwoSectionHeaderView(month: month, year: year)) {
|
|
||||||
homeViewTwoMonthListView(month: month, year: year, entries: entries)
|
|
||||||
}
|
|
||||||
.onTapGesture{
|
|
||||||
let deailView = MonthDetailView(monthInt: month,
|
|
||||||
yearInt: year,
|
|
||||||
entries: entries)
|
|
||||||
|
|
||||||
selectedDetail.fuckingWrapped = deailView
|
|
||||||
selectedDetail.showFuckingSheet = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.bottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding([.leading, .trailing])
|
|
||||||
}.sheet(isPresented: $selectedDetail.showFuckingSheet,
|
|
||||||
onDismiss: didDismiss) {
|
|
||||||
selectedDetail.fuckingWrapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func didDismiss() {
|
|
||||||
selectedDetail.showFuckingSheet = false
|
|
||||||
selectedDetail.fuckingWrapped = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension HomeViewTwo {
|
|
||||||
private var topView: some View {
|
|
||||||
HStack {
|
|
||||||
Text("dis top")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// view that make up the list body
|
|
||||||
extension HomeViewTwo {
|
|
||||||
private func homeViewTwoSectionHeaderView(month: Int, year: Int) -> some View {
|
|
||||||
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
|
|
||||||
.font(.body)
|
|
||||||
.foregroundColor(Color(UIColor.label))
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.background(
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func homeViewTwoMonthListView(month: Int, year: Int, entries: [MoodEntry]) -> some View {
|
|
||||||
LazyVGrid(columns: columns, spacing: 15) {
|
|
||||||
ForEach(entries, id: \.self) { entry in
|
|
||||||
Circle()
|
|
||||||
.foregroundColor(entry.mood.color)
|
|
||||||
.frame(minHeight: 5, idealHeight: 20, maxHeight: 50, alignment: .center)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HomeViewTwo_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
HomeViewTwo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
//
|
|
||||||
// MonthDetailView.swift
|
|
||||||
// Feels (iOS)
|
|
||||||
//
|
|
||||||
// Created by Trey Tartt on 2/18/22.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct MonthDetailView: View {
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.deleteEnable.rawValue, store: GroupUserDefaults.groupDefaults) private var deleteEnabled = true
|
|
||||||
|
|
||||||
@State private var showingUpdateEntryAlert = false
|
|
||||||
|
|
||||||
let monthInt: Int
|
|
||||||
let yearInt: Int
|
|
||||||
let entries: [MoodEntry]
|
|
||||||
|
|
||||||
lazy var dateFormatter: DateFormatter = {
|
|
||||||
let dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = "dd"
|
|
||||||
return dateFormatter
|
|
||||||
}()
|
|
||||||
|
|
||||||
let columns = [
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50)),
|
|
||||||
GridItem(.flexible(minimum: 5, maximum: 50))
|
|
||||||
]
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack {
|
|
||||||
Text("\(Random.monthName(fromMonthInt: monthInt)) \(String(yearInt))")
|
|
||||||
.font(.title)
|
|
||||||
.foregroundColor(Color(UIColor.label))
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.padding()
|
|
||||||
.background(
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
)
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
LazyVGrid(columns: columns, spacing: 25) {
|
|
||||||
ForEach(entries, id: \.self) { entry in
|
|
||||||
VStack {
|
|
||||||
if entry.mood != .placeholder {
|
|
||||||
Text(entry.forDate!,
|
|
||||||
format: Date.FormatStyle().day())
|
|
||||||
.font(.title3)
|
|
||||||
.foregroundColor(Color(UIColor.label))
|
|
||||||
|
|
||||||
entry.mood.icon
|
|
||||||
.resizable()
|
|
||||||
.frame(minWidth: 5,
|
|
||||||
maxWidth: 50,
|
|
||||||
minHeight: 5,
|
|
||||||
maxHeight: 50,
|
|
||||||
alignment: .center)
|
|
||||||
.aspectRatio(contentMode: .fit)
|
|
||||||
.foregroundColor(entry.mood.color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.alert(ContentModeViewModel.updateTitleHeader(forEntry: entry),
|
|
||||||
isPresented: $showingUpdateEntryAlert) {
|
|
||||||
ForEach(Mood.allValues) { mood in
|
|
||||||
Button(mood.strValue, action: {
|
|
||||||
PersistenceController.shared.update(entryDate: entry.forDate!, withModd: mood)
|
|
||||||
// viewModel.update(entry: selectedEntry, toMood: mood)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if deleteEnabled,
|
|
||||||
entry.mood != .missing {
|
|
||||||
Button(String(localized: "content_view_delete_entry"), action: {
|
|
||||||
PersistenceController.shared.update(entryDate: entry.forDate!, withModd: Mood.missing)
|
|
||||||
// viewModel.update(entry: selectedEntry, toMood: Mood.missing)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(String(localized: "content_view_fill_in_missing_entry_cancel"), role: .cancel, action: {
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding([.leading, .trailing])
|
|
||||||
|
|
||||||
monthDetails
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.background(
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var monthDetails: some View {
|
|
||||||
VStack {
|
|
||||||
SmallRollUpHeaderView(entries: entries,
|
|
||||||
viewType: .constant(.total))
|
|
||||||
|
|
||||||
SmallRollUpHeaderView(entries: entries,
|
|
||||||
viewType: .constant(.percentageCircle))
|
|
||||||
.padding(.top, -20)
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MonthDetailView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
MonthDetailView(monthInt: 5, yearInt: 2022, entries:
|
|
||||||
PersistenceController.shared.randomEntries(count: 30).sorted(by: {
|
|
||||||
$0.forDate! < $1.forDate!
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@ struct MainTabView: View {
|
|||||||
TabView {
|
TabView {
|
||||||
HomeViewTwo()
|
HomeViewTwo()
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Label(String(localized: "content_view_tab_main"), systemImage: "list.dash")
|
Label(String(localized: "content_view_tab_main"), systemImage: "calendar")
|
||||||
}
|
}
|
||||||
|
|
||||||
HomeView()
|
HomeView()
|
||||||
@@ -26,13 +26,18 @@ struct MainTabView: View {
|
|||||||
|
|
||||||
FilterView()
|
FilterView()
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Label(String(localized: "content_view_tab_filter"), systemImage: "calendar.circle")
|
Label(String(localized: "content_view_tab_filter"), systemImage: "line.3.horizontal.decrease.circle")
|
||||||
}
|
}
|
||||||
|
|
||||||
SharingListView()
|
SharingListView()
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Label(String(localized: "content_view_tab_share"), systemImage: "square.and.arrow.up")
|
Label(String(localized: "content_view_tab_share"), systemImage: "square.and.arrow.up")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomizeView()
|
||||||
|
.tabItem {
|
||||||
|
Label(String(localized: "content_view_tab_customize"), systemImage: "pencil")
|
||||||
|
}
|
||||||
}.sheet(isPresented: $needsOnboarding, onDismiss: {
|
}.sheet(isPresented: $needsOnboarding, onDismiss: {
|
||||||
|
|
||||||
}, content: {
|
}, content: {
|
||||||
|
|||||||
@@ -12,13 +12,11 @@ struct SettingsView: View {
|
|||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
let editedDataClosure: (() -> Void)
|
let editedDataClosure: (() -> Void)
|
||||||
let updateBoardingDataClosure: ((OnboardingData) -> Void)
|
|
||||||
|
|
||||||
@State private var showOnboarding = false
|
@State private var showOnboarding = false
|
||||||
|
|
||||||
@State private var showSpecialThanks = false
|
@State private var showSpecialThanks = false
|
||||||
@State private var showWhyBGMode = false
|
@State private var showWhyBGMode = false
|
||||||
@State private var showCreateCustomWidget = false
|
|
||||||
@ObservedObject var syncMonitor = SyncMonitor.shared
|
@ObservedObject var syncMonitor = SyncMonitor.shared
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.useCloudKit.rawValue, store: GroupUserDefaults.groupDefaults) private var useCloudKit = false
|
@AppStorage(UserDefaultsStore.Keys.useCloudKit.rawValue, store: GroupUserDefaults.groupDefaults) private var useCloudKit = false
|
||||||
@@ -34,9 +32,6 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
cloudKitEnable
|
cloudKitEnable
|
||||||
canDelete
|
canDelete
|
||||||
changeIcon
|
|
||||||
themePicker
|
|
||||||
createCustomWidget
|
|
||||||
showOnboardingButton
|
showOnboardingButton
|
||||||
whyBackgroundMode
|
whyBackgroundMode
|
||||||
specialThanksCell
|
specialThanksCell
|
||||||
@@ -56,13 +51,10 @@ struct SettingsView: View {
|
|||||||
}.sheet(isPresented: $showOnboarding) {
|
}.sheet(isPresented: $showOnboarding) {
|
||||||
OnboardingMain(onboardingData: UserDefaultsStore.getOnboarding(),
|
OnboardingMain(onboardingData: UserDefaultsStore.getOnboarding(),
|
||||||
updateBoardingDataClosure: { onboardingData in
|
updateBoardingDataClosure: { onboardingData in
|
||||||
updateBoardingDataClosure(onboardingData)
|
OnboardingDataDataManager.shared.updateOnboardingData(onboardingData: onboardingData)
|
||||||
showOnboarding = false
|
showOnboarding = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $showCreateCustomWidget) {
|
|
||||||
CreateIconView()
|
|
||||||
}
|
|
||||||
.background(
|
.background(
|
||||||
theme.currentTheme.bg
|
theme.currentTheme.bg
|
||||||
.edgesIgnoringSafeArea(.all)
|
.edgesIgnoringSafeArea(.all)
|
||||||
@@ -84,7 +76,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var specialThanksCell: some View {
|
private var specialThanksCell: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
VStack {
|
VStack {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
withAnimation{
|
withAnimation{
|
||||||
@@ -107,7 +99,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var addTestDataCell: some View {
|
private var addTestDataCell: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
Button(action: {
|
Button(action: {
|
||||||
PersistenceController.shared.populateTestData()
|
PersistenceController.shared.populateTestData()
|
||||||
editedDataClosure()
|
editedDataClosure()
|
||||||
@@ -122,7 +114,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var clearDB: some View {
|
private var clearDB: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
Button(action: {
|
Button(action: {
|
||||||
PersistenceController.shared.clearDB()
|
PersistenceController.shared.clearDB()
|
||||||
editedDataClosure()
|
editedDataClosure()
|
||||||
@@ -137,7 +129,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var whyBackgroundMode: some View {
|
private var whyBackgroundMode: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
VStack {
|
VStack {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
withAnimation{
|
withAnimation{
|
||||||
@@ -157,51 +149,13 @@ struct SettingsView: View {
|
|||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
}
|
}
|
||||||
|
|
||||||
let iconSets: [(String,String)] = [
|
|
||||||
("PurpleFeelsAppIcon", "PurpleAppIcon"),
|
|
||||||
("RedFeelsAppIcon", "RedAppIcon")
|
|
||||||
]
|
|
||||||
|
|
||||||
private var changeIcon: some View {
|
|
||||||
ZStack {
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
VStack {
|
|
||||||
Text(String(localized: "settings_view_change_icon"))
|
|
||||||
HStack {
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
UIApplication.shared.setAlternateIconName(nil)
|
|
||||||
}, label: {
|
|
||||||
Image("FeelsAppIcon", bundle: .main)
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 50, height:50)
|
|
||||||
.cornerRadius(10)
|
|
||||||
})
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
ForEach(iconSets, id: \.self.0){ iconSet in
|
|
||||||
Button(action: {
|
|
||||||
UIApplication.shared.setAlternateIconName(iconSet.1) { (error) in
|
|
||||||
// FIXME: Handle error
|
|
||||||
}
|
|
||||||
}, label: {
|
|
||||||
Image(iconSet.0, bundle: .main)
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 50, height:50)
|
|
||||||
.cornerRadius(10)
|
|
||||||
})
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
|
||||||
}
|
|
||||||
|
|
||||||
private var showOnboardingButton: some View {
|
private var showOnboardingButton: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
Button(action: {
|
Button(action: {
|
||||||
showOnboarding.toggle()
|
showOnboarding.toggle()
|
||||||
}, label: {
|
}, label: {
|
||||||
@@ -215,7 +169,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var cloudKitEnable: some View {
|
private var cloudKitEnable: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
VStack {
|
VStack {
|
||||||
Toggle(String(localized: "settings_use_cloudkit_title"),
|
Toggle(String(localized: "settings_use_cloudkit_title"),
|
||||||
isOn: $useCloudKit)
|
isOn: $useCloudKit)
|
||||||
@@ -233,7 +187,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var cloudKitStatus: some View {
|
private var cloudKitStatus: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
VStack {
|
VStack {
|
||||||
Image(systemName: syncMonitor.syncStateSummary.symbolName)
|
Image(systemName: syncMonitor.syncStateSummary.symbolName)
|
||||||
.foregroundColor(syncMonitor.syncStateSummary.symbolColor)
|
.foregroundColor(syncMonitor.syncStateSummary.symbolColor)
|
||||||
@@ -247,7 +201,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
private var canDelete: some View {
|
private var canDelete: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
VStack {
|
VStack {
|
||||||
Toggle(String(localized: "settings_use_delete_enable"),
|
Toggle(String(localized: "settings_use_delete_enable"),
|
||||||
isOn: $deleteEnabled)
|
isOn: $deleteEnabled)
|
||||||
@@ -257,65 +211,16 @@ struct SettingsView: View {
|
|||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
}
|
}
|
||||||
|
|
||||||
private var themePicker: some View {
|
|
||||||
ZStack {
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
VStack {
|
|
||||||
Text(String(localized: "settings_background_title"))
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
ForEach(Theme.allCases, id:\.rawValue) { aTheme in
|
|
||||||
Button(action: {
|
|
||||||
theme = aTheme
|
|
||||||
}, label: {
|
|
||||||
VStack {
|
|
||||||
aTheme.currentTheme.preview
|
|
||||||
.overlay(
|
|
||||||
Circle()
|
|
||||||
.stroke(Color(UIColor.systemGray), style: StrokeStyle(lineWidth: 2))
|
|
||||||
)
|
|
||||||
Text(aTheme.title)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.top)
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
|
||||||
}
|
|
||||||
|
|
||||||
private var createCustomWidget: some View {
|
|
||||||
ZStack {
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
Button(action: {
|
|
||||||
showCreateCustomWidget = true
|
|
||||||
}, label: {
|
|
||||||
Text("Create Custom Widget")
|
|
||||||
})
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SettingsView_Previews: PreviewProvider {
|
struct SettingsView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
SettingsView(editedDataClosure: {
|
SettingsView(editedDataClosure: {
|
||||||
|
|
||||||
}, updateBoardingDataClosure: { _ in
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
SettingsView(editedDataClosure: {
|
SettingsView(editedDataClosure: {
|
||||||
|
|
||||||
}, updateBoardingDataClosure: { _ in
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.preferredColorScheme(.dark)
|
.preferredColorScheme(.dark)
|
||||||
}
|
}
|
||||||
@@ -71,13 +71,13 @@ struct SharingListView: View {
|
|||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
WrappedSharable(preview: AnyView(
|
WrappedSharable(preview: AnyView(
|
||||||
MonthTotalTemplate(isPreview: true,
|
MonthTotalTemplate(isPreview: true,
|
||||||
startDate: Date().startOfMonth(),
|
startDate: Date().startOfMonth,
|
||||||
endDate: Date().endOfMonth(),
|
endDate: Date().endOfMonth,
|
||||||
fakeData: false)
|
fakeData: false)
|
||||||
), destination: AnyView(
|
), destination: AnyView(
|
||||||
MonthTotalTemplate(isPreview: false,
|
MonthTotalTemplate(isPreview: false,
|
||||||
startDate: Date().startOfMonth(),
|
startDate: Date().startOfMonth,
|
||||||
endDate: Date().endOfMonth(),
|
endDate: Date().endOfMonth,
|
||||||
fakeData: false)
|
fakeData: false)
|
||||||
), description: MonthTotalTemplate.description),
|
), description: MonthTotalTemplate.description),
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
@@ -93,7 +93,7 @@ struct SharingListView: View {
|
|||||||
Text(String(format: String(localized: "Share your shit")))
|
Text(String(format: String(localized: "Share your shit")))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.padding([.top, .leading])
|
.padding([.top, .leading])
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ struct SharingListView: View {
|
|||||||
selectedShare.showFuckingSheet = true
|
selectedShare.showFuckingSheet = true
|
||||||
}, label: {
|
}, label: {
|
||||||
ZStack {
|
ZStack {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
|
|
||||||
item.preview
|
item.preview
|
||||||
.frame(height: 88)
|
.frame(height: 88)
|
||||||
@@ -113,7 +113,7 @@ struct SharingListView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
Text(item.description)
|
Text(item.description)
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.frame(minWidth: 0, maxWidth: .infinity)
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
.frame(height: 44)
|
.frame(height: 44)
|
||||||
@@ -19,6 +19,8 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
|
|
||||||
@State var showSharingTemplate = false
|
@State var showSharingTemplate = false
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
private var entries = [MoodMetrics]()
|
private var entries = [MoodMetrics]()
|
||||||
|
|
||||||
@@ -41,16 +43,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
totalEntryCount = moodEntries?.count ?? 0
|
totalEntryCount = moodEntries?.count ?? 0
|
||||||
|
|
||||||
if let moodEntries = moodEntries {
|
if let moodEntries = moodEntries {
|
||||||
for (_, mood) in Mood.allValues.enumerated() {
|
entries = Random.createTotalPerc(fromEntries: moodEntries)
|
||||||
|
|
||||||
let moodEntries = moodEntries.filter({
|
|
||||||
Int($0.moodValue) == mood.rawValue
|
|
||||||
})
|
|
||||||
let total = moodEntries.count
|
|
||||||
let perc = (Float(total) / Float(totalEntryCount)) * 100
|
|
||||||
entries.append(MoodMetrics(mood: mood, total: total, percent: perc))
|
|
||||||
}
|
|
||||||
|
|
||||||
entries = entries.sorted(by: {
|
entries = entries.sorted(by: {
|
||||||
$0.percent > $1.percent
|
$0.percent > $1.percent
|
||||||
})
|
})
|
||||||
@@ -78,7 +71,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
mood.icon
|
mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.foregroundColor(mood.color)
|
.foregroundColor(moodTint.color(forMood: mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +79,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
HStack {
|
HStack {
|
||||||
ForEach(entries.prefix(2), id: \.mood) { model in
|
ForEach(entries.prefix(2), id: \.mood) { model in
|
||||||
ZStack {
|
ZStack {
|
||||||
Circle().fill(model.mood.color)
|
Circle().fill(moodTint.color(forMood: model.mood))
|
||||||
|
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
@@ -104,7 +97,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
HStack {
|
HStack {
|
||||||
ForEach(entries.suffix(3), id: \.mood) { model in
|
ForEach(entries.suffix(3), id: \.mood) { model in
|
||||||
ZStack {
|
ZStack {
|
||||||
Circle().fill(model.mood.color)
|
Circle().fill(moodTint.color(forMood: model.mood))
|
||||||
|
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
@@ -124,7 +117,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
HStack {
|
HStack {
|
||||||
ForEach(entries, id: \.mood) { model in
|
ForEach(entries, id: \.mood) { model in
|
||||||
ZStack {
|
ZStack {
|
||||||
Circle().fill(model.mood.color)
|
Circle().fill(moodTint.color(forMood: model.mood))
|
||||||
|
|
||||||
Text("\(model.total)")
|
Text("\(model.total)")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
@@ -144,7 +137,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
VStack {
|
VStack {
|
||||||
Text(String(format: String(localized: "share_view_all_moods_total_template_title"), totalEntryCount))
|
Text(String(format: String(localized: "share_view_all_moods_total_template_title"), totalEntryCount))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
@@ -203,7 +196,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
|
|||||||
.padding([.leading, .trailing], -20)
|
.padding([.leading, .trailing], -20)
|
||||||
} else {
|
} else {
|
||||||
mainView
|
mainView
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing, .top])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ struct CurrentStreakTemplate: View, SharingTemplate {
|
|||||||
|
|
||||||
@State var showSharingTemplate = false
|
@State var showSharingTemplate = false
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
let columns = [
|
let columns = [
|
||||||
GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center),
|
GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center),
|
||||||
@@ -60,7 +61,7 @@ struct CurrentStreakTemplate: View, SharingTemplate {
|
|||||||
entry.mood.icon
|
entry.mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.foregroundColor(entry.mood.color)
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ struct CurrentStreakTemplate: View, SharingTemplate {
|
|||||||
VStack {
|
VStack {
|
||||||
Text(String(format: String(localized: "share_view_current_streak_template_title")))
|
Text(String(format: String(localized: "share_view_current_streak_template_title")))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding(.top)
|
.padding(.top)
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ struct CurrentStreakTemplate: View, SharingTemplate {
|
|||||||
entry.mood.icon
|
entry.mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.foregroundColor(entry.mood.color)
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +142,8 @@ struct CurrentStreakTemplate: View, SharingTemplate {
|
|||||||
.padding([.leading, .trailing], -20)
|
.padding([.leading, .trailing], -20)
|
||||||
} else {
|
} else {
|
||||||
mainView
|
mainView
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing, .top])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ struct LongestStreakTemplate: View, SharingTemplate {
|
|||||||
|
|
||||||
@State var showSharingTemplate = false
|
@State var showSharingTemplate = false
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
let columns = [
|
let columns = [
|
||||||
GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center),
|
GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center),
|
||||||
@@ -96,7 +97,7 @@ struct LongestStreakTemplate: View, SharingTemplate {
|
|||||||
entry.mood.icon
|
entry.mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.foregroundColor(entry.mood.color)
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,26 +113,26 @@ struct LongestStreakTemplate: View, SharingTemplate {
|
|||||||
VStack {
|
VStack {
|
||||||
Text(String(format: String(localized: "share_view_longest_streak_template_title"), self.selectedMood.strValue))
|
Text(String(format: String(localized: "share_view_longest_streak_template_title"), self.selectedMood.strValue))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text(self.moodEntries.first?.forDate ?? Date(), formatter: itemFormatter)
|
Text(self.moodEntries.first?.forDate ?? Date(), formatter: itemFormatter)
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding(.top, 1)
|
.padding(.top, 1)
|
||||||
|
|
||||||
Text("-")
|
Text("-")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding(.top, 1)
|
.padding(.top, 1)
|
||||||
|
|
||||||
Text(self.moodEntries.last?.forDate ?? Date(), formatter: itemFormatter)
|
Text(self.moodEntries.last?.forDate ?? Date(), formatter: itemFormatter)
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding(.top, 1)
|
.padding(.top, 1)
|
||||||
}
|
}
|
||||||
@@ -144,7 +145,7 @@ struct LongestStreakTemplate: View, SharingTemplate {
|
|||||||
entry.mood.icon
|
entry.mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.foregroundColor(entry.mood.color)
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +225,8 @@ struct LongestStreakTemplate: View, SharingTemplate {
|
|||||||
.padding([.leading, .trailing], -20)
|
.padding([.leading, .trailing], -20)
|
||||||
} else {
|
} else {
|
||||||
mainView
|
mainView
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing, .top])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ struct MonthTotalTemplate: View, SharingTemplate {
|
|||||||
|
|
||||||
@State var showSharingTemplate = false
|
@State var showSharingTemplate = false
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
private var moodMetrics = [MoodMetrics]()
|
private var moodMetrics = [MoodMetrics]()
|
||||||
private var moodEntries = [MoodEntry]()
|
private var moodEntries = [MoodEntry]()
|
||||||
@@ -59,16 +61,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
|
|||||||
moodEntries = _moodEntries ?? [MoodEntry]()
|
moodEntries = _moodEntries ?? [MoodEntry]()
|
||||||
|
|
||||||
totalEntryCount = moodEntries.count
|
totalEntryCount = moodEntries.count
|
||||||
|
moodMetrics = Random.createTotalPerc(fromEntries: moodEntries)
|
||||||
for (_, mood) in Mood.allValues.enumerated() {
|
|
||||||
let moodEntries = moodEntries.filter({
|
|
||||||
Int($0.moodValue) == mood.rawValue
|
|
||||||
})
|
|
||||||
let total = moodEntries.count
|
|
||||||
let perc = (Float(total) / Float(totalEntryCount)) * 100
|
|
||||||
moodMetrics.append(MoodMetrics(mood: mood, total: total, percent: perc))
|
|
||||||
}
|
|
||||||
|
|
||||||
moodMetrics = moodMetrics.sorted(by: {
|
moodMetrics = moodMetrics.sorted(by: {
|
||||||
$0.mood.rawValue > $1.mood.rawValue
|
$0.mood.rawValue > $1.mood.rawValue
|
||||||
})
|
})
|
||||||
@@ -89,7 +82,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
|
|||||||
HStack {
|
HStack {
|
||||||
ForEach(moodMetrics, id: \.mood) { model in
|
ForEach(moodMetrics, id: \.mood) { model in
|
||||||
ZStack {
|
ZStack {
|
||||||
Circle().fill(model.mood.color)
|
Circle().fill(moodTint.color(forMood: model.mood))
|
||||||
|
|
||||||
Text("\(model.percent, specifier: "%.0f")%")
|
Text("\(model.percent, specifier: "%.0f")%")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
@@ -109,7 +102,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
|
|||||||
VStack {
|
VStack {
|
||||||
Text(String(format: String(localized: "share_view_month_moods_total_template_title"), Random.monthName(fromMonthInt: month), moodEntries.count))
|
Text(String(format: String(localized: "share_view_month_moods_total_template_title"), Random.monthName(fromMonthInt: month), moodEntries.count))
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.foregroundColor(Color(UIColor.label))
|
.foregroundColor(theme.currentTheme.labelColor)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
@@ -119,7 +112,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
|
|||||||
entry.mood.icon
|
entry.mood.icon
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.foregroundColor(entry.mood.color)
|
.foregroundColor(moodTint.color(forMood: entry.mood))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,15 +172,15 @@ struct MonthTotalTemplate: View, SharingTemplate {
|
|||||||
.padding([.leading, .trailing], -20)
|
.padding([.leading, .trailing], -20)
|
||||||
} else {
|
} else {
|
||||||
mainView
|
mainView
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing, .top])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MonthTotalTemplate_Previews: PreviewProvider {
|
struct MonthTotalTemplate_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
MonthTotalTemplate(isPreview: true, startDate: Date().startOfMonth(), endDate: Date().endOfMonth(), fakeData: true)
|
MonthTotalTemplate(isPreview: true, startDate: Date().startOfMonth, endDate: Date().endOfMonth, fakeData: true)
|
||||||
|
|
||||||
MonthTotalTemplate(isPreview: false, startDate: Date().startOfMonth(), endDate: Date().endOfMonth(), fakeData: true)
|
MonthTotalTemplate(isPreview: false, startDate: Date().startOfMonth, endDate: Date().endOfMonth, fakeData: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import SwiftUI
|
|||||||
|
|
||||||
struct SmallRollUpHeaderView: View {
|
struct SmallRollUpHeaderView: View {
|
||||||
@Binding var viewType: MainSwitchableViewType
|
@Binding var viewType: MainSwitchableViewType
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
let entries: [MoodEntry]
|
let entries: [MoodEntry]
|
||||||
private var moodMetrics = [MoodGroupingMetrics]()
|
private var moodMetrics = [MoodMetrics]()
|
||||||
|
|
||||||
init(entries: [MoodEntry], viewType: Binding<MainSwitchableViewType>) {
|
init(entries: [MoodEntry], viewType: Binding<MainSwitchableViewType>) {
|
||||||
self.entries = entries
|
self.entries = entries
|
||||||
@@ -20,7 +21,7 @@ struct SmallRollUpHeaderView: View {
|
|||||||
moodMetrics = Random.createTotalPerc(fromEntries: entries)
|
moodMetrics = Random.createTotalPerc(fromEntries: entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func textView(forModel model: MoodGroupingMetrics) -> Text {
|
private func textView(forModel model: MoodMetrics) -> Text {
|
||||||
switch viewType {
|
switch viewType {
|
||||||
case .total:
|
case .total:
|
||||||
return Text(String(model.total))
|
return Text(String(model.total))
|
||||||
@@ -32,24 +33,25 @@ struct SmallRollUpHeaderView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var textViews: some View {
|
private var textViews: some View {
|
||||||
HStack {
|
HStack() {
|
||||||
ForEach(moodMetrics, id: \.0) { model in
|
ForEach(moodMetrics, id: \.id) { model in
|
||||||
textView(forModel: model)
|
textView(forModel: model)
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.foregroundColor(model.mood.color)
|
.foregroundColor(moodTint.color(forMood: model.mood))
|
||||||
.frame(width: 70, height: 70)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.padding([.top, .bottom])
|
.padding([.top, .bottom])
|
||||||
}
|
}
|
||||||
|
|
||||||
private var circularViews: some View {
|
private var circularViews: some View {
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(moodMetrics, id: \.0) { model in
|
ForEach(moodMetrics, id: \.id) { model in
|
||||||
ZStack {
|
ZStack {
|
||||||
Circle().fill(model.mood.color)
|
Circle().fill(moodTint.color(forMood: model.mood))
|
||||||
.frame(minWidth: 5,
|
.frame(minWidth: 5,
|
||||||
maxWidth: 70,
|
maxWidth: 70,
|
||||||
minHeight: 5,
|
minHeight: 5,
|
||||||
@@ -60,9 +62,9 @@ struct SmallRollUpHeaderView: View {
|
|||||||
.font(.title3)
|
.font(.title3)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.clipShape(ContainerRelativeShape()).padding()
|
.clipShape(ContainerRelativeShape())
|
||||||
.foregroundColor(Color(UIColor.white))
|
.foregroundColor(Color(UIColor.white))
|
||||||
.minimumScaleFactor(0.1)
|
.minimumScaleFactor(0.7)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,8 +96,13 @@ struct SmallHeaderView_Previews: PreviewProvider {
|
|||||||
viewType: .constant(.total))
|
viewType: .constant(.total))
|
||||||
|
|
||||||
SmallRollUpHeaderView(entries: PersistenceController.shared.randomEntries(count: 10),
|
SmallRollUpHeaderView(entries: PersistenceController.shared.randomEntries(count: 10),
|
||||||
viewType: .constant(.total))
|
viewType: .constant(.percentageCircle))
|
||||||
.frame(height: 20)
|
.background(.gray)
|
||||||
|
|
||||||
|
SmallRollUpHeaderView(entries: PersistenceController.shared.randomEntries(count: 10),
|
||||||
|
viewType: .constant(.percentage))
|
||||||
|
|
||||||
|
.background(.gray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ struct SwitchableView: View {
|
|||||||
let daysBack: Int
|
let daysBack: Int
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
|
||||||
|
|
||||||
init(daysBack: Int, viewType: Binding<MainSwitchableViewType>, headerTypeChanged: @escaping ((MainSwitchableViewType) -> Void)) {
|
init(daysBack: Int, viewType: Binding<MainSwitchableViewType>, headerTypeChanged: @escaping ((MainSwitchableViewType) -> Void)) {
|
||||||
self.daysBack = daysBack
|
self.daysBack = daysBack
|
||||||
self.headerTypeChanged = headerTypeChanged
|
self.headerTypeChanged = headerTypeChanged
|
||||||
@@ -40,7 +41,7 @@ struct SwitchableView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
switch viewType {
|
switch viewType {
|
||||||
case .total:
|
case .total:
|
||||||
HeaderStatsView(fakeData: false, backDays: daysBack)
|
HeaderStatsView(fakeData: false, backDays: daysBack, moodTint: moodTint)
|
||||||
.padding([.leading, .trailing], -15)
|
.padding([.leading, .trailing], -15)
|
||||||
.padding([.top, .bottom], 8)
|
.padding([.top, .bottom], 8)
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
@@ -75,7 +76,7 @@ struct SwitchableView: View {
|
|||||||
.padding(.top, -12)
|
.padding(.top, -12)
|
||||||
}
|
}
|
||||||
.background(
|
.background(
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
theme.currentTheme.secondaryBGColor
|
||||||
)
|
)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"content_view_tab_main" = "Main";
|
"content_view_tab_main" = "Main";
|
||||||
"content_view_tab_filter" = "Filter";
|
"content_view_tab_filter" = "Filter";
|
||||||
"content_view_tab_share" = "Share";
|
"content_view_tab_share" = "Share";
|
||||||
|
"content_view_tab_customize" = "Customize";
|
||||||
"content_view_fill_in_missing_entry" = "Update %@";
|
"content_view_fill_in_missing_entry" = "Update %@";
|
||||||
"content_view_fill_in_missing_entry_cancel" = "Cancel";
|
"content_view_fill_in_missing_entry_cancel" = "Cancel";
|
||||||
"content_view_delete_entry" = "Delete this entry";
|
"content_view_delete_entry" = "Delete this entry";
|
||||||
@@ -70,3 +71,5 @@
|
|||||||
"share_view_month_moods_total_template_title" = "Total Entries for %@ - %d";
|
"share_view_month_moods_total_template_title" = "Total Entries for %@ - %d";
|
||||||
"share_view_current_streak_template_title" = "Last 10 Days";
|
"share_view_current_streak_template_title" = "Last 10 Days";
|
||||||
"share_view_longest_streak_template_title" = "Longest consecutive days I was %@";
|
"share_view_longest_streak_template_title" = "Longest consecutive days I was %@";
|
||||||
|
|
||||||
|
"customize_view_title" = "Make ifeel yours!!!";
|
||||||
|
|||||||
Reference in New Issue
Block a user