everything changed

This commit is contained in:
Trey t
2022-02-20 14:33:58 -06:00
parent 1cf38cb854
commit 0035f61204
50 changed files with 2155 additions and 875 deletions

View File

@@ -7,12 +7,27 @@
objects = {
/* Begin PBXBuildFile section */
1C02589C27B9677A00EB91AC /* CreateIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C02589B27B9677A00EB91AC /* CreateIconView.swift */; };
1C02589E27B9821700EB91AC /* CenterTiledImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C02589D27B9821700EB91AC /* CenterTiledImage.swift */; };
1C02589C27B9677A00EB91AC /* CreateWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C02589B27B9677A00EB91AC /* CreateWidgetView.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 */; };
1C10E24E27A1AB110047948B /* UserDefaultsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */; };
1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.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 */; };
1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C2618FD27960A4F00FDC148 /* FilterViewModel.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 */; };
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C744F2B278CE15600953A57 /* AppDelegate.swift */; };
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 */; };
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA03774279A294800D26164 /* OnboardingDay.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 */; };
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90AEB278C7DDF001C4FEA /* Feels.xcdatamodeld */; };
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B75278C8119001C4FEA /* LocalNotification.swift */; };
1CEC966F27B9C29300CC8688 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* IconView.swift */; };
1CEC967127B9C2BB00CC8688 /* CustomIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */; };
1CEC967227B9C9FB00CC8688 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* IconView.swift */; };
1CEC967327B9CA0C00CC8688 /* CustomIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */; };
1CEC966F27B9C29300CC8688 /* CustomWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */; };
1CEC967127B9C2BB00CC8688 /* CustomWidgetModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */; };
1CEC967227B9C9FB00CC8688 /* CustomWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */; };
1CEC967327B9CA0C00CC8688 /* CustomWidgetModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -149,10 +164,17 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1C02589B27B9677A00EB91AC /* CreateIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateIconView.swift; sourceTree = "<group>"; };
1C02589D27B9821700EB91AC /* CenterTiledImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CenterTiledImage.swift; sourceTree = "<group>"; };
1C02589B27B9677A00EB91AC /* CreateWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CreateWidgetView.swift; path = ../CustomIcon/CreateWidgetView.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>"; };
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>"; };
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>"; };
@@ -179,7 +201,7 @@
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>"; };
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>"; };
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>"; };
@@ -230,8 +252,8 @@
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>"; };
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>"; };
1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomIcon.swift; sourceTree = "<group>"; };
1CEC966E27B9C29300CC8688 /* CustomWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomWidgetView.swift; sourceTree = "<group>"; };
1CEC967027B9C2BB00CC8688 /* CustomWidgetModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomWidgetModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -279,6 +301,68 @@
/* End PBXFrameworksBuildPhase 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 */ = {
isa = PBXGroup;
children = (
@@ -317,8 +401,8 @@
1C4FF3C627BEE09E00BE8F34 /* PersistenceADD.swift */,
1C4FF3C227BEE07200BE8F34 /* PersistenceDELETE.swift */,
1C4FF3BF27BEE06900BE8F34 /* PersistenceGET.swift */,
1C4FF3BD27BEDF9100BE8F34 /* PersistenceHelper.swift */,
1C658D7627C0744D003231EE /* PersistenceUPDATE.swift */,
1C4FF3BD27BEDF9100BE8F34 /* PersistenceHelper.swift */,
);
path = Persisence;
sourceTree = "<group>";
@@ -350,18 +434,19 @@
1C358FB927B35252002C83A6 /* ActivityViewController.swift */,
1CAD602F27A5C1C800C520BD /* AddMoodHeaderView.swift */,
1CAD603127A5C1C800C520BD /* BGView.swift */,
1C02589B27B9677A00EB91AC /* CreateIconView.swift */,
1C04489027C2CAAC00D22444 /* CustomIcon */,
1C04489227C2CAB700D22444 /* CustomizeView */,
1C04489127C2CAB100D22444 /* CustomWidget */,
1CC469AB27907D48003E0C6E /* DayChartView.swift */,
1CB101C427B62A2D00D1C033 /* EmptyView.swift */,
1CAD602E27A5C1C800C520BD /* FilterView.swift */,
1C04489427C2CAD100D22444 /* FilterView */,
1CAD602D27A5C1C800C520BD /* GraphView.swift */,
1CAD603027A5C1C800C520BD /* HeaderPercView.swift */,
1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */,
1CAD603227A5C1C800C520BD /* HomeView.swift */,
1C361F1827C046E400E832FC /* HomeViewTwo */,
1CEC966E27B9C29300CC8688 /* IconView.swift */,
1C04488F27C2CA9C00D22444 /* HomeView */,
1C361F0B27C0356B00E832FC /* MainTabView.swift */,
1CAD602C27A5C1C800C520BD /* SettingsView.swift */,
1C358FB027B0AD87002C83A6 /* SharingListView.swift */,
1C04489327C2CABF00D22444 /* SettingsView */,
1C04489527C2CB1A00D22444 /* Sharing */,
1C358FB427B0ADF3002C83A6 /* SharingTemplates */,
1CAD602B27A5C1C800C520BD /* SmallRollUpHeaderView.swift */,
1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */,
@@ -397,6 +482,8 @@
1CD90B75278C8119001C4FEA /* LocalNotification.swift */,
1C4FF3C527BEE07800BE8F34 /* Persisence */,
1CD90B5C278C7EAD001C4FEA /* Random.swift */,
1C2162EA27C14EFA004353D1 /* Date+Extensions.swift */,
1C2162ED27C15191004353D1 /* MoodEntryFunctions.swift */,
1C683FC92792281400745862 /* Stats.swift */,
1C4FF3BA27BEDDF000BE8F34 /* ShowBasedOnVoteLogics.swift */,
1CA03771279A291F00D26164 /* Onboarding */,
@@ -471,15 +558,13 @@
1CD90B60278C7EBA001C4FEA /* Models */ = {
isa = PBXGroup;
children = (
1C02589D27B9821700EB91AC /* CenterTiledImage.swift */,
1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */,
1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */,
1CC469AB27907D48003E0C6E /* DayChartView.swift */,
1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */,
1CD90B61278C7EBA001C4FEA /* Mood.swift */,
1CD90B62278C7EBA001C4FEA /* MoodEntryExtension.swift */,
1C2162F327C1602D004353D1 /* MoodImagable.swift */,
1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */,
1C2162F627C16D11004353D1 /* MoodTintable.swift */,
1C361F1327C03C8600E832FC /* OnboardingDataDataManager.swift */,
1C04488627C1C81D00D22444 /* PersonalityPackable.swift */,
1C358FAC27ADD0C3002C83A6 /* Theme.swift */,
1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */,
);
@@ -685,7 +770,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1CA037702799FFA600D26164 /* ContentModeViewModel.swift in Sources */,
1CA037702799FFA600D26164 /* HomeViewViewModel.swift in Sources */,
1CA03773279A293D00D26164 /* OnboardingTime.swift in Sources */,
1CAD603927A5C1C800C520BD /* HeaderPercView.swift in Sources */,
1CAD603C27A5C1C800C520BD /* HeaderStatsView.swift in Sources */,
@@ -694,11 +779,14 @@
1C4FF3C327BEE07200BE8F34 /* PersistenceDELETE.swift in Sources */,
1CA03775279A294800D26164 /* OnboardingDay.swift in Sources */,
1CAD603727A5C1C800C520BD /* FilterView.swift in Sources */,
1C04488D27C2ADDB00D22444 /* IconViewModel.swift in Sources */,
1C2162F227C156E6004353D1 /* CustomizeView.swift in Sources */,
1C683FCA2792281400745862 /* Stats.swift in Sources */,
1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */,
1CD90B76278C8119001C4FEA /* LocalNotification.swift in Sources */,
1C358FB627B0AE15002C83A6 /* AllMoodsTotalTemplate.swift in Sources */,
1CD90B16278C7DE0001C4FEA /* Feels.xcdatamodeld in Sources */,
1C04488727C1C81D00D22444 /* PersonalityPackable.swift in Sources */,
1C4FF3BE27BEDF9100BE8F34 /* PersistenceHelper.swift in Sources */,
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */,
1CAD603B27A5C1C800C520BD /* HomeView.swift in Sources */,
@@ -707,7 +795,6 @@
1CAD603A27A5C1C800C520BD /* BGView.swift in Sources */,
1C26190727960DC900FDC148 /* ChartViewItemBuildable.swift in Sources */,
1CD90B5D278C7EAD001C4FEA /* Random.swift in Sources */,
1C02589E27B9821700EB91AC /* CenterTiledImage.swift in Sources */,
1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */,
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */,
1CD90B63278C7EBA001C4FEA /* Mood.swift in Sources */,
@@ -720,7 +807,9 @@
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */,
1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */,
1CB101C727B81CAC00D1C033 /* MoodMetrics.swift in Sources */,
1C2162F427C1602D004353D1 /* MoodImagable.swift in Sources */,
1CAD603627A5C1C800C520BD /* GraphView.swift in Sources */,
1C2162F727C16D11004353D1 /* MoodTintable.swift in Sources */,
1C361F1727C046D800E832FC /* MonthDetailView.swift in Sources */,
1CD90B66278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
1C658D7727C0744D003231EE /* PersistenceUPDATE.swift in Sources */,
@@ -728,7 +817,7 @@
1C358FB827B0AEE3002C83A6 /* LongestStreakTemplate.swift in Sources */,
1C358FB127B0AD87002C83A6 /* SharingListView.swift in Sources */,
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */,
1CEC966F27B9C29300CC8688 /* IconView.swift in Sources */,
1CEC966F27B9C29300CC8688 /* CustomWidgetView.swift in Sources */,
1CA0377A279A296E00D26164 /* OnboardingMain.swift in Sources */,
1C358FBA27B35252002C83A6 /* ActivityViewController.swift in Sources */,
1C5F4978279C945E0092F1B4 /* UserDefaultsStore.swift in Sources */,
@@ -736,12 +825,15 @@
1C358FC027B4D20C002C83A6 /* MonthTotalTemplate.swift in Sources */,
1CA03777279A295600D26164 /* OnboardingTitle.swift in Sources */,
1C4FF3C027BEE06900BE8F34 /* PersistenceGET.swift in Sources */,
1C04488A27C2ABD500D22444 /* IconView.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 */,
1C361F1427C03C8600E832FC /* OnboardingDataDataManager.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 */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -781,8 +873,10 @@
buildActionMask = 2147483647;
files = (
1CD90B65278C7EBA001C4FEA /* Mood.swift in Sources */,
1C04488B27C2ABDE00D22444 /* IconView.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 */,
1C4FF3C927BEE0C300BE8F34 /* PersistenceHelper.swift in Sources */,
1CA2662D2793908700C0E12C /* Persistence.swift in Sources */,
@@ -791,16 +885,22 @@
1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */,
1C658D7827C0744D003231EE /* PersistenceUPDATE.swift in Sources */,
1C10E25127A1AB320047948B /* OnboardingTitle.swift in Sources */,
1C04488E27C2AE5200D22444 /* IconViewModel.swift in Sources */,
1C04489727C2DB9B00D22444 /* BGView.swift in Sources */,
1CB101C827B81CAC00D1C033 /* MoodMetrics.swift in Sources */,
1C683FCB2792281400745862 /* Stats.swift in Sources */,
1CEC967327B9CA0C00CC8688 /* CustomIcon.swift in Sources */,
1CEC967327B9CA0C00CC8688 /* CustomWidgetModel.swift in Sources */,
1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */,
1C04488827C1CD8C00D22444 /* PersonalityPackable.swift in Sources */,
1C4FF3C427BEE07200BE8F34 /* PersistenceDELETE.swift in Sources */,
1C4FF3C827BEE09E00BE8F34 /* PersistenceADD.swift in Sources */,
1C2162F527C16061004353D1 /* MoodImagable.swift in Sources */,
1C2162EC27C14FC5004353D1 /* Date+Extensions.swift in Sources */,
1C4FF3C127BEE06900BE8F34 /* PersistenceGET.swift in Sources */,
1C361F0D27C03BDF00E832FC /* OnboardingData.swift in Sources */,
1CD90B52278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */,
1CD90B4D278C7E7A001C4FEA /* FeelsWidget.swift in Sources */,
1C04489627C2DB0100D22444 /* Theme.swift in Sources */,
1C361F0F27C03C0E00E832FC /* LocalNotification.swift in Sources */,
1C10E24E27A1AB110047948B /* UserDefaultsStore.swift in Sources */,
);

View File

@@ -16,12 +16,14 @@ class WatchTimelineView: Identifiable {
let graphic: Image
let date: Date
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.date = date
self.color = color
self.graphic = graphic
self.secondaryColor = secondaryColor
}
}
@@ -39,17 +41,21 @@ struct TimeLineCreator {
let dayStart = Calendar.current.startOfDay(for: day)
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 {
timeLineView.append(WatchTimelineView(image: todayEntry.mood.icon,
date: dayStart,
color: todayEntry.mood.color,
graphic: todayEntry.mood.graphic))
timeLineView.append(WatchTimelineView(image: moodImages.icon(forMood: todayEntry.mood),
graphic: moodImages.icon(forMood: todayEntry.mood),
date: dayStart,
color: moodTint.color(forMood: todayEntry.mood),
secondaryColor: moodTint.secondary(forMood: todayEntry.mood)))
} else {
timeLineView.append(WatchTimelineView(image: Mood.missing.icon,
date: dayStart,
color: Mood.missing.color,
graphic: Mood.missing.graphic))
timeLineView.append(WatchTimelineView(image: moodImages.icon(forMood: .missing),
graphic: moodImages.icon(forMood: .missing),
date: Date(),
color: moodTint.color(forMood: .missing),
secondaryColor: moodTint.secondary(forMood: .missing)))
}
}
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) -> ()) {
let entry = SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
configuration: ConfigurationIntent(),
timeLineViews: Array(TimeLineCreator.createViews(daysBack: 11).prefix(10)))
completion(entry)
}
@@ -83,8 +89,8 @@ struct Provider: IntentTimelineProvider {
timeLineViews: nil)
let midNightEntry = SimpleEntry(date: Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())!,
configuration: ConfigurationIntent(),
timeLineViews: nil)
configuration: ConfigurationIntent(),
timeLineViews: nil)
let date = Calendar.current.date(byAdding: .second, value: 10, to: Date())!
let timeline = Timeline(entries: [entry, midNightEntry], policy: .after(date))
@@ -164,7 +170,7 @@ struct SmallWidgetView: View {
struct MediumWidgetView: View {
var entry: Provider.Entry
var timeLineView = [WatchTimelineView]()
init(entry: Provider.Entry) {
self.entry = entry
timeLineView = Array(TimeLineCreator.createViews(daysBack: 6).prefix(5))
@@ -191,7 +197,7 @@ struct MediumWidgetView: View {
struct LargeWidgetView: View {
var entry: Provider.Entry
var timeLineView = [WatchTimelineView]()
init(entry: Provider.Entry) {
self.entry = entry
timeLineView = Array(TimeLineCreator.createViews(daysBack: 11).prefix(10))
@@ -241,26 +247,31 @@ struct FeelsGraphicWidgetEntryView : View {
var body: some View {
SmallGraphicWidgetView(entry: entry)
.onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
// make sure you don't call this too often
WidgetCenter.shared.reloadAllTimelines()
}
// make sure you don't call this too often
WidgetCenter.shared.reloadAllTimelines()
}
}
}
struct SmallGraphicWidgetView: View {
var entry: Provider.Entry
var timeLineView = [WatchTimelineView]()
var timeLineView: [WatchTimelineView]
init(entry: Provider.Entry) {
self.entry = entry
timeLineView = [TimeLineCreator.createViews(daysBack: 2).first!]
timeLineView = TimeLineCreator.createViews(daysBack: 2)
}
var body: some View {
GeometryReader { geo in
timeLineView.first!.graphic
.resizable()
.scaledToFit()
if let first = timeLineView.first {
IconView(iconViewModel: IconViewModel(backgroundImage: first.graphic,
bgColor: first.color,
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 {
static var previews: some View {
Group {
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
// configuration: ConfigurationIntent(),
// timeLineViews: FeelsWidget_Previews.data))
// .previewContext(WidgetPreviewContext(family: .systemSmall))
// .environment(\.sizeCategory, .small)
//
// 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)
FeelsGraphicWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
timeLineViews: [WatchTimelineView(image: HandEmojiMoodImages.icon(forMood: .great),
graphic: HandEmojiMoodImages.icon(forMood: .great),
date: Date(),
color: MoodTints.Neon.color(forMood: .great),
secondaryColor: .white),
WatchTimelineView(image: HandEmojiMoodImages.icon(forMood: .great),
graphic: HandEmojiMoodImages.icon(forMood: .great),
date: Date(),
color: MoodTints.Neon.color(forMood: .great),
secondaryColor: .white)]))
.previewContext(WidgetPreviewContext(family: .systemSmall))
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)
}
}
}

View File

@@ -18,11 +18,20 @@ class AppDelegate: NSObject, UIApplicationDelegate {
// PersistenceController.shared.clearDB()
PersistenceController.shared.fillInMissingDates()
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
}
func applicationWillEnterForeground(_ application: UIApplication) {
PersistenceController.shared.fillInMissingDates()
// reschedule notifications so there's a new title next notification
LocalNotification.rescheduleNotifiations()
}
}

View 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)
}
}

View File

@@ -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) {
self.removeNotificaiton()
@@ -37,7 +45,7 @@ class LocalNotification {
let _ = LocalNotification.createNotificationCategory()
let notificationContent = UNMutableNotificationContent()
notificationContent.title = title
notificationContent.title = UserDefaultsStore.personalityPackable().randomPushNotificationTitle()
notificationContent.badge = NSNumber(value: 1)
notificationContent.sound = .default

View File

@@ -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
}
}

View File

@@ -37,22 +37,8 @@ enum Mood: Int {
}
var color: Color {
switch self {
case .horrible:
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
}
let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
return moodTint.color(forMood: self)
}
static var allValues: [Mood] {
@@ -60,23 +46,8 @@ enum Mood: Int {
}
var icon: Image {
switch 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)
}
let moodImages: MoodImagable.Type = UserDefaultsStore.moodMoodImagable()
return moodImages.icon(forMood: self)
}
var graphic: Image {

View 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()!)
}
}
}

