diff --git a/Feels.xcodeproj/project.pbxproj b/Feels.xcodeproj/project.pbxproj index a161a3a..f0b0ebf 100644 --- a/Feels.xcodeproj/project.pbxproj +++ b/Feels.xcodeproj/project.pbxproj @@ -19,6 +19,14 @@ 1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C26190227960CE500FDC148 /* ChartDataBuildable.swift */; }; 1C26190727960DC900FDC148 /* ChartViewItemBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C26190627960DC900FDC148 /* ChartViewItemBuildable.swift */; }; 1C358FAD27ADD0C3002C83A6 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FAC27ADD0C3002C83A6 /* Theme.swift */; }; + 1C358FB127B0AD87002C83A6 /* SharingListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FB027B0AD87002C83A6 /* SharingListView.swift */; }; + 1C358FB327B0ADA4002C83A6 /* SharingTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FB227B0ADA4002C83A6 /* SharingTemplate.swift */; }; + 1C358FB627B0AE15002C83A6 /* AllMoodsTotalTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FB527B0AE15002C83A6 /* AllMoodsTotalTemplate.swift */; }; + 1C358FB827B0AEE3002C83A6 /* LongestStreakTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FB727B0AEE3002C83A6 /* LongestStreakTemplate.swift */; }; + 1C358FBA27B35252002C83A6 /* ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FB927B35252002C83A6 /* ActivityViewController.swift */; }; + 1C358FBE27B4D1F2002C83A6 /* CurrentStreakTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FBD27B4D1F2002C83A6 /* CurrentStreakTemplate.swift */; }; + 1C358FC027B4D20C002C83A6 /* MonthTotalTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FBF27B4D20C002C83A6 /* MonthTotalTemplate.swift */; }; + 1C358FC227B4D227002C83A6 /* WeekTotalTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C358FC127B4D227002C83A6 /* WeekTotalTemplate.swift */; }; 1C5F4976279C84090092F1B4 /* OnboardingData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5F4975279C84090092F1B4 /* OnboardingData.swift */; }; 1C5F4978279C945E0092F1B4 /* UserDefaultsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */; }; 1C683FCA2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; }; @@ -44,6 +52,8 @@ 1CAD603C27A5C1C800C520BD /* HeaderStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */; }; 1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */; }; 1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB101C427B62A2D00D1C033 /* EmptyView.swift */; }; + 1CB101C727B81CAC00D1C033 /* MoodMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */; }; + 1CB101C827B81CAC00D1C033 /* MoodMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */; }; 1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469A9278F30A0003E0C6E /* BGTask.swift */; }; 1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469AB27907D48003E0C6E /* DayChartView.swift */; }; 1CD90B07278C7DE0001C4FEA /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B06278C7DE0001C4FEA /* Tests_iOS.swift */; }; @@ -129,6 +139,14 @@ 1C26190227960CE500FDC148 /* ChartDataBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartDataBuildable.swift; sourceTree = ""; }; 1C26190627960DC900FDC148 /* ChartViewItemBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartViewItemBuildable.swift; sourceTree = ""; }; 1C358FAC27ADD0C3002C83A6 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + 1C358FB027B0AD87002C83A6 /* SharingListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingListView.swift; sourceTree = ""; }; + 1C358FB227B0ADA4002C83A6 /* SharingTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingTemplate.swift; sourceTree = ""; }; + 1C358FB527B0AE15002C83A6 /* AllMoodsTotalTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllMoodsTotalTemplate.swift; sourceTree = ""; }; + 1C358FB727B0AEE3002C83A6 /* LongestStreakTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongestStreakTemplate.swift; sourceTree = ""; }; + 1C358FB927B35252002C83A6 /* ActivityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityViewController.swift; sourceTree = ""; }; + 1C358FBD27B4D1F2002C83A6 /* CurrentStreakTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentStreakTemplate.swift; sourceTree = ""; }; + 1C358FBF27B4D20C002C83A6 /* MonthTotalTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonthTotalTemplate.swift; sourceTree = ""; }; + 1C358FC127B4D227002C83A6 /* WeekTotalTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeekTotalTemplate.swift; sourceTree = ""; }; 1C5F4975279C84090092F1B4 /* OnboardingData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingData.swift; sourceTree = ""; }; 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsStore.swift; sourceTree = ""; }; 1C683FC92792281400745862 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = ""; }; @@ -150,6 +168,7 @@ 1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderStatsView.swift; sourceTree = ""; }; 1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchableView.swift; sourceTree = ""; }; 1CB101C427B62A2D00D1C033 /* EmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyView.swift; sourceTree = ""; }; + 1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoodMetrics.swift; sourceTree = ""; }; 1CC03FA627B5865600B530AF /* Shared 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Shared 2.xcdatamodel"; sourceTree = ""; }; 1CC469A9278F30A0003E0C6E /* BGTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGTask.swift; sourceTree = ""; }; 1CC469AB27907D48003E0C6E /* DayChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayChartView.swift; sourceTree = ""; }; @@ -232,13 +251,26 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1C26190127960CDA00FDC148 /* Protocol */ = { + 1C26190127960CDA00FDC148 /* Protocols */ = { isa = PBXGroup; children = ( 1C26190227960CE500FDC148 /* ChartDataBuildable.swift */, 1C26190627960DC900FDC148 /* ChartViewItemBuildable.swift */, + 1C358FB227B0ADA4002C83A6 /* SharingTemplate.swift */, ); - path = Protocol; + path = Protocols; + sourceTree = ""; + }; + 1C358FB427B0ADF3002C83A6 /* SharingTemplates */ = { + isa = PBXGroup; + children = ( + 1C358FB527B0AE15002C83A6 /* AllMoodsTotalTemplate.swift */, + 1C358FBD27B4D1F2002C83A6 /* CurrentStreakTemplate.swift */, + 1C358FB727B0AEE3002C83A6 /* LongestStreakTemplate.swift */, + 1C358FBF27B4D20C002C83A6 /* MonthTotalTemplate.swift */, + 1C358FC127B4D227002C83A6 /* WeekTotalTemplate.swift */, + ); + path = SharingTemplates; sourceTree = ""; }; 1CA03771279A291F00D26164 /* Onboarding */ = { @@ -278,6 +310,8 @@ 1CAD602C27A5C1C800C520BD /* SettingsView.swift */, 1CAD602B27A5C1C800C520BD /* SmallRollUpHeaderView.swift */, 1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */, + 1C358FB027B0AD87002C83A6 /* SharingListView.swift */, + 1C358FB927B35252002C83A6 /* ActivityViewController.swift */, ); path = Views; sourceTree = ""; @@ -312,7 +346,7 @@ 1CD90B5C278C7EAD001C4FEA /* Random.swift */, 1C683FC92792281400745862 /* Stats.swift */, 1CA03771279A291F00D26164 /* Onboarding */, - 1C26190127960CDA00FDC148 /* Protocol */, + 1C26190127960CDA00FDC148 /* Protocols */, 1CAD602A27A5C1C800C520BD /* Views */, 1CD90B60278C7EBA001C4FEA /* Models */, 1CD90AF0278C7DE0001C4FEA /* Assets.xcassets */, @@ -383,6 +417,7 @@ 1CD90B60278C7EBA001C4FEA /* Models */ = { isa = PBXGroup; children = ( + 1C358FB427B0ADF3002C83A6 /* SharingTemplates */, 1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */, 1CC469AB27907D48003E0C6E /* DayChartView.swift */, 1C2618FD27960A4F00FDC148 /* FilterViewModel.swift */, @@ -392,6 +427,7 @@ 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */, 1C02589D27B9821700EB91AC /* CenterTiledImage.swift */, 1CEC967027B9C2BB00CC8688 /* CustomIcon.swift */, + 1CB101C627B81CAC00D1C033 /* MoodMetrics.swift */, ); path = Models; sourceTree = ""; @@ -606,6 +642,7 @@ 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 */, 1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */, 1CAD603B27A5C1C800C520BD /* ContentView.swift in Sources */, @@ -618,22 +655,30 @@ 1C2618FE27960A4F00FDC148 /* FilterViewModel.swift in Sources */, 1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */, 1CD90B63278C7EBA001C4FEA /* Mood.swift in Sources */, + 1C358FBE27B4D1F2002C83A6 /* CurrentStreakTemplate.swift in Sources */, 1CAD603527A5C1C800C520BD /* SettingsView.swift in Sources */, 1CD90B53278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */, 1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */, 1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */, 1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */, + 1CB101C727B81CAC00D1C033 /* MoodMetrics.swift in Sources */, 1CAD603627A5C1C800C520BD /* GraphView.swift in Sources */, 1CD90B66278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */, + 1C358FB327B0ADA4002C83A6 /* SharingTemplate.swift in Sources */, + 1C358FB827B0AEE3002C83A6 /* LongestStreakTemplate.swift in Sources */, + 1C358FB127B0AD87002C83A6 /* SharingListView.swift in Sources */, 1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */, 1CEC966F27B9C29300CC8688 /* IconView.swift in Sources */, 1CA0377A279A296E00D26164 /* OnboardingMain.swift in Sources */, + 1C358FBA27B35252002C83A6 /* ActivityViewController.swift in Sources */, 1C5F4978279C945E0092F1B4 /* UserDefaultsStore.swift in Sources */, 1CD90B18278C7DE0001C4FEA /* FeelsApp.swift in Sources */, + 1C358FC027B4D20C002C83A6 /* MonthTotalTemplate.swift in Sources */, 1CA03777279A295600D26164 /* OnboardingTitle.swift in Sources */, 1CEC967127B9C2BB00CC8688 /* CustomIcon.swift in Sources */, 1C358FAD27ADD0C3002C83A6 /* Theme.swift in Sources */, 1C02589C27B9677A00EB91AC /* CreateIconView.swift in Sources */, + 1C358FC227B4D227002C83A6 /* WeekTotalTemplate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -679,6 +724,7 @@ 1CD90B68278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */, 1CD90B71278C80CA001C4FEA /* Feels.xcdatamodeld in Sources */, 1C10E25127A1AB320047948B /* OnboardingTitle.swift in Sources */, + 1CB101C827B81CAC00D1C033 /* MoodMetrics.swift in Sources */, 1C683FCB2792281400745862 /* Stats.swift in Sources */, 1C10E25027A1AB220047948B /* OnboardingDay.swift in Sources */, 1C10E24F27A1AB1D0047948B /* OnboardingData.swift in Sources */, diff --git a/Feels.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Feels.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/Feels.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/Shared/Models/MoodMetrics.swift b/Shared/Models/MoodMetrics.swift new file mode 100644 index 0000000..a3cead9 --- /dev/null +++ b/Shared/Models/MoodMetrics.swift @@ -0,0 +1,15 @@ +// +// MoodMetrics.swift +// Feels +// +// Created by Trey Tartt on 2/12/22. +// + +import Foundation + +struct MoodMetrics: Identifiable { + let id = UUID() + let mood: Mood + let total: Int + let percent: Float +} diff --git a/Shared/Models/SharingTemplates/AllMoodsTotalTemplate.swift b/Shared/Models/SharingTemplates/AllMoodsTotalTemplate.swift new file mode 100644 index 0000000..b8763a3 --- /dev/null +++ b/Shared/Models/SharingTemplates/AllMoodsTotalTemplate.swift @@ -0,0 +1,200 @@ +// +// AllMoods.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/6/22. +// + +import SwiftUI + +struct AllMoodsTotalTemplate: View, SharingTemplate { + static var description: String { + "All Time Count" + } + + var isPreview: Bool + var startDate: Date + var endDate: Date + var totalEntryCount: Int = 0 + + @State var showSharingTemplate = false + @Environment(\.presentationMode) var presentationMode + + private var entries = [MoodMetrics]() + + init(isPreview: Bool, startDate: Date, endDate: Date, fakeData: Bool) { + self.isPreview = isPreview + self.startDate = startDate + self.endDate = endDate + + var moodEntries: [MoodEntry]? + + if fakeData { + moodEntries = PersistenceController.shared.randomEntries(count: 10) + } else { + + moodEntries = PersistenceController.shared.getData(startDate:startDate, + endDate: endDate, + includedDays: [1,2,3,4,5,6,7]) + } + + 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 = entries.sorted(by: { + $0.mood.rawValue > $1.mood.rawValue + }) + } else { + fatalError("no data") + } + } + + var image: UIImage { + let image = shareView.snapshot() + return image + } + + var preview: some View { + circularViews + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 100) + } + + private var circularViews: some View { + VStack { + + HStack { + ForEach(Mood.allValues, id: \.self) { mood in + mood.icon + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(mood.color) + } + } + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 100) + + HStack { + ForEach(entries, id: \.mood) { model in + ZStack { + Circle().fill(model.mood.color) + + Text("\(model.percent, specifier: "%.0f")%") + .font(.title) + .fontWeight(.bold) + .scaledToFill() + .minimumScaleFactor(0.5) + .lineLimit(1) + .foregroundColor(Color(UIColor.white)) + .padding(2) + } + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 100) + } + } + + HStack { + ForEach(entries, id: \.mood) { model in + ZStack { + Circle().fill(model.mood.color) + + Text("\(model.total)") + .font(.title) + .fontWeight(.bold) + .scaledToFill() + .minimumScaleFactor(0.5) + .lineLimit(1) + .foregroundColor(Color(UIColor.white)) + .padding(2) + } + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 100) + } + } + } + } + + var shareView: some View { + VStack { + Text(String(format: String(localized: "share_view_all_moods_total_template_title"), totalEntryCount)) + .font(.title) + .foregroundColor(Color(UIColor.label)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + + circularViews + .padding([.trailing, .leading, .top]) + + Spacer() + } + } + + var mainView: some View { + VStack { + shareView + Spacer() + HStack(alignment: .center) { + Button(action: { + showSharingTemplate = true + }, label: { + Text("Share") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.green + ) + .padding(.trailing, -5) + + Button(action: { + presentationMode.wrappedValue.dismiss() + }, label: { + Text("Exit") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.red + ) + .padding(.leading, -5) + } + .padding([.leading, .trailing], -20) + }.sheet(isPresented: $showSharingTemplate) { + ActivityViewController(activityItems: [self.image]) + } + } + + var body: some View { + if isPreview { + preview + .padding([.leading, .trailing], -20) + } else { + mainView + .padding([.leading, .trailing]) + } + } +} + +struct AllMoodsSharingTemplate_Previews: PreviewProvider { + static var previews: some View { + AllMoodsTotalTemplate(isPreview: true, startDate: Date(), endDate: Date(), fakeData: true) + + AllMoodsTotalTemplate(isPreview: false, startDate: Date(), endDate: Date(), fakeData: true) + } +} diff --git a/Shared/Models/SharingTemplates/CurrentStreakTemplate.swift b/Shared/Models/SharingTemplates/CurrentStreakTemplate.swift new file mode 100644 index 0000000..2fe3598 --- /dev/null +++ b/Shared/Models/SharingTemplates/CurrentStreakTemplate.swift @@ -0,0 +1,153 @@ +// +// CurrentStreakTemplate.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/9/22. +// + +import SwiftUI + +struct CurrentStreakTemplate: View, SharingTemplate { + var image: UIImage { + return UIImage(systemName: "square.and.arrow.up")! + } + + static var description: String { + "Last 10 Days" + } + + var isPreview: Bool + var startDate: Date + var endDate: Date + let moodEntries: [MoodEntry] + + @State var showSharingTemplate = false + @Environment(\.presentationMode) var presentationMode + + + let columns = [ + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center) + ] + + init(isPreview: Bool, startDate: Date, endDate: Date, fakeData: Bool) { + self.isPreview = isPreview + self.startDate = startDate + self.endDate = endDate + + var _moodEntries: [MoodEntry]? + + if fakeData { + _moodEntries = PersistenceController.shared.randomEntries(count: 10) + } else { + + _moodEntries = PersistenceController.shared.getData(startDate:startDate, + endDate: endDate, + includedDays: [1,2,3,4,5,6,7]) + } + + self.moodEntries = _moodEntries ?? [MoodEntry]() + } + + var preview: some View { + HStack { + VStack { + LazyVGrid(columns: columns, spacing: 0) { + ForEach(moodEntries) { entry in + entry.mood.icon + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(entry.mood.color) + } + } + } + } + .frame(height: 100) + } + + var shareView: some View { + VStack { + Text(String(format: String(localized: "share_view_current_streak_template_title"))) + .font(.title) + .foregroundColor(Color(UIColor.label)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + + HStack { + VStack { + LazyVGrid(columns: columns, spacing: 0) { + ForEach(moodEntries) { entry in + entry.mood.icon + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(entry.mood.color) + } + } + } + } + .padding() + } + } + + var mainView: some View { + VStack { + shareView + Spacer() + HStack(alignment: .center) { + Button(action: { + showSharingTemplate = true + }, label: { + Text("Share") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.green + ) + .padding(.trailing, -5) + + Button(action: { + presentationMode.wrappedValue.dismiss() + }, label: { + Text("Exit") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.red + ) + .padding(.leading, -5) + } + .padding([.leading, .trailing], -20) + }.sheet(isPresented: $showSharingTemplate) { + ActivityViewController(activityItems: [self.image]) + } + } + + var body: some View { + if isPreview { + preview + .padding([.leading, .trailing], -20) + } else { + mainView + .padding([.leading, .trailing]) + } + } +} + +struct CurrentStreakTemplate_Previews: PreviewProvider { + static var previews: some View { + CurrentStreakTemplate(isPreview: true, startDate: Date(), endDate: Date(), fakeData: true) + + CurrentStreakTemplate(isPreview: false, startDate: Date(), endDate: Date(), fakeData: true) + } +} diff --git a/Shared/Models/SharingTemplates/LongestStreakTemplate.swift b/Shared/Models/SharingTemplates/LongestStreakTemplate.swift new file mode 100644 index 0000000..3a13060 --- /dev/null +++ b/Shared/Models/SharingTemplates/LongestStreakTemplate.swift @@ -0,0 +1,234 @@ +// +// AllMoods.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/6/22. +// + +import SwiftUI +import Algorithms + +struct LongestStreakTemplate: View, SharingTemplate { + var image: UIImage { + return UIImage(systemName: "square.and.arrow.up")! + } + + static var description: String { + "Longest Streak" + } + + private let itemFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .short + return formatter + }() + + var isPreview: Bool + var startDate: Date + var endDate: Date + var fakeData: Bool + + @State var moodEntries = [MoodEntry]() + @State var selectedMood: Mood = .great + + @State var showSharingTemplate = false + @Environment(\.presentationMode) var presentationMode + + + let columns = [ + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center) + ] + + init(isPreview: Bool, startDate: Date, endDate: Date, fakeData: Bool) { + self.isPreview = isPreview + self.startDate = startDate + self.endDate = endDate + self.fakeData = fakeData + + configureData(fakeData: self.fakeData, mood: self.selectedMood) + } + + private func configureData(fakeData: Bool, mood: Mood) { + var _moodEntries: [MoodEntry]? + + if fakeData { + _moodEntries = PersistenceController.shared.randomEntries(count: 10) + } else { + + _moodEntries = PersistenceController.shared.getData(startDate:startDate, + endDate: endDate, + includedDays: [1,2,3,4,5,6,7]) + } + let data = _moodEntries ?? [MoodEntry]() + + var splitArrays = createSubArrays(fromMoodEntries: data, splitOn: mood) + splitArrays = splitArrays.sorted(by: { + $0.count > $1.count + } ) + self.moodEntries = splitArrays.first ?? [MoodEntry]() + } + + private func createSubArrays(fromMoodEntries: [MoodEntry], splitOn: Mood) -> [[MoodEntry]] { + var splitArrays = [[MoodEntry]]() + var currentSplit = [MoodEntry]() + for entry in fromMoodEntries { + if entry.mood == splitOn { + currentSplit.append(entry) + } else { + splitArrays.append(currentSplit) + currentSplit.removeAll() + } + } + // append the last grouping + splitArrays.append(currentSplit) + return splitArrays + } + + var preview: some View { + HStack { + VStack { + LazyVGrid(columns: columns, spacing: 0) { + ForEach(moodEntries) { entry in + entry.mood.icon + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(entry.mood.color) + } + } + } + } + .frame(height: 88) + .clipped() + .onAppear(perform: { + self.configureData(fakeData: self.fakeData, mood: self.selectedMood) + }) + } + + var shareView: some View { + VStack { + Text(String(format: String(localized: "share_view_longest_streak_template_title"), self.selectedMood.strValue)) + .font(.title) + .foregroundColor(Color(UIColor.label)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + + HStack { + Text(self.moodEntries.first?.forDate ?? Date(), formatter: itemFormatter) + .font(.title) + .foregroundColor(Color(UIColor.label)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + + Text("-") + .font(.title) + .foregroundColor(Color(UIColor.label)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + + Text(self.moodEntries.last?.forDate ?? Date(), formatter: itemFormatter) + .font(.title) + .foregroundColor(Color(UIColor.label)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + } + HStack { + VStack { + LazyVGrid(columns: columns, spacing: 0) { + ForEach(moodEntries) { entry in + entry.mood.icon + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(entry.mood.color) + } + } + } + } + .padding() + } + .onAppear(perform: { + self.configureData(fakeData: self.fakeData, mood: self.selectedMood) + }) + } + + var mainView: some View { + VStack { + shareView + Spacer() + Menu(content: { + ForEach(Mood.allValues) { mood in + Button(mood.strValue, action: { + selectedMood = mood + configureData(fakeData: self.fakeData, mood: self.selectedMood) + }) + } + }, label: { + Text("Moods") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color(UIColor.white)) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.green + ) + .padding([.leading, .trailing], -5) + + HStack(alignment: .center) { + Button(action: { + showSharingTemplate = true + }, label: { + Text("Share") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.green + ) + .padding(.trailing, -5) + + Button(action: { + presentationMode.wrappedValue.dismiss() + }, label: { + Text("Exit") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.red + ) + .padding(.leading, -5) + } + .padding([.leading, .trailing], -20) + }.sheet(isPresented: $showSharingTemplate) { + ActivityViewController(activityItems: [self.image]) + } + } + + var body: some View { + if isPreview { + preview + .padding([.leading, .trailing], -20) + } else { + mainView + .padding([.leading, .trailing]) + } + } +} + +struct CurrentStreakSharingTemplate_Previews: PreviewProvider { + static var previews: some View { + LongestStreakTemplate(isPreview: false, startDate: Date(), endDate: Date(), fakeData: true) + + LongestStreakTemplate(isPreview: true, startDate: Date(), endDate: Date(), fakeData: true) + } +} diff --git a/Shared/Models/SharingTemplates/MonthTotalTemplate.swift b/Shared/Models/SharingTemplates/MonthTotalTemplate.swift new file mode 100644 index 0000000..edc6a6a --- /dev/null +++ b/Shared/Models/SharingTemplates/MonthTotalTemplate.swift @@ -0,0 +1,192 @@ +// +// MonthTotalTemplate.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/9/22. +// + +import SwiftUI + +struct MonthTotalTemplate: View, SharingTemplate { + static var description: String { + "This Month" + } + + var isPreview: Bool + var startDate: Date + var endDate: Date + var totalEntryCount: Int = 0 + + private var month = Calendar.current.dateComponents([.month], from: Date()).month! + + @State var showSharingTemplate = false + @Environment(\.presentationMode) var presentationMode + + private var moodMetrics = [MoodMetrics]() + private var moodEntries = [MoodEntry]() + + let columns = [ + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center), + GridItem(.flexible(minimum: 5, maximum: .infinity), alignment: .center) + ] + + init(isPreview: Bool, startDate: Date, endDate: Date, fakeData: Bool) { + self.isPreview = isPreview + self.startDate = startDate + self.endDate = endDate + + var _moodEntries: [MoodEntry]? + + if fakeData { + _moodEntries = PersistenceController.shared.randomEntries(count: 10) + } else { + + _moodEntries = PersistenceController.shared.getData(startDate: startDate, + endDate: endDate, + includedDays: [1,2,3,4,5,6,7]) + + // _moodEntries = PersistenceController.shared.getData(startDate:Calendar.current.date(byAdding: .day, value: -33, to: Date())!, + // endDate: Date(), + // includedDays: [1,2,3,4,5,6,7]) + + } + + 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 = moodMetrics.sorted(by: { + $0.mood.rawValue > $1.mood.rawValue + }) + } + + var image: UIImage { + let image = shareView.snapshot() + return image + } + + var preview: some View { + circularViews + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 100) + } + + private var circularViews: some View { + HStack { + ForEach(moodMetrics, id: \.mood) { model in + ZStack { + Circle().fill(model.mood.color) + + Text("\(model.percent, specifier: "%.0f")%") + .font(.title) + .fontWeight(.bold) + .minimumScaleFactor(0.5) + .lineLimit(1) + .foregroundColor(Color(UIColor.white)) + .padding(5) + } + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 100) + } + } + } + + var shareView: some View { + 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)) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.top, 1) + + VStack { + LazyVGrid(columns: columns, spacing: 0) { + ForEach(moodEntries) { entry in + entry.mood.icon + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(entry.mood.color) + } + } + } + + circularViews + .padding([.trailing, .leading, .top]) + + Spacer() + } + } + + var mainView: some View { + VStack { + shareView + Spacer() + HStack(alignment: .center) { + Button(action: { + showSharingTemplate = true + }, label: { + Text("Share") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.green + ) + .padding(.trailing, -5) + + Button(action: { + presentationMode.wrappedValue.dismiss() + }, label: { + Text("Exit") + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color.white) + .padding(.top, 20) + }) + .frame(maxWidth: .infinity, alignment: .center) + .background( + Color.red + ) + .padding(.leading, -5) + } + .padding([.leading, .trailing], -20) + }.sheet(isPresented: $showSharingTemplate) { + ActivityViewController(activityItems: [self.image]) + } + } + + var body: some View { + if isPreview { + preview + .padding([.leading, .trailing], -20) + } else { + mainView + .padding([.leading, .trailing]) + } + } +} + +struct MonthTotalTemplate_Previews: PreviewProvider { + static var previews: some View { + MonthTotalTemplate(isPreview: true, startDate: Date().startOfMonth(), endDate: Date().endOfMonth(), fakeData: true) + + MonthTotalTemplate(isPreview: false, startDate: Date().startOfMonth(), endDate: Date().endOfMonth(), fakeData: true) + } +} diff --git a/Shared/Models/SharingTemplates/WeekTotalTemplate.swift b/Shared/Models/SharingTemplates/WeekTotalTemplate.swift new file mode 100644 index 0000000..f4c65ec --- /dev/null +++ b/Shared/Models/SharingTemplates/WeekTotalTemplate.swift @@ -0,0 +1,48 @@ +// +// WeekTotalTemplate.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/9/22. +// + +import SwiftUI + +struct WeekTotalTemplate: View, SharingTemplate { + static var description: String { + "WeekTotalTemplate" + } + + var image: UIImage { + return UIImage(systemName: "square.and.arrow.up")! + } + + var isPreview: Bool + + var startDate: Date + var endDate: Date + + var preview: some View { + Rectangle() + .frame(width: 150, height: 50, alignment: .leading) + } + + var mainView: some View { + Text("WeekTotalTemplate body") + } + + var body: some View { + if isPreview { + preview + } else { + mainView + } + } +} + +struct WeekTotalTemplate_Previews: PreviewProvider { + static var previews: some View { + WeekTotalTemplate(isPreview: true, startDate: Date(), endDate: Date()) + + WeekTotalTemplate(isPreview: false, startDate: Date(), endDate: Date()) + } +} diff --git a/Shared/Persistence.swift b/Shared/Persistence.swift index babd85a..226d09e 100644 --- a/Shared/Persistence.swift +++ b/Shared/Persistence.swift @@ -21,6 +21,11 @@ class PersistenceController { return PersistenceController.shared.container.viewContext } + private var childContext: NSManagedObjectContext { + return NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) + } + + public var switchContainerListeners = [(() -> Void)]() public func getEntry(byDate date: Date) -> MoodEntry? { @@ -185,7 +190,7 @@ class PersistenceController { var entries = [MoodEntry]() for idx in 0.. [MoodEntry] { +// let predicate = NSPredicate(format: "forDate == %@", date as NSDate) + + let fetchRequest = NSFetchRequest(entityName: "MoodEntry") +// fetchRequest.predicate = predicate + fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)] + let data = try! viewContext.fetch(fetchRequest) + return data + } +} class NSCustomPersistentContainer: NSPersistentContainer { override open class func defaultDirectoryURL() -> URL { diff --git a/Shared/Protocol/ChartDataBuildable.swift b/Shared/Protocols/ChartDataBuildable.swift similarity index 100% rename from Shared/Protocol/ChartDataBuildable.swift rename to Shared/Protocols/ChartDataBuildable.swift diff --git a/Shared/Protocol/ChartViewItemBuildable.swift b/Shared/Protocols/ChartViewItemBuildable.swift similarity index 100% rename from Shared/Protocol/ChartViewItemBuildable.swift rename to Shared/Protocols/ChartViewItemBuildable.swift diff --git a/Shared/Protocols/SharingTemplate.swift b/Shared/Protocols/SharingTemplate.swift new file mode 100644 index 0000000..334954e --- /dev/null +++ b/Shared/Protocols/SharingTemplate.swift @@ -0,0 +1,23 @@ +// +// SharingTemplate.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/6/22. +// + +import Foundation +import SwiftUI + +protocol SharingTemplate { + associatedtype MainView : View + associatedtype Preview : View + + var startDate: Date { get } + var endDate: Date { get } + var isPreview: Bool { get } + var image: UIImage { get } + static var description: String { get } + + @ViewBuilder var mainView: Self.MainView { get } + @ViewBuilder var preview: Self.Preview { get } +} diff --git a/Shared/Random.swift b/Shared/Random.swift index 9a53a1b..38b0fbd 100644 --- a/Shared/Random.swift +++ b/Shared/Random.swift @@ -59,6 +59,30 @@ extension Date: RawRepresentable { 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! + } } @@ -77,6 +101,18 @@ extension View { func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View { clipShape( RoundedCorner(radius: radius, corners: corners) ) } + + func snapshot() -> UIImage { + let controller = UIHostingController(rootView: self) + let view = controller.view + let targetSize = controller.view.intrinsicContentSize + view?.bounds = CGRect(origin: .zero, size: targetSize) + view?.backgroundColor = .clear + let renderer = UIGraphicsImageRenderer(size: targetSize) + return renderer.image { _ in + view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true) + } + } } extension Date { diff --git a/Shared/views/ActivityViewController.swift b/Shared/views/ActivityViewController.swift new file mode 100644 index 0000000..985eb56 --- /dev/null +++ b/Shared/views/ActivityViewController.swift @@ -0,0 +1,16 @@ +import UIKit +import SwiftUI + +struct ActivityViewController: UIViewControllerRepresentable { + + var activityItems: [Any] + var applicationActivities: [UIActivity]? = nil + + func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIActivityViewController { + let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities) + return controller + } + + func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext) {} + +} diff --git a/Shared/views/ContentView.swift b/Shared/views/ContentView.swift index 418c8cc..87e65e2 100644 --- a/Shared/views/ContentView.swift +++ b/Shared/views/ContentView.swift @@ -66,9 +66,9 @@ struct ContentView: View { Label(String(localized: "content_view_tab_filter"), systemImage: "calendar.circle") } - GraphView() + SharingListView() .tabItem { - Label(String(localized: "content_view_tab_stats"), systemImage: "chart.line.uptrend.xyaxis") + Label(String(localized: "content_view_tab_share"), systemImage: "square.and.arrow.up") } }.sheet(isPresented: $needsOnboarding, onDismiss: { diff --git a/Shared/views/SharingListView.swift b/Shared/views/SharingListView.swift new file mode 100644 index 0000000..c8fbf6c --- /dev/null +++ b/Shared/views/SharingListView.swift @@ -0,0 +1,151 @@ +// +// SharingView.swift +// Feels (iOS) +// +// Created by Trey Tartt on 2/6/22. +// + +import SwiftUI + +struct WrappedSharable: Hashable, Equatable { + static func == (lhs: WrappedSharable, rhs: WrappedSharable) -> Bool { + lhs.id == rhs.id && lhs.description == rhs.description + } + + func hash(into hasher: inout Hasher) { + hasher.combine(id) + } + + let id = UUID() + let preview: AnyView + let destination: AnyView + let description: String +} + +struct SharingListView: View { + @AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system + + class StupidAssObservableObject: ObservableObject { + @Published var fuckingWrappedShrable: WrappedSharable? = nil + @Published var showFuckingSheet = false + } + + @StateObject private var selectedShare = StupidAssObservableObject() + + let sharebleItems: [WrappedSharable] = [ + WrappedSharable(preview: AnyView( + AllMoodsTotalTemplate(isPreview: true, + startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(), + endDate: Date(), + fakeData: false) + ),destination: AnyView( + AllMoodsTotalTemplate(isPreview: false, + startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(), + endDate: Date(), + fakeData: false) + ),description: AllMoodsTotalTemplate.description), + ////////////////////////////////////////////////////////// + WrappedSharable(preview: AnyView( + CurrentStreakTemplate(isPreview: true, + startDate: Calendar.current.date(byAdding: .day, value: -10, to: Date())!, + endDate: Date(), + fakeData: false) + ), destination: AnyView( + CurrentStreakTemplate(isPreview: false, + startDate: Calendar.current.date(byAdding: .day, value: -10, to: Date())!, + endDate: Date(), + fakeData: false) + ), description: CurrentStreakTemplate.description), + ////////////////////////////////////////////////////////// + WrappedSharable(preview: AnyView( + LongestStreakTemplate(isPreview: true, + startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(), + endDate: Date(), + fakeData: false) + ), destination: AnyView( + LongestStreakTemplate(isPreview: false, + startDate: PersistenceController.shared.earliestEntry?.forDate ?? Date(), + endDate: Date(), + fakeData: false) + ), description: LongestStreakTemplate.description), + ////////////////////////////////////////////////////////// + WrappedSharable(preview: AnyView( + MonthTotalTemplate(isPreview: true, + startDate: Date().startOfMonth(), + endDate: Date().endOfMonth(), + fakeData: false) + ), destination: AnyView( + MonthTotalTemplate(isPreview: false, + startDate: Date().startOfMonth(), + endDate: Date().endOfMonth(), + fakeData: false) + ), description: MonthTotalTemplate.description), + ////////////////////////////////////////////////////////// + ] + + func didDismiss() { + selectedShare.showFuckingSheet = false + selectedShare.fuckingWrappedShrable = nil + } + + var body: some View { + VStack { + Text(String(format: String(localized: "Share your shit"))) + .font(.title) + .fontWeight(.bold) + .foregroundColor(Color(UIColor.label)) + .padding([.top, .leading]) + .frame(maxWidth: .infinity, alignment: .leading) + + ScrollView { + ForEach(sharebleItems, id: \.self) { item in + Button(action: { + selectedShare.fuckingWrappedShrable = item + selectedShare.showFuckingSheet = true + }, label: { + ZStack { + Color(theme.currentTheme.secondaryBGColor) + + item.preview + .frame(height: 88) + + VStack { + Spacer() + Text(item.description) + .font(.title) + .foregroundColor(Color(UIColor.label)) + .fontWeight(.bold) + .frame(minWidth: 0, maxWidth: .infinity) + .frame(height: 44) + .background( + Color(UIColor.secondarySystemBackground) + ) + .opacity(0.9) + } + } + .frame(height: 88) + .cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight]) + .scaledToFill() + .clipped() + .contentShape(Path(CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 88))) + .padding([.leading, .trailing]) + }) + } + + }.background( + theme.currentTheme.bg + .edgesIgnoringSafeArea(.all) + ) + } + .sheet(isPresented: $selectedShare.showFuckingSheet, + onDismiss: didDismiss) { + selectedShare.fuckingWrappedShrable?.destination + } + } +} + +struct SharingView_Previews: PreviewProvider { + static var previews: some View { + SharingListView() + } +} diff --git a/en.lproj/Localizable.strings b/en.lproj/Localizable.strings index d25fc25..73ba908 100644 --- a/en.lproj/Localizable.strings +++ b/en.lproj/Localizable.strings @@ -32,7 +32,7 @@ "content_view_tab_main" = "Main"; "content_view_tab_filter" = "Filter"; -"content_view_tab_stats" = "Stats"; +"content_view_tab_share" = "Share"; "content_view_fill_in_missing_entry" = "Update %@"; "content_view_fill_in_missing_entry_cancel" = "Cancel"; "content_view_delete_entry" = "Delete this entry"; @@ -65,3 +65,8 @@ "mood_value_horrible" = "Horrible"; "mood_value_missing" = "Missing"; "mood_value_missing_tap_to_add" = "Missing - Tap to add"; + +"share_view_all_moods_total_template_title" = "Total Entries: %d"; +"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 %@";