// // HomeViewTwo.swift // Feels (iOS) // // Created by Trey Tartt on 2/18/22. // import SwiftUI struct MonthView: 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 @AppStorage(UserDefaultsStore.Keys.textColor.rawValue, store: GroupUserDefaults.groupDefaults) private var textColor: Color = DefaultTextColor.textColor @AppStorage(UserDefaultsStore.Keys.shape.rawValue, store: GroupUserDefaults.groupDefaults) private var shape: BGShape = .circle @StateObject private var shareImage = StupidAssShareObservableObject() // store a value that gets changed when user updates custom colors to update the view since the moodTint doesn't change @AppStorage(UserDefaultsStore.Keys.customMoodTintUpdateNumber.rawValue, store: GroupUserDefaults.groupDefaults) private var customMoodTintUpdateNumber: Int = 0 @EnvironmentObject var iapManager: IAPManager @StateObject private var selectedDetail = StupidAssDetailViewObservableObject() @State private var showingSheet = false @StateObject private var onboardingData = OnboardingDataDataManager.shared @StateObject private var filteredDays = DaysFilterClass.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)) ] @ObservedObject var viewModel: DayViewViewModel @State private var trialWarningHidden = false @State private var showSubscriptionStore = false var body: some View { ZStack { if viewModel.hasNoData { EmptyHomeView(showVote: false, viewModel: nil) .padding() } else { ScrollView { VStack(spacing: 5) { 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]) .background( GeometryReader { proxy in let offset = proxy.frame(in: .named("scroll")).minY Color.clear.preference(key: ViewOffsetKey.self, value: offset) } ) } .disabled(iapManager.shouldShowPaywall) } if iapManager.shouldShowPaywall { // Paywall overlay - tap to show subscription store Color.black.opacity(0.3) .ignoresSafeArea() .onTapGesture { showSubscriptionStore = true } VStack { Spacer() Button { showSubscriptionStore = true } label: { Text(String(localized: "subscription_required_button")) .font(.headline) .foregroundColor(.white) .frame(maxWidth: .infinity) .padding() .background(RoundedRectangle(cornerRadius: 10).fill(Color.pink)) } .padding() } } else if iapManager.shouldShowTrialWarning { VStack { Spacer() if !trialWarningHidden { IAPWarningView(iapManager: iapManager) } } } } .sheet(isPresented: $showSubscriptionStore) { FeelsSubscriptionStoreView() } .onAppear(perform: { EventLogger.log(event: "show_month_view") }) .padding([.top]) .background( theme.currentTheme.bg .edgesIgnoringSafeArea(.all) ) .sheet(isPresented: $selectedDetail.showFuckingSheet, onDismiss: didDismiss) { selectedDetail.fuckingWrapped } .sheet(isPresented: self.$shareImage.showFuckingSheet) { if let uiImage = self.shareImage.fuckingWrappedShrable { ShareSheet(photo: uiImage) } } .onPreferenceChange(ViewOffsetKey.self) { value in withAnimation { trialWarningHidden = value < 0 } } } func didDismiss() { selectedDetail.showFuckingSheet = false selectedDetail.fuckingWrapped = nil } } extension MonthView { 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() } .padding(.top, 60) .padding(.trailing) Spacer() } } } } // view that make up the list body extension MonthView { private func monthCountView(forMonth month: Int, year: Int) -> [MoodMetrics] { let (startDate, endDate) = Date.dateRange(monthInt: month, yearInt: year) let entries = PersistenceController.shared.getData(startDate: startDate, endDate: endDate, includedDays: [1,2,3,4,5,6,7]) return Random.createTotalPerc(fromEntries: entries) } private func homeViewTwoSectionHeaderView(month: Int, year: Int) -> some View { ZStack { HStack { Text("\(Random.monthName(fromMonthInt: month)) \(String(year))") .font(.body) .foregroundColor(textColor) .frame(maxWidth: .infinity, alignment: .leading) Spacer() ForEach(monthCountView(forMonth: month, year: year)) { Text("\($0.total)") .font(.body) .fontWeight(.bold) .foregroundColor($0.mood.color) } } Text(String(customMoodTintUpdateNumber)) .hidden() } } private func shareViewImage(month: Int, year: Int, entries: [MoodEntry]) -> some View { ZStack { VStack { HStack { homeViewTwoSectionHeaderView(month: month, year: year) } Divider() LazyVGrid(columns: columns, spacing: 15) { ForEach(entries, id: \.self) { entry in shape.view(withText: Text(""), bgColor: entry.mood == .placeholder ? .clear : moodTint.color(forMood: entry.mood), textColor: .clear) .frame(minHeight: 25, idealHeight: 25, maxHeight: 50, alignment: .center) } } Spacer() } .padding() .background( RoundedRectangle(cornerRadius: 10) .foregroundColor( theme.currentTheme.secondaryBGColor ) ) .padding() } .background( theme.currentTheme.bg ) .padding(.bottom, 55) } private func homeViewTwoMonthListView(month: Int, year: Int, entries: [MoodEntry]) -> some View { VStack { HStack { homeViewTwoSectionHeaderView(month: month, year: year) } Divider() LazyVGrid(columns: columns, spacing: 15) { ForEach(entries, id: \.self) { entry in if filteredDays.currentFilters.contains(Int(entry.weekDay)) { shape.view(withText: Text(""), bgColor: entry.mood == .placeholder ? .clear : moodTint.color(forMood: entry.mood), textColor: .clear) .frame(minHeight: 25, idealHeight: 25, maxHeight: 50, alignment: .center) } else { shape.view(withText: Text(""), bgColor: .clear, textColor: .clear) .frame(minHeight: 25, idealHeight: 25, maxHeight: 50, alignment: .center) } } } } .contentShape(Rectangle()) .onTapGesture{ let deailView = MonthDetailView(monthInt: month, yearInt: year, entries: entries, parentViewModel: viewModel) selectedDetail.fuckingWrapped = deailView selectedDetail.showFuckingSheet = true } } } struct MonthView_Previews: PreviewProvider { static var previews: some View { MonthView(viewModel: DayViewViewModel(addMonthStartWeekdayPadding: true)) } }