View 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)
}
}
}

View File

@@ -7,13 +7,14 @@
import Foundation
final class OnboardingDataDataManager {
final class OnboardingDataDataManager: ObservableObject {
static let shared = OnboardingDataDataManager()
@Published public private(set) var savedOnboardingData = UserDefaultsStore.getOnboarding()
public func updateOnboardingData(onboardingData: OnboardingData) {
let onboardingData = UserDefaultsStore.saveOnboarding(onboardingData: onboardingData)
savedOnboardingData = onboardingData
LocalNotification.scheduleReminder(atTime: onboardingData.date, withTitle: onboardingData.title)
}
}

View 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"
]
}
}

View File

@@ -14,6 +14,8 @@ struct ThemeConstants {
enum Theme: Int, CaseIterable {
case system
case iFeel
case dark
case light
var title: String {
switch self {
@@ -21,6 +23,10 @@ enum Theme: Int, CaseIterable {
return SystemTheme.title
case .iFeel:
return IFeelTheme.title
case .dark:
return AlwaysDark.title
case .light:
return AlwaysLight.title
}
}
@@ -31,24 +37,33 @@ enum Theme: Int, CaseIterable {
return SystemTheme()
case .iFeel:
return IFeelTheme()
case .dark:
return AlwaysDark()
case .light:
return AlwaysLight()
}
}
}
protocol Themeable {
static var title: String { get }
var secondaryBGColor: UIColor { get }
var secondaryBGColor: Color { get }
var bg: AnyView { get }
var preview: AnyView { get }
var labelColor: Color { get }
}
struct IFeelTheme: Themeable {
static var title: String {
return "iFeel Theme"
var labelColor: Color {
return Color(uiColor: UIColor.label)
}
var secondaryBGColor: UIColor {
return UIColor.systemBackground
static var title: String {
return "iFeel"
}
var secondaryBGColor: Color {
return Color(uiColor: UIColor.systemBackground)
}
var bg: AnyView {
@@ -69,12 +84,16 @@ struct IFeelTheme: Themeable {
}
struct SystemTheme: Themeable {
var labelColor: Color {
return Color(uiColor: UIColor.label)
}
static var title: String {
return "System"
}
var secondaryBGColor: UIColor {
return UIColor.secondarySystemBackground
var secondaryBGColor: Color {
return Color(uiColor: UIColor.secondarySystemBackground)
}
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))
}
)
}
}

View File

@@ -15,7 +15,9 @@ class UserDefaultsStore {
case deleteEnable
case mainViewTopHeaderIndex
case theme
case moodImages
case moodTint
case personalityPack
case customIcon
case contentViewCurrentSelectedHeaderViewBackDays
@@ -43,4 +45,41 @@ class UserDefaultsStore {
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
}
}
}

View 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
}
}

View File

@@ -32,7 +32,8 @@ extension PersistenceController {
}
func fillInMissingDates() {
let endDate = ShowBasedOnVoteLogics.getLastDateVoteShouldExist()
let currentOnboarding = UserDefaultsStore.getOnboarding()
let endDate = ShowBasedOnVoteLogics.getLastDateVoteShouldExist(onboardingData: currentOnboarding)
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: false)]

View File

@@ -73,13 +73,12 @@ extension PersistenceController {
var components = DateComponents()
components.month = month
components.year = year
components.day = 1
let startDateOfMonth = Calendar.current.date(from: components)!
let items = data.filter({ entry in
let components = calendar.dateComponents([.month, .year], from: startDateOfMonth)
let entryComponents = calendar.dateComponents([.month, .year], from: entry.forDate!)
return (components.month == entryComponents.month && components.year == entryComponents.year)
})
let items = PersistenceController.shared.getData(startDate: startDateOfMonth,
endDate: startDateOfMonth.endOfMonth,
includedDays: [1,2,3,4,5,6,7])
if !items.isEmpty {
allMonths[month] = items
}

View File

@@ -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)
newItem.timestamp = Date()
newItem.moodValue = Int16(Mood.placeholder.rawValue)
newItem.forDate = Date()
newItem.moodValue = Int16(mood.rawValue)
newItem.forDate = date
newItem.weekDay = Int16(Calendar.current.component(.weekday, from: Date()))
newItem.canEdit = false
newItem.canDelete = false

View File

@@ -77,7 +77,9 @@ extension ChartDataBuildable {
let date = components.day
return day == date
}).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),
viewType: .square)
filledOutArray.append(view)

View File

@@ -18,8 +18,6 @@ struct GroupUserDefaults {
}
}
typealias MoodGroupingMetrics = (mood: Mood, total: Int, percent: Float)
class Random {
static var tomorrowMidnightThirty: Date {
let components = DateComponents(hour: 0, minute: 30, second: 0)
@@ -52,61 +50,29 @@ class Random {
return formatter.string(from: NSNumber(integerLiteral: day)) ?? ""
}
static func createTotalPerc(fromEntries entries: [MoodEntry]) -> [MoodGroupingMetrics] {
var returnData = [MoodGroupingMetrics]()
static func createTotalPerc(fromEntries entries: [MoodEntry]) -> [MoodMetrics] {
let filteredEntries = entries.filter({
return ![.missing, .placeholder].contains($0.mood)
})
var returnData = [MoodMetrics]()
for (_, mood) in Mood.allValues.enumerated() {
let moodEntries = entries.filter({
let moodEntries = filteredEntries.filter({
Int($0.moodValue) == mood.rawValue
})
let total = moodEntries.count
let perc = (Float(total) / Float(entries.count)) * 100
returnData.append((mood, total, perc))
let perc = (Float(total) / Float(filteredEntries.count)) * 100
returnData.append(MoodMetrics(mood: mood, total: total, percent: perc))
}
returnData = returnData.sorted(by: {
$0.0.rawValue > $1.0.rawValue
$0.mood.rawValue > $1.mood.rawValue
})
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 {
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 {
static func random() -> Self {
Self(
@@ -175,4 +127,47 @@ extension Color {
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()
}
}

View File

@@ -18,17 +18,13 @@ import SwiftUI
// today at 11 am -> How as 2 days ago
// today at 1 pm -> How was yesterday
class ShowBasedOnVoteLogics {
private static var currentVoting: (passTimeToVote: Bool, dayOptions: DayOptions) {
let passedTimeToVote = UserDefaultsStore.getOnboarding().ableToVoteBasedOnCurentTime()
let inputDay = UserDefaultsStore.getOnboarding().inputDay
static func isMissingCurrentVote(onboardingData: OnboardingData) -> Bool {
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
let inputDay = onboardingData.inputDay
return (passedTimeToVote, inputDay)
}
static func isMissingCurrentVote() -> Bool {
var startDate: Date?
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
switch (passedTimeToVote, inputDay) {
case (true, .Previous):
// 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())!
@@ -57,8 +53,11 @@ class ShowBasedOnVoteLogics {
return entries < 1
}
static func getVotingTitle() -> String {
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
static func getVotingTitle(onboardingData: OnboardingData) -> String {
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
let inputDay = onboardingData.inputDay
switch (passedTimeToVote, inputDay) {
case (true, .Previous):
// if we're passed time to vote and the voting type is previous - last vote should be -1
return "how was yesterday"
@@ -67,7 +66,7 @@ class ShowBasedOnVoteLogics {
return "how is today"
case (false, .Previous):
// 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))"
case (false, .Today):
// 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?
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
switch (passedTimeToVote, inputDay) {
case (true, .Previous):
// 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())
@@ -100,10 +102,13 @@ class ShowBasedOnVoteLogics {
return nil
}
static func getLastDateVoteShouldExist() -> Date {
static func getLastDateVoteShouldExist(onboardingData: OnboardingData) -> Date {
let passedTimeToVote = onboardingData.ableToVoteBasedOnCurentTime()
let inputDay = onboardingData.inputDay
var endDate: Date?
switch (currentVoting.passTimeToVote, currentVoting.dayOptions) {
switch (passedTimeToVote, inputDay) {
case (true, .Previous):
// 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())!

View File

@@ -11,8 +11,10 @@ import SwiftUI
import CoreData
struct AddMoodHeaderView: View {
private let savedOnboardingData = UserDefaultsStore.getOnboarding()
@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)
@@ -22,12 +24,12 @@ struct AddMoodHeaderView: View {
var body: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Text(ShowBasedOnVoteLogics.getVotingTitle())
Text(ShowBasedOnVoteLogics.getVotingTitle(onboardingData: onboardingData))
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.padding()
HStack{
ForEach(Mood.allValues) { mood in
@@ -38,7 +40,7 @@ struct AddMoodHeaderView: View {
mood.icon
.resizable()
.frame(width: CGFloat(50), height: CGFloat(50), alignment: .center)
.foregroundColor(mood.color)
.foregroundColor(moodTint.color(forMood: mood))
})
//Text(mood.strValue)
@@ -49,7 +51,7 @@ struct AddMoodHeaderView: View {
.padding([.leading, .trailing, .bottom])
}
.background(
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
.frame(minHeight: 88, maxHeight: 150)
@@ -57,7 +59,7 @@ struct AddMoodHeaderView: View {
}
private func addItem(withMood mood: Mood) {
if let date = ShowBasedOnVoteLogics.dateForHeaderVote() {
if let date = ShowBasedOnVoteLogics.dateForHeaderVote(onboardingData: onboardingData) {
addItemHeaderClosure(mood, date)
}
}

View File

@@ -8,14 +8,16 @@
import SwiftUI
struct BGViewItem: View {
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
let mood: Mood
let size: CGSize
var color: Color
let animate: Bool
let yRowPosition: Float
init(mood: Mood, size: CGSize, animate: Bool, yRowPosition: Float) {
color = mood.color
init(mood: Mood, size: CGSize, animate: Bool, yRowPosition: Float, color: Color) {
self.color = color
self.mood = mood
self.size = size
self.yRowPosition = yRowPosition
@@ -23,16 +25,18 @@ struct BGViewItem: View {
}
var body: some View {
Mood.allValues.randomElement()?.icon
FontAwesomeMoodImages.icon(forMood: mood)
.resizable()
.frame(width: size.width, height: size.height)
.foregroundColor(color)
// .blur(radius: 3)
.foregroundColor(DefaultMoodTint.color(forMood: mood))
// .blur(radius: 3)
.opacity(0.1)
}
}
struct BGView: View, Equatable {
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
var numAcross: Int
var numDown: Int
let iconSize = 35
@@ -45,15 +49,22 @@ struct BGView: View, Equatable {
numDown = Int(screenHeight)/iconSize
}
var randomMood: Mood? {
return Mood.allValues.randomElement()
}
var body: some View {
VStack {
ForEach(0...numDown, id: \.self) { row in
HStack {
ForEach(0...numAcross, id: \.self) { _ in
BGViewItem(mood: Mood.allValues.randomElement()!,
size: .init(width: iconSize,height: iconSize),
animate: false,
yRowPosition: Float(row)/Float(numDown))
if let randomMood = randomMood {
BGViewItem(mood: randomMood,
size: .init(width: iconSize,height: iconSize),
animate: false,
yRowPosition: Float(row)/Float(numDown),
color: moodTint.color(forMood:randomMood))
}
}.frame(minWidth: 0, maxWidth: .infinity)
.padding([.trailing, .leading], 13.5)
}

View File

@@ -7,47 +7,47 @@
import SwiftUI
struct CreateIconView: View {
struct CreateWidgetView: View {
@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
static var iconViewBGs: [(BackGroundOptions, UUID)] = {
var blah = [(BackGroundOptions, UUID)]()
static var iconViewBGs: [(CustomWidgetBackGroundOptions, UUID)] = {
var blah = [(CustomWidgetBackGroundOptions, UUID)]()
for _ in 0...99 {
blah.append((BackGroundOptions.selectable.randomElement()!, UUID()))
blah.append((CustomWidgetBackGroundOptions.selectable.randomElement()!, UUID()))
}
return blah
}()
@State private var mouth: MouthOptions = MouthOptions.defaultOption
@StateObject private var customIcon = CustomIcon(leftEye: EyeOptions.defaultOption,
rightEye: EyeOptions.defaultOption,
mouth: MouthOptions.defaultOption,
background: CreateIconView.iconViewBGs,
bgColor: .red,
innerColor: .green,
bgOverlayColor: .black,
rightEyeColor: .orange,
leftEyeColor: .yellow,
mouthColor: .purple,
circleStrokeColor: .pink)
@State private var mouth: CustomWidgetMouthOptions = CustomWidgetMouthOptions.defaultOption
@StateObject private var customIcon = CustomWidgetModel(leftEye: CustomWidgetEyeOptions.defaultOption,
rightEye: CustomWidgetEyeOptions.defaultOption,
mouth: CustomWidgetMouthOptions.defaultOption,
background: CreateWidgetView.iconViewBGs,
bgColor: .red,
innerColor: .green,
bgOverlayColor: .black,
rightEyeColor: .orange,
leftEyeColor: .yellow,
mouthColor: .purple,
circleStrokeColor: .pink)
private var randomElements: [AnyView] = [
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20)),
AnyView(Image(BackGroundOptions.selectable.randomElement()!.rawValue)
AnyView(Image(CustomWidgetBackGroundOptions.selectable.randomElement()!.rawValue)
.resizable()
.frame(width: 20, height: 20))
]
func update(eye: Eyes, eyeOption: EyeOptions) {
func update(eye: CustomWidgetEyes, eyeOption: CustomWidgetEyeOptions) {
switch eye {
case .left:
customIcon.leftEye = eyeOption
@@ -65,27 +65,27 @@ struct CreateIconView: View {
customIcon.rightEyeColor = Color.random()
customIcon.mouthColor = Color.random()
update(eye: .left, eyeOption: EyeOptions.allCases.randomElement()!)
update(eye: .right, eyeOption: EyeOptions.allCases.randomElement()!)
update(mouthOption: MouthOptions.allCases.randomElement()!)
update(eye: .left, eyeOption: CustomWidgetEyeOptions.allCases.randomElement()!)
update(eye: .right, eyeOption: CustomWidgetEyeOptions.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
}
func update(background: BackGroundOptions) {
func update(background: CustomWidgetBackGroundOptions) {
customIcon.background.removeAll()
if background == .random {
for _ in 0...CustomIcon.numberOfBGItems {
customIcon.background.append((BackGroundOptions.selectable.randomElement()!, UUID()))
for _ in 0...CustomWidgetModel.numberOfBGItems {
customIcon.background.append((CustomWidgetBackGroundOptions.selectable.randomElement()!, UUID()))
}
return
}
for _ in 0...CustomIcon.numberOfBGItems {
for _ in 0...CustomWidgetModel.numberOfBGItems {
customIcon.background.append((background, UUID()))
}
}
@@ -103,16 +103,16 @@ struct CreateIconView: View {
}
}
var iconView: some View {
IconView(customIcon: customIcon, isPreview: true)
var widgetView: some View {
CustomWidgetView(customWidgetModel: customIcon)
}
var body: some View {
VStack(spacing: 0) {
iconView
.frame(width: 256, height: 256)
widgetView
// .frame(width: 256, height: 256)
.cornerRadius(10)
.padding(.top)
.padding()
Spacer()
@@ -123,7 +123,7 @@ struct CreateIconView: View {
Spacer()
VStack(alignment: .center) {
Menu("Left Eye") {
ForEach(EyeOptions.allCases, id: \.self) { option in
ForEach(CustomWidgetEyeOptions.allCases, id: \.self) { option in
Button(action: {
update(eye: .left, eyeOption: option)
}, label: {
@@ -131,12 +131,12 @@ struct CreateIconView: View {
})
}
}
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
}
Spacer()
VStack(alignment: .center) {
Menu("Right Eye") {
ForEach(EyeOptions.allCases, id: \.self) { option in
ForEach(CustomWidgetEyeOptions.allCases, id: \.self) { option in
Button(action: {
update(eye: .right, eyeOption: option)
}, label: {
@@ -144,12 +144,12 @@ struct CreateIconView: View {
})
}
}
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
}
Spacer()
VStack(alignment: .center) {
Menu("Mouth") {
ForEach(MouthOptions.allCases, id: \.self) { option in
ForEach(CustomWidgetMouthOptions.allCases, id: \.self) { option in
Button(action: {
update(mouthOption: option)
}, label: {
@@ -157,13 +157,13 @@ struct CreateIconView: View {
})
}
}
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
}
Spacer()
}
.padding()
.background(
Color(uiColor: theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
}
@@ -171,7 +171,7 @@ struct CreateIconView: View {
Group {
HStack {
ForEach(BackGroundOptions.selectable, id: \.self) { bg in
ForEach(CustomWidgetBackGroundOptions.selectable, id: \.self) { bg in
Image(bg.rawValue, bundle: .main)
.resizable()
.aspectRatio(contentMode: .fill)
@@ -191,7 +191,7 @@ struct CreateIconView: View {
}
.padding()
.background(
Color(uiColor: theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
}
@@ -248,7 +248,7 @@ struct CreateIconView: View {
}
.padding()
.background(
Color(uiColor: theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
}
@@ -269,7 +269,7 @@ struct CreateIconView: View {
.background(.blue)
Button(action: {
let bigIconView = IconView(customIcon: customIcon, isPreview: false)
let bigIconView = CustomWidgetView(customWidgetModel: customIcon)
.frame(width: 512, height: 512, alignment: .center)
.aspectRatio(contentMode: .fill)
let icon = bigIconView.snapshot()
@@ -297,9 +297,9 @@ struct CreateIconView: View {
struct CreateIconView_Previews: PreviewProvider {
static var previews: some View {
Group {
CreateIconView()
CreateWidgetView()
CreateIconView()
CreateWidgetView()
.preferredColorScheme(.dark)
}
}

View 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)
}
}
}

View 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)
}
}

View File

@@ -7,26 +7,26 @@
import SwiftUI
class CustomIcon: ObservableObject {
static let numberOfBGItems = 99
class CustomWidgetModel: ObservableObject {
static let numberOfBGItems = 109
static let defaultCustomIcon = CustomIcon(leftEye: EyeOptions.defaultOption,
rightEye: EyeOptions.defaultOption,
mouth: MouthOptions.defaultOption,
background: IconView_Previews.backgrounds,
bgColor: .red,
innerColor: .green,
bgOverlayColor: .orange,
rightEyeColor: .orange,
leftEyeColor: .yellow,
mouthColor: .green,
circleStrokeColor: .pink)
static let defaultCustomIcon = CustomWidgetModel(leftEye: CustomWidgetEyeOptions.defaultOption,
rightEye: CustomWidgetEyeOptions.defaultOption,
mouth: CustomWidgetMouthOptions.defaultOption,
background: WidgetView_Previews.backgrounds,
bgColor: .red,
innerColor: .green,
bgOverlayColor: .orange,
rightEyeColor: .orange,
leftEyeColor: .yellow,
mouthColor: .green,
circleStrokeColor: .pink)
init(leftEye: EyeOptions,
rightEye: EyeOptions,
mouth: MouthOptions,
background: [(BackGroundOptions, UUID)],
init(leftEye: CustomWidgetEyeOptions,
rightEye: CustomWidgetEyeOptions,
mouth: CustomWidgetMouthOptions,
background: [(CustomWidgetBackGroundOptions, UUID)],
bgColor: Color,
innerColor: Color,
bgOverlayColor: Color,
@@ -48,11 +48,11 @@ class CustomIcon: ObservableObject {
self.circleStrokeColor = circleStrokeColor
}
@Published var leftEye: EyeOptions
@Published var rightEye: EyeOptions
@Published var mouth: MouthOptions
@Published var leftEye: CustomWidgetEyeOptions
@Published var rightEye: CustomWidgetEyeOptions
@Published var mouth: CustomWidgetMouthOptions
@Published var background: [(BackGroundOptions, UUID)]
@Published var background: [(CustomWidgetBackGroundOptions, UUID)]
@Published var bgColor: Color
@Published var innerColor: Color
@Published var bgOverlayColor: Color
@@ -64,7 +64,7 @@ class CustomIcon: ObservableObject {
@Published var circleStrokeColor: Color
}
enum BackGroundOptions: String, CaseIterable, Codable {
enum CustomWidgetBackGroundOptions: String, CaseIterable, Codable {
case horrible
case bad
case average
@@ -72,12 +72,12 @@ enum BackGroundOptions: String, CaseIterable, Codable {
case great
case random
static var selectable: [BackGroundOptions] {
static var selectable: [CustomWidgetBackGroundOptions] {
return [.great, .good, .average, .bad, .horrible]
}
static public var defaultOption: BackGroundOptions {
BackGroundOptions.random
static public var defaultOption: CustomWidgetBackGroundOptions {
CustomWidgetBackGroundOptions.random
}
public var image: Image {
@@ -85,12 +85,12 @@ enum BackGroundOptions: String, CaseIterable, Codable {
}
}
enum Eyes: String, Codable {
enum CustomWidgetEyes: String, Codable {
case left
case right
}
enum EyeOptions: String, CaseIterable, Codable {
enum CustomWidgetEyeOptions: String, CaseIterable, Codable {
case fire = "fire"
case bolt = "bolt2"
case dollar = "dollar"
@@ -109,8 +109,8 @@ enum EyeOptions: String, CaseIterable, Codable {
case skull2 = "skull2"
case poo = "poo"
static public var defaultOption: EyeOptions {
EyeOptions.fire
static public var defaultOption: CustomWidgetEyeOptions {
CustomWidgetEyeOptions.fire
}
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 bolt = "bolt2"
case dollar = "dollar"
@@ -137,8 +137,8 @@ enum MouthOptions: String, CaseIterable, Codable {
case skull2 = "skull2"
case poo = "poo"
static public var defaultOption: MouthOptions {
MouthOptions.bomb
static public var defaultOption: CustomWidgetMouthOptions {
CustomWidgetMouthOptions.bomb
}
public var image: Image {

View File

@@ -7,32 +7,31 @@
import SwiftUI
struct IconView: View {
@State public var customIcon: CustomIcon
struct CustomWidgetView: View {
@State public var customWidgetModel: CustomWidgetModel
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)
}
// 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),
@@ -52,32 +51,33 @@ struct IconView: View {
ZStack {
Rectangle()
.fill(
customIcon.bgColor
customWidgetModel.bgColor
)
.frame(maxWidth: .infinity, maxHeight: .infinity)
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
.resizable()
.aspectRatio(1, contentMode: .fill)
.foregroundColor(customIcon.bgOverlayColor)
.foregroundColor(customWidgetModel.bgOverlayColor)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.scaleEffect(1.1)
.clipped()
.background(
.clear
)
Circle()
.strokeBorder(customIcon.circleStrokeColor, lineWidth: geo.size.width * 0.045)
.background(Circle().fill(customIcon.innerColor))
.strokeBorder(customWidgetModel.circleStrokeColor, lineWidth: geo.size.width * 0.045)
.background(Circle().fill(customWidgetModel.innerColor))
.frame(width: geo.size.width*facePercSize,
height: geo.size.height*facePercSize,
alignment: .center)
.position(x: geo.size.width/2, y: geo.size.height/2)
customIcon.leftEye.image
customWidgetModel.leftEye.image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width*0.12,
@@ -85,9 +85,9 @@ struct IconView: View {
alignment: .center)
.position(x: geo.size.width*0.4,
y: geo.size.height*0.4)
.foregroundColor(customIcon.leftEyeColor)
.foregroundColor(customWidgetModel.leftEyeColor)
customIcon.rightEye.image
customWidgetModel.rightEye.image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width*0.12,
@@ -95,9 +95,9 @@ struct IconView: View {
alignment: .center)
.position(x: geo.size.width*0.6,
y: geo.size.height*0.4)
.foregroundColor(customIcon.rightEyeColor)
.foregroundColor(customWidgetModel.rightEyeColor)
customIcon.mouth.image
customWidgetModel.mouth.image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width*0.12,
@@ -105,26 +105,25 @@ struct IconView: View {
alignment: .center)
.position(x: geo.size.width*0.5,
y: geo.size.height*0.59)
.foregroundColor(customIcon.mouthColor)
.foregroundColor(customWidgetModel.mouthColor)
}
.position(x: geo.size.width/2,
y: geo.size.height/2 - entireFuckingViewOffset)
y: geo.size.height/2)
}
}
}
struct IconView_Previews: PreviewProvider {
static var backgrounds: [(BackGroundOptions, UUID)] = {
var blah = [(BackGroundOptions, UUID)]()
for _ in 0...CustomIcon.numberOfBGItems {
blah.append((BackGroundOptions.selectable.randomElement()!, UUID()))
struct WidgetView_Previews: PreviewProvider {
static var backgrounds: [(CustomWidgetBackGroundOptions, UUID)] = {
var blah = [(CustomWidgetBackGroundOptions, UUID)]()
for _ in 0...CustomWidgetModel.numberOfBGItems {
blah.append((CustomWidgetBackGroundOptions.selectable.randomElement()!, UUID()))
}
return blah
}()
static var previews: some View {
IconView(customIcon: CustomIcon.defaultCustomIcon,
isPreview: true)
CustomWidgetView(customWidgetModel: CustomWidgetModel.defaultCustomIcon)
.frame(width: 256, height: 256, alignment: .center)
}

View 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()
}
}

View File

@@ -10,21 +10,21 @@ import SwiftUI
struct EmptyHomeView: View {
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
let viewModel: ContentModeViewModel
let viewModel: HomeViewViewModel
var body: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Text(String(localized: "content_view_empty_title"))
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.padding()
Text(String(localized: "content_view_empty_title"))
.font(.body)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.padding()
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
withAnimation {
@@ -40,6 +40,6 @@ struct EmptyHomeView: View {
struct EmptyHomeView_Previews: PreviewProvider {
static var previews: some View {
EmptyHomeView(viewModel: ContentModeViewModel(addMonthStartWeekdayPadding: false))
EmptyHomeView(viewModel: HomeViewViewModel(addMonthStartWeekdayPadding: false))
}
}

View File

@@ -21,7 +21,8 @@ struct FilterView: View {
private var items: FetchedResults<MoodEntry>
@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()
//[
// 2001: [0: [], 1: [], 2: []],
@@ -54,6 +55,7 @@ struct FilterView: View {
Text(String(localized: "filter_view_total") + ": \(self.viewModel.numberOfRatings)")
.font(.title2)
.foregroundColor(theme.currentTheme.labelColor)
if showFilter {
filterView
@@ -80,13 +82,16 @@ struct FilterView: View {
Text(showFilter ? String(localized: "filter_view_hide_filters") : String(localized: "filter_view_show_filters"))
.frame(maxWidth: .infinity)
.frame(height: 44)
.foregroundColor(Color(UIColor.label))
.background(Color(theme.currentTheme.secondaryBGColor))
.foregroundColor(theme.currentTheme.labelColor)
.background(theme.currentTheme.secondaryBGColor)
.cornerRadius(10)
}).frame(maxWidth: .infinity)
}
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 mood: Mood
@@ -95,15 +100,16 @@ struct FilterView: View {
Text(String(Stats.getCountFor(moodType: mood,
inData: data)))
.font(.title)
.foregroundColor(theme.currentTheme.labelColor)
Text(mood.strValue)
.foregroundColor(mood.color)
.foregroundColor(moodTint.color(forMood: mood))
}
}
}
private var statsView: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
HStack {
Spacer()
@@ -120,7 +126,7 @@ struct FilterView: View {
VStack {
VStack {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
DatePicker(
String(localized: "filter_view_begin_date"),
selection: $viewModel.entryStartDate,
@@ -133,9 +139,10 @@ struct FilterView: View {
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44)
.cornerRadius(10)
.padding([.leading, .trailing])
.foregroundColor(theme.currentTheme.labelColor)
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
DatePicker(
String(localized: "filter_view_end_date"),
selection: $viewModel.entryEndDate,
@@ -148,9 +155,10 @@ struct FilterView: View {
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 44, maxHeight: 44)
.cornerRadius(10)
.padding([.leading, .trailing])
.foregroundColor(theme.currentTheme.labelColor)
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
HStack {
Spacer()
ForEach(weekdays.indices, id: \.self) { dayIdx in
@@ -186,6 +194,7 @@ struct FilterView: View {
ForEach(months, id: \.self.0) { item in
Text(item.1)
.textCase(.uppercase)
.foregroundColor(theme.currentTheme.labelColor)
}
}.padding([.leading, .trailing, .top])
}
@@ -202,9 +211,10 @@ struct FilterView: View {
let yearData = self.viewModel.data[yearKey]!
Text(String(yearKey))
.font(.title)
.foregroundColor(theme.currentTheme.labelColor)
yearGridView(yearData: yearData, columns: columns)
.background(
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
.cornerRadius(10)
}

View File

@@ -13,8 +13,9 @@ enum PercViewType {
}
struct HeaderPercView: View {
typealias model = (mood: Mood, total: Int, percent: Float)
var entries = [model]()
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
var entries = [MoodMetrics]()
let backDays: Int
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])
}
let totalEntryCount = moodEntries?.count ?? 0
if let moodEntries = 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
entries.append((mood, total, perc))
}
entries = Random.createTotalPerc(fromEntries: moodEntries)
entries = entries.sorted(by: {
$0.mood.rawValue > $1.mood.rawValue
})
}
entries = entries.sorted(by: {
$0.0.rawValue > $1.0.rawValue
})
}
private var textViews: some View {
VStack {
Spacer()
HStack {
ForEach(entries.prefix(3), id: \.0) { model in
ForEach(entries.prefix(3), id: \.id) { model in
Text("\(model.percent, specifier: "%.0f")%")
.font(.title)
.fontWeight(.bold)
.foregroundColor(model.mood.color)
.foregroundColor(moodTint.color(forMood: model.mood))
.frame(maxWidth: .infinity)
}
}
Spacer()
HStack {
ForEach(entries.suffix(2), id: \.0) { model in
ForEach(entries.suffix(2), id: \.id) { model in
Text("\(model.percent, specifier: "%.0f")%")
.font(.title)
.fontWeight(.bold)
.foregroundColor(model.mood.color)
.foregroundColor(moodTint.color(forMood: model.mood))
.frame(maxWidth: .infinity)
}
}
@@ -81,27 +72,27 @@ struct HeaderPercView: View {
VStack {
Spacer()
HStack {
ForEach(entries.prefix(3), id: \.0) { model in
ForEach(entries.prefix(3), id: \.id) { model in
Text("\(model.percent, specifier: "%.0f")%")
.font(.title2)
.fontWeight(.bold)
.multilineTextAlignment(.center)
.padding()
.frame(maxWidth: .infinity)
.background(Circle().fill(model.mood.color))
.background(Circle().fill(moodTint.color(forMood: model.mood)))
.foregroundColor(Color(UIColor.white))
}
}
Spacer()
HStack {
ForEach(entries.suffix(2), id: \.0) { model in
ForEach(entries.suffix(2), id: \.id) { model in
Text("\(model.percent, specifier: "%.0f")%")
.font(.title2)
.fontWeight(.bold)
.multilineTextAlignment(.center)
.padding()
.frame(maxWidth: .infinity)
.background(Circle().fill(model.mood.color))
.background(Circle().fill(moodTint.color(forMood: model.mood)))
.foregroundColor(Color(UIColor.white))
}
}

View File

@@ -11,8 +11,10 @@ import Charts
struct HeaderStatsView : UIViewRepresentable {
//Bar chart accepts data as array of BarChartDataEntry objects
var entries : [BarChartDataEntry]
var moodTint: MoodTints
init(fakeData: Bool, backDays: Int) {
init(fakeData: Bool, backDays: Int, moodTint: MoodTints) {
self.moodTint = moodTint
entries = [BarChartDataEntry]()
var moodEntries: [MoodEntry]?
@@ -96,7 +98,7 @@ struct HeaderStatsView : UIViewRepresentable {
let dataSet = BarChartDataSet(entries: entries)
// 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.valueColors = [.white]
dataSet.highlightAlpha = 0.0
@@ -120,6 +122,6 @@ struct HeaderStatsView : UIViewRepresentable {
struct HeaderStatsView_Previews: PreviewProvider {
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)
}
}

View File

@@ -20,7 +20,10 @@ struct HomeView: View {
@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.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
@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
@@ -37,6 +40,7 @@ struct HomeView: View {
// MARK: ?? properties
@State private var showTodayInput = true
@State private var showUpdateEntryAlert = false
@StateObject private var onboardingData = OnboardingDataDataManager.shared
// MARK: header properties
@State private var headerHeight: CGFloat = HomeViewConstants.maxHeaderHeight
@@ -44,17 +48,11 @@ struct HomeView: View {
@State private var headerOpacity: Double = 1.0
//
@ObservedObject var viewModel = ContentModeViewModel(addMonthStartWeekdayPadding: false)
init(){
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.label
UIPageControl.appearance().pageIndicatorTintColor = UIColor.systemGray
UITabBar.appearance().backgroundColor = UIColor.secondarySystemBackground
}
@ObservedObject var viewModel = HomeViewViewModel(addMonthStartWeekdayPadding: false)
var body: some View {
mainView
.alert(ContentModeViewModel.updateTitleHeader(forEntry: selectedEntry),
.alert(HomeViewViewModel.updateTitleHeader(forEntry: selectedEntry),
isPresented: $showUpdateEntryAlert) {
ForEach(Mood.allValues) { mood in
Button(mood.strValue, action: {
@@ -130,11 +128,12 @@ struct HomeView: View {
VStack {
SmallRollUpHeaderView(entries: getBackEntries(),
viewType: $currentSelectedHeaderViewViewType)
.frame(height: HomeViewConstants.minHeaderHeight)
.padding([.trailing, .leading])
.background(
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
.padding([.top, .bottom], 5)
Spacer()
}
@@ -173,8 +172,6 @@ struct HomeView: View {
withAnimation{
viewModel.updateData()
}
}, updateBoardingDataClosure: { onboardingData in
OnboardingDataDataManager.shared.updateOnboardingData(onboardingData: onboardingData)
})
}.padding(.trailing)
}
@@ -182,7 +179,7 @@ struct HomeView: View {
private var headerView: some View {
VStack {
if ShowBasedOnVoteLogics.isMissingCurrentVote() {
if ShowBasedOnVoteLogics.isMissingCurrentVote(onboardingData: onboardingData.savedOnboardingData) {
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
withAnimation {
viewModel.add(mood: mood, forDate: date, entryType: .header)
@@ -255,7 +252,7 @@ struct HomeView: View {
)
}
.background(
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
.coordinateSpace(name: "scroll")
.onPreferenceChange(ViewOffsetKey.self) { value in
@@ -281,11 +278,11 @@ extension HomeView {
private func SectionHeaderView(month: Int, year: Int) -> some View {
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.background(
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
}
@@ -307,23 +304,23 @@ extension HomeView {
private func entryListView(entry: MoodEntry) -> some View {
HStack {
entry.mood.icon
imagePack.icon(forMood: entry.mood)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 40, height: 40, alignment: .center)
.foregroundColor(entry.mood.color)
.foregroundColor(moodTint.color(forMood: entry.mood))
.padding(.leading, 5)
VStack {
HStack {
Text(Random.weekdayName(fromDate:entry.forDate!))
.font(.title3)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
Text(" - ")
.padding([.leading, .trailing], -10)
Text(Random.dayFormat(fromDate:entry.forDate!))
.font(.title3)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
Spacer()
}
.multilineTextAlignment(.leading)

View 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()
}
}

View 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))
}
}

View File

@@ -8,7 +8,7 @@
import SwiftUI
import CoreData
class ContentModeViewModel: ObservableObject {
class HomeViewViewModel: ObservableObject {
@Published var grouped = [Int: [Int: [MoodEntry]]]()
@Published var numberOfItems = 0
@@ -50,33 +50,7 @@ class ContentModeViewModel: ObservableObject {
grouped = PersistenceController.shared.splitIntoYearMonth()
if addMonthStartWeekdayPadding {
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] {
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
grouped = MoodEntryFunctions.padMoodEntriesForCalendar(entries: grouped)
}
numberOfItems = numberOfEntries

View File

@@ -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()
}
}

View File

@@ -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!
}))
}
}

View File

@@ -16,7 +16,7 @@ struct MainTabView: View {
TabView {
HomeViewTwo()
.tabItem {
Label(String(localized: "content_view_tab_main"), systemImage: "list.dash")
Label(String(localized: "content_view_tab_main"), systemImage: "calendar")
}
HomeView()
@@ -26,13 +26,18 @@ struct MainTabView: View {
FilterView()
.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()
.tabItem {
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: {
}, content: {

View File

@@ -12,13 +12,11 @@ struct SettingsView: View {
@Environment(\.dismiss) var dismiss
let editedDataClosure: (() -> Void)
let updateBoardingDataClosure: ((OnboardingData) -> Void)
@State private var showOnboarding = false
@State private var showSpecialThanks = false
@State private var showWhyBGMode = false
@State private var showCreateCustomWidget = false
@ObservedObject var syncMonitor = SyncMonitor.shared
@AppStorage(UserDefaultsStore.Keys.useCloudKit.rawValue, store: GroupUserDefaults.groupDefaults) private var useCloudKit = false
@@ -34,9 +32,6 @@ struct SettingsView: View {
cloudKitEnable
canDelete
changeIcon
themePicker
createCustomWidget
showOnboardingButton
whyBackgroundMode
specialThanksCell
@@ -56,13 +51,10 @@ struct SettingsView: View {
}.sheet(isPresented: $showOnboarding) {
OnboardingMain(onboardingData: UserDefaultsStore.getOnboarding(),
updateBoardingDataClosure: { onboardingData in
updateBoardingDataClosure(onboardingData)
OnboardingDataDataManager.shared.updateOnboardingData(onboardingData: onboardingData)
showOnboarding = false
})
}
.sheet(isPresented: $showCreateCustomWidget) {
CreateIconView()
}
.background(
theme.currentTheme.bg
.edgesIgnoringSafeArea(.all)
@@ -84,7 +76,7 @@ struct SettingsView: View {
private var specialThanksCell: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Button(action: {
withAnimation{
@@ -107,7 +99,7 @@ struct SettingsView: View {
private var addTestDataCell: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
Button(action: {
PersistenceController.shared.populateTestData()
editedDataClosure()
@@ -122,7 +114,7 @@ struct SettingsView: View {
private var clearDB: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
Button(action: {
PersistenceController.shared.clearDB()
editedDataClosure()
@@ -137,7 +129,7 @@ struct SettingsView: View {
private var whyBackgroundMode: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Button(action: {
withAnimation{
@@ -157,51 +149,13 @@ struct SettingsView: View {
.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 {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
Button(action: {
showOnboarding.toggle()
}, label: {
@@ -215,7 +169,7 @@ struct SettingsView: View {
private var cloudKitEnable: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Toggle(String(localized: "settings_use_cloudkit_title"),
isOn: $useCloudKit)
@@ -233,7 +187,7 @@ struct SettingsView: View {
private var cloudKitStatus: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Image(systemName: syncMonitor.syncStateSummary.symbolName)
.foregroundColor(syncMonitor.syncStateSummary.symbolColor)
@@ -247,7 +201,7 @@ struct SettingsView: View {
private var canDelete: some View {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
VStack {
Toggle(String(localized: "settings_use_delete_enable"),
isOn: $deleteEnabled)
@@ -257,65 +211,16 @@ struct SettingsView: View {
.fixedSize(horizontal: false, vertical: true)
.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 {
static var previews: some View {
SettingsView(editedDataClosure: {
}, updateBoardingDataClosure: { _ in
})
SettingsView(editedDataClosure: {
}, updateBoardingDataClosure: { _ in
})
.preferredColorScheme(.dark)
}

View File

@@ -71,13 +71,13 @@ struct SharingListView: View {
//////////////////////////////////////////////////////////
WrappedSharable(preview: AnyView(
MonthTotalTemplate(isPreview: true,
startDate: Date().startOfMonth(),
endDate: Date().endOfMonth(),
startDate: Date().startOfMonth,
endDate: Date().endOfMonth,
fakeData: false)
), destination: AnyView(
MonthTotalTemplate(isPreview: false,
startDate: Date().startOfMonth(),
endDate: Date().endOfMonth(),
startDate: Date().startOfMonth,
endDate: Date().endOfMonth,
fakeData: false)
), description: MonthTotalTemplate.description),
//////////////////////////////////////////////////////////
@@ -93,7 +93,7 @@ struct SharingListView: View {
Text(String(format: String(localized: "Share your shit")))
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.padding([.top, .leading])
.frame(maxWidth: .infinity, alignment: .leading)
@@ -104,7 +104,7 @@ struct SharingListView: View {
selectedShare.showFuckingSheet = true
}, label: {
ZStack {
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
item.preview
.frame(height: 88)
@@ -113,7 +113,7 @@ struct SharingListView: View {
Spacer()
Text(item.description)
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.fontWeight(.bold)
.frame(minWidth: 0, maxWidth: .infinity)
.frame(height: 44)

View File

@@ -19,6 +19,8 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
@State var showSharingTemplate = false
@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]()
@@ -41,16 +43,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
totalEntryCount = moodEntries?.count ?? 0
if let moodEntries = 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
entries.append(MoodMetrics(mood: mood, total: total, percent: perc))
}
entries = Random.createTotalPerc(fromEntries: moodEntries)
entries = entries.sorted(by: {
$0.percent > $1.percent
})
@@ -78,7 +71,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
mood.icon
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(mood.color)
.foregroundColor(moodTint.color(forMood: mood))
}
}
@@ -86,7 +79,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
HStack {
ForEach(entries.prefix(2), id: \.mood) { model in
ZStack {
Circle().fill(model.mood.color)
Circle().fill(moodTint.color(forMood: model.mood))
Text("\(model.percent, specifier: "%.0f")%")
.font(.title)
@@ -104,7 +97,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
HStack {
ForEach(entries.suffix(3), id: \.mood) { model in
ZStack {
Circle().fill(model.mood.color)
Circle().fill(moodTint.color(forMood: model.mood))
Text("\(model.percent, specifier: "%.0f")%")
.font(.title)
@@ -124,7 +117,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
HStack {
ForEach(entries, id: \.mood) { model in
ZStack {
Circle().fill(model.mood.color)
Circle().fill(moodTint.color(forMood: model.mood))
Text("\(model.total)")
.font(.title)
@@ -144,7 +137,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
VStack {
Text(String(format: String(localized: "share_view_all_moods_total_template_title"), totalEntryCount))
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding()
@@ -203,7 +196,7 @@ struct AllMoodsTotalTemplate: View, SharingTemplate {
.padding([.leading, .trailing], -20)
} else {
mainView
.padding([.leading, .trailing])
.padding([.leading, .trailing, .top])
}
}
}

View File

@@ -23,7 +23,8 @@ struct CurrentStreakTemplate: View, SharingTemplate {
@State var showSharingTemplate = false
@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 = [
GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center),
@@ -60,7 +61,7 @@ struct CurrentStreakTemplate: View, SharingTemplate {
entry.mood.icon
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(entry.mood.color)
.foregroundColor(moodTint.color(forMood: entry.mood))
}
}
}
@@ -72,7 +73,7 @@ struct CurrentStreakTemplate: View, SharingTemplate {
VStack {
Text(String(format: String(localized: "share_view_current_streak_template_title")))
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.top)
@@ -83,7 +84,7 @@ struct CurrentStreakTemplate: View, SharingTemplate {
entry.mood.icon
.resizable()
.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)
} else {
mainView
.padding([.leading, .trailing])
.padding([.leading, .trailing, .top])
}
}
}

View File

@@ -33,7 +33,8 @@ struct LongestStreakTemplate: View, SharingTemplate {
@State var showSharingTemplate = false
@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 = [
GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center),
@@ -96,7 +97,7 @@ struct LongestStreakTemplate: View, SharingTemplate {
entry.mood.icon
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(entry.mood.color)
.foregroundColor(moodTint.color(forMood: entry.mood))
}
}
}
@@ -112,26 +113,26 @@ struct LongestStreakTemplate: View, SharingTemplate {
VStack {
Text(String(format: String(localized: "share_view_longest_streak_template_title"), self.selectedMood.strValue))
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding()
HStack {
Text(self.moodEntries.first?.forDate ?? Date(), formatter: itemFormatter)
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.top, 1)
Text("-")
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.top, 1)
Text(self.moodEntries.last?.forDate ?? Date(), formatter: itemFormatter)
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding(.top, 1)
}
@@ -144,7 +145,7 @@ struct LongestStreakTemplate: View, SharingTemplate {
entry.mood.icon
.resizable()
.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)
} else {
mainView
.padding([.leading, .trailing])
.padding([.leading, .trailing, .top])
}
}
}

View File

@@ -21,6 +21,8 @@ struct MonthTotalTemplate: View, SharingTemplate {
@State var showSharingTemplate = false
@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 moodEntries = [MoodEntry]()
@@ -59,16 +61,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
moodEntries = _moodEntries ?? [MoodEntry]()
totalEntryCount = moodEntries.count
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 = Random.createTotalPerc(fromEntries: moodEntries)
moodMetrics = moodMetrics.sorted(by: {
$0.mood.rawValue > $1.mood.rawValue
})
@@ -89,7 +82,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
HStack {
ForEach(moodMetrics, id: \.mood) { model in
ZStack {
Circle().fill(model.mood.color)
Circle().fill(moodTint.color(forMood: model.mood))
Text("\(model.percent, specifier: "%.0f")%")
.font(.title)
@@ -109,7 +102,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
VStack {
Text(String(format: String(localized: "share_view_month_moods_total_template_title"), Random.monthName(fromMonthInt: month), moodEntries.count))
.font(.title)
.foregroundColor(Color(UIColor.label))
.foregroundColor(theme.currentTheme.labelColor)
.frame(maxWidth: .infinity, alignment: .center)
.padding()
@@ -119,7 +112,7 @@ struct MonthTotalTemplate: View, SharingTemplate {
entry.mood.icon
.resizable()
.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)
} else {
mainView
.padding([.leading, .trailing])
.padding([.leading, .trailing, .top])
}
}
}
struct MonthTotalTemplate_Previews: PreviewProvider {
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)
}
}

View File

@@ -9,9 +9,10 @@ import SwiftUI
struct SmallRollUpHeaderView: View {
@Binding var viewType: MainSwitchableViewType
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults) private var moodTint: MoodTints = .Default
let entries: [MoodEntry]
private var moodMetrics = [MoodGroupingMetrics]()
private var moodMetrics = [MoodMetrics]()
init(entries: [MoodEntry], viewType: Binding<MainSwitchableViewType>) {
self.entries = entries
@@ -20,7 +21,7 @@ struct SmallRollUpHeaderView: View {
moodMetrics = Random.createTotalPerc(fromEntries: entries)
}
private func textView(forModel model: MoodGroupingMetrics) -> Text {
private func textView(forModel model: MoodMetrics) -> Text {
switch viewType {
case .total:
return Text(String(model.total))
@@ -32,24 +33,25 @@ struct SmallRollUpHeaderView: View {
}
private var textViews: some View {
HStack {
ForEach(moodMetrics, id: \.0) { model in
HStack() {
ForEach(moodMetrics, id: \.id) { model in
textView(forModel: model)
.font(.title2)
.fontWeight(.bold)
.lineLimit(1)
.foregroundColor(model.mood.color)
.frame(width: 70, height: 70)
.foregroundColor(moodTint.color(forMood: model.mood))
.frame(maxWidth: .infinity, alignment: .center)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding([.top, .bottom])
}
private var circularViews: some View {
HStack {
ForEach(moodMetrics, id: \.0) { model in
ForEach(moodMetrics, id: \.id) { model in
ZStack {
Circle().fill(model.mood.color)
Circle().fill(moodTint.color(forMood: model.mood))
.frame(minWidth: 5,
maxWidth: 70,
minHeight: 5,
@@ -60,9 +62,9 @@ struct SmallRollUpHeaderView: View {
.font(.title3)
.fontWeight(.bold)
.lineLimit(1)
.clipShape(ContainerRelativeShape()).padding()
.clipShape(ContainerRelativeShape())
.foregroundColor(Color(UIColor.white))
.minimumScaleFactor(0.1)
.minimumScaleFactor(0.7)
)
}
}
@@ -94,8 +96,13 @@ struct SmallHeaderView_Previews: PreviewProvider {
viewType: .constant(.total))
SmallRollUpHeaderView(entries: PersistenceController.shared.randomEntries(count: 10),
viewType: .constant(.total))
.frame(height: 20)
viewType: .constant(.percentageCircle))
.background(.gray)
SmallRollUpHeaderView(entries: PersistenceController.shared.randomEntries(count: 10),
viewType: .constant(.percentage))
.background(.gray)
}
}
}

View File

@@ -28,7 +28,8 @@ struct SwitchableView: View {
let daysBack: Int
@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)) {
self.daysBack = daysBack
self.headerTypeChanged = headerTypeChanged
@@ -40,7 +41,7 @@ struct SwitchableView: View {
ZStack {
switch viewType {
case .total:
HeaderStatsView(fakeData: false, backDays: daysBack)
HeaderStatsView(fakeData: false, backDays: daysBack, moodTint: moodTint)
.padding([.leading, .trailing], -15)
.padding([.top, .bottom], 8)
.allowsHitTesting(false)
@@ -75,7 +76,7 @@ struct SwitchableView: View {
.padding(.top, -12)
}
.background(
Color(theme.currentTheme.secondaryBGColor)
theme.currentTheme.secondaryBGColor
)
.contentShape(Rectangle())
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])

View File

@@ -33,6 +33,7 @@
"content_view_tab_main" = "Main";
"content_view_tab_filter" = "Filter";
"content_view_tab_share" = "Share";
"content_view_tab_customize" = "Customize";
"content_view_fill_in_missing_entry" = "Update %@";
"content_view_fill_in_missing_entry_cancel" = "Cancel";
"content_view_delete_entry" = "Delete this entry";
@@ -70,3 +71,5 @@
"share_view_month_moods_total_template_title" = "Total Entries for %@ - %d";
"share_view_current_streak_template_title" = "Last 10 Days";
"share_view_longest_streak_template_title" = "Longest consecutive days I was %@";
"customize_view_title" = "Make ifeel yours!!!";