From 2590a77bffbfc0c4c555b8324e5578037c165393 Mon Sep 17 00:00:00 2001 From: Trey t Date: Wed, 2 Mar 2022 11:22:20 -0600 Subject: [PATCH] custom mood tint --- Shared/Models/MoodTintable.swift | 103 ++++++++++++++--- Shared/Models/UserDefaultsStore.swift | 26 +++++ Shared/Persisence/PersistenceGET.swift | 2 +- .../views/CustomizeView/CustomizeView.swift | 107 +++++++++++++----- Shared/views/HomeView/HomeView.swift | 9 +- Shared/views/MonthView/MonthView.swift | 15 ++- 6 files changed, 209 insertions(+), 53 deletions(-) diff --git a/Shared/Models/MoodTintable.swift b/Shared/Models/MoodTintable.swift index d616719..20b9607 100644 --- a/Shared/Models/MoodTintable.swift +++ b/Shared/Models/MoodTintable.swift @@ -14,21 +14,22 @@ protocol MoodTintable { enum MoodTints: Int, CaseIterable { case Default - case AllRed case Neon - case MonoChrome case Pastel + case Custom + + static var defaultOptions: [MoodTints] { + return [Default, Neon, Pastel] + } func color(forMood mood: Mood) -> Color { switch self { case .Default: return DefaultMoodTint.color(forMood: mood) - case .AllRed: - return AllRedMoodTint.color(forMood: mood) + case .Custom: + return CustomMoodTint.color(forMood: mood) case .Neon: return NeonMoodTint.color(forMood: mood) - case .MonoChrome: - return MonoChromeTint.color(forMood: mood) case .Pastel: return PastelTint.color(forMood: mood) } @@ -38,12 +39,10 @@ enum MoodTints: Int, CaseIterable { switch self { case .Default: return DefaultMoodTint.secondary(forMood: mood) - case .AllRed: - return AllRedMoodTint.secondary(forMood: mood) + case .Custom: + return CustomMoodTint.secondary(forMood: mood) case .Neon: return NeonMoodTint.secondary(forMood: mood) - case .MonoChrome: - return MonoChromeTint.secondary(forMood: mood) case .Pastel: return PastelTint.secondary(forMood: mood) } @@ -53,18 +52,94 @@ enum MoodTints: Int, CaseIterable { switch self { case .Default: return DefaultMoodTint.self - case .AllRed: - return AllRedMoodTint.self + case .Custom: + return CustomMoodTint.self case .Neon: return NeonMoodTint.self - case .MonoChrome: - return MonoChromeTint.self case .Pastel: return PastelTint.self } } } +final class SavedMoodTint: NSObject, ObservableObject, Codable { + @Published var colorOne: Color + @Published var colorTwo: Color + @Published var colorThree: Color + @Published var colorFour: Color + @Published var colorFive: Color + + override init() { + colorOne = Color(hex: "a92b26") + colorTwo = Color(hex: "a92b26") + colorThree = Color(hex: "a92b26") + colorFour = Color(hex: "a92b26") + colorFive = Color(hex: "a92b26") + } + + enum CodingKeys: CodingKey { + case colorOne, colorTwo, colorThree, colorFour, colorFive + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + colorOne = try container.decode(Color.self, forKey: .colorOne) + colorTwo = try container.decode(Color.self, forKey: .colorTwo) + colorThree = try container.decode(Color.self, forKey: .colorThree) + colorFour = try container.decode(Color.self, forKey: .colorFour) + colorFive = try container.decode(Color.self, forKey: .colorFive) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(colorOne, forKey: .colorOne) + try container.encode(colorTwo, forKey: .colorTwo) + try container.encode(colorThree, forKey: .colorThree) + try container.encode(colorFour, forKey: .colorFour) + try container.encode(colorFive, forKey: .colorFive) + } +} + +final class CustomMoodTint: MoodTintable { + static func color(forMood mood: Mood) -> Color { + switch mood { + case .horrible: + return UserDefaultsStore.getCustomMoodTint().colorFive + case .bad: + return UserDefaultsStore.getCustomMoodTint().colorFour + case .average: + return UserDefaultsStore.getCustomMoodTint().colorThree + case .good: + return UserDefaultsStore.getCustomMoodTint().colorTwo + case .great: + return UserDefaultsStore.getCustomMoodTint().colorOne + case .missing: + return Color(uiColor: UIColor.lightGray) + case .placeholder: + return Color(uiColor: UIColor.lightGray) + } + } + + static func secondary(forMood mood: Mood) -> Color { + switch mood { + case .horrible: + return UserDefaultsStore.getCustomMoodTint().colorFive + case .bad: + return UserDefaultsStore.getCustomMoodTint().colorFour + case .average: + return UserDefaultsStore.getCustomMoodTint().colorThree + case .good: + return UserDefaultsStore.getCustomMoodTint().colorTwo + case .great: + return UserDefaultsStore.getCustomMoodTint().colorOne + case .missing: + return Color(uiColor: UIColor.lightGray) + case .placeholder: + return Color(uiColor: UIColor.lightGray) + } + } +} + final class DefaultMoodTint: MoodTintable { static func color(forMood mood: Mood) -> Color { switch mood { diff --git a/Shared/Models/UserDefaultsStore.swift b/Shared/Models/UserDefaultsStore.swift index f50d5e2..cd59f9c 100644 --- a/Shared/Models/UserDefaultsStore.swift +++ b/Shared/Models/UserDefaultsStore.swift @@ -19,6 +19,8 @@ class UserDefaultsStore { case moodTint case personalityPack case customWidget + case customMoodTint + case customMoodTintUpdateNumber case contentViewCurrentSelectedHeaderViewBackDays case contentViewHeaderTag @@ -173,5 +175,29 @@ class UserDefaultsStore { fatalError("error saving") } } + + static func getCustomMoodTint() -> SavedMoodTint { + if let data = GroupUserDefaults.groupDefaults.object(forKey: UserDefaultsStore.Keys.customMoodTint.rawValue) as? Data{ + do { + let model = try JSONDecoder().decode(SavedMoodTint.self, from: data) + return model + } catch { + print(error) + } + } + return SavedMoodTint() + } + + @discardableResult + static func saveCustomMoodTint(customTint: SavedMoodTint) -> SavedMoodTint { + do { + let data = try JSONEncoder().encode(customTint) + GroupUserDefaults.groupDefaults.set(data, forKey: UserDefaultsStore.Keys.customMoodTint.rawValue) + return UserDefaultsStore.getCustomMoodTint() + } catch { + print(error) + fatalError("error saving") + } + } } diff --git a/Shared/Persisence/PersistenceGET.swift b/Shared/Persisence/PersistenceGET.swift index 425945d..36f0742 100644 --- a/Shared/Persisence/PersistenceGET.swift +++ b/Shared/Persisence/PersistenceGET.swift @@ -25,7 +25,7 @@ extension PersistenceController { public func getData(startDate: Date, endDate: Date, includedDays: [Int]) -> [MoodEntry] { try! viewContext.setQueryGenerationFrom(.current) - viewContext.refreshAllObjects() +// viewContext.refreshAllObjects() var includedDays16 = [Int16]() diff --git a/Shared/views/CustomizeView/CustomizeView.swift b/Shared/views/CustomizeView/CustomizeView.swift index 4b57b80..557b645 100644 --- a/Shared/views/CustomizeView/CustomizeView.swift +++ b/Shared/views/CustomizeView/CustomizeView.swift @@ -9,10 +9,17 @@ 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 + @AppStorage(UserDefaultsStore.Keys.customMoodTintUpdateNumber.rawValue, store: GroupUserDefaults.groupDefaults) private var customMoodTintUpdateNumber: Int = 0 + + @StateObject private var customMoodTint = UserDefaultsStore.getCustomMoodTint() + class StupidAssCustomWidgetObservableObject: ObservableObject { @Published var fuckingWrapped: CustomWidgetModel? = nil @Published var showFuckingSheet = false @@ -28,12 +35,6 @@ struct CustomizeView: View { 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 @@ -58,11 +59,6 @@ struct CustomizeView: View { ZStack { theme.currentTheme.secondaryBGColor VStack { - Text(String(localized: "customize_view_view_change_icon")) - .font(.body) - .foregroundColor(theme.currentTheme.labelColor) - .padding(.top) - ScrollView(.horizontal) { HStack { Button(action: { @@ -102,10 +98,6 @@ struct CustomizeView: View { ZStack { theme.currentTheme.secondaryBGColor VStack { - Text(String(localized: "customize_view_background_title")) - .font(.body) - .foregroundColor(theme.currentTheme.labelColor) - HStack { Spacer() ForEach(Theme.allCases, id:\.rawValue) { aTheme in @@ -143,10 +135,6 @@ struct CustomizeView: View { ZStack { theme.currentTheme.secondaryBGColor VStack { - Text(String(localized: "customize_view_custom_widget_title")) - .font(.body) - .foregroundColor(theme.currentTheme.labelColor) - .padding(.top) ScrollView(.horizontal) { HStack { ForEach(UserDefaultsStore.getCustomWidgets(), id: \.uuid) { widget in @@ -173,6 +161,9 @@ struct CustomizeView: View { .background(RoundedRectangle(cornerRadius: 10).fill().foregroundColor(theme.currentTheme.bgColor)) .padding() .cornerRadius(10) + + Text("[How to add widget](https://support.apple.com/guide/iphone/add-widgets-iphb8f1bf206/ios)") + .padding(.bottom) } } .fixedSize(horizontal: false, vertical: true) @@ -227,7 +218,7 @@ struct CustomizeView: View { ZStack { theme.currentTheme.secondaryBGColor VStack { - ForEach(MoodTints.allCases, id: \.rawValue) { tint in + ForEach(MoodTints.defaultOptions, id: \.rawValue) { tint in HStack { ForEach(Mood.allValues, id: \.self) { mood in Circle() @@ -250,10 +241,68 @@ struct CustomizeView: View { impactMed.impactOccurred() moodTint = tint } - if tint.rawValue != (MoodTints.allCases.sorted(by: { $0.rawValue > $1.rawValue }).first?.rawValue) ?? 0 { - Divider() - } + Divider() } + + ZStack { + Color.clear + + Rectangle() + .frame(height: 35) + .frame(minWidth: 0, maxWidth: .infinity) + .foregroundColor(.clear) + .contentShape(Rectangle()) + .onTapGesture { + moodTint = .Custom + let impactMed = UIImpactFeedbackGenerator(style: .heavy) + impactMed.impactOccurred() + } + + HStack { + ColorPicker("", selection: $customMoodTint.colorOne) + .onChange(of: customMoodTint.colorOne, perform: { _ in + saveCustomMoodTint() + }) + .labelsHidden() + .frame(minWidth: 0, maxWidth: .infinity) + + ColorPicker("", selection: $customMoodTint.colorTwo) + .labelsHidden() + .frame(minWidth: 0, maxWidth: .infinity) + .onChange(of: customMoodTint.colorTwo, perform: { _ in + saveCustomMoodTint() + }) + + ColorPicker("", selection: $customMoodTint.colorThree) + .labelsHidden() + .frame(minWidth: 0, maxWidth: .infinity) + .onChange(of: customMoodTint.colorThree, perform: { _ in + saveCustomMoodTint() + }) + + ColorPicker("", selection: $customMoodTint.colorFour) + .labelsHidden() + .frame(minWidth: 0, maxWidth: .infinity) + .onChange(of: customMoodTint.colorFour, perform: { _ in + saveCustomMoodTint() + }) + + ColorPicker("", selection: $customMoodTint.colorFive) + .labelsHidden() + .frame(minWidth: 0, maxWidth: .infinity) + .onChange(of: customMoodTint.colorFive, perform: { _ in + saveCustomMoodTint() + }) + } + .background( + Color.clear + ) + } + .background( + RoundedRectangle(cornerRadius: 10, style: .continuous) + .fill(moodTint == .Custom ? theme.currentTheme.bgColor : .clear) + .padding([.top, .bottom], -3) + ) } .padding() } @@ -261,6 +310,12 @@ struct CustomizeView: View { .cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight]) } + private func saveCustomMoodTint() { + UserDefaultsStore.saveCustomMoodTint(customTint: customMoodTint) + moodTint = .Custom + customMoodTintUpdateNumber += 1 + } + private var pickPeronsalityPack: some View { ZStack { theme.currentTheme.secondaryBGColor @@ -303,9 +358,3 @@ struct CustomizeView: View { .cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight]) } } - -struct CustomizeView_Previews: PreviewProvider { - static var previews: some View { - CustomizeView() - } -} diff --git a/Shared/views/HomeView/HomeView.swift b/Shared/views/HomeView/HomeView.swift index 2e74d2f..0e64e95 100644 --- a/Shared/views/HomeView/HomeView.swift +++ b/Shared/views/HomeView/HomeView.swift @@ -124,7 +124,7 @@ struct HomeView: View { Spacer() } .opacity(headerOpacity) - + VStack { SmallRollUpHeaderView(entries: getBackEntries(), viewType: $currentSelectedHeaderViewViewType) @@ -134,14 +134,13 @@ struct HomeView: View { theme.currentTheme.secondaryBGColor ) .cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight]) - + Spacer() } .opacity(1 - headerOpacity) } .frame(height: headerHeight + 20) - listView .padding(.top, -25) } @@ -200,7 +199,7 @@ struct HomeView: View { .frame(height: headerHeight) .frame(minWidth: 0, maxWidth: .infinity) .contentShape(Rectangle()) - + SwitchableView(daysBack: 7, viewType: $secondSwichableHeaderViewType, headerTypeChanged: { viewType in @@ -218,7 +217,7 @@ struct HomeView: View { currentSelectedHeaderViewBackDays = 30 currentSelectedHeaderViewViewType = firstSwichableHeaderViewType } - + if value == 2 { currentSelectedHeaderViewBackDays = 7 currentSelectedHeaderViewViewType = secondSwichableHeaderViewType diff --git a/Shared/views/MonthView/MonthView.swift b/Shared/views/MonthView/MonthView.swift index 78bafa2..7497a60 100644 --- a/Shared/views/MonthView/MonthView.swift +++ b/Shared/views/MonthView/MonthView.swift @@ -11,8 +11,11 @@ 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.customMoodTintUpdateNumber.rawValue, store: GroupUserDefaults.groupDefaults) private var customMoodTintUpdateNumber: Int = 0 + @ObservedObject var viewModel = HomeViewViewModel(addMonthStartWeekdayPadding: true) @StateObject private var selectedDetail = StupidAssDetailViewObservableObject() @@ -125,10 +128,14 @@ extension MonthView { // view that make up the list body extension MonthView { 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) + ZStack { + Text("\(Random.monthName(fromMonthInt: month)) \(String(year))") + .font(.body) + .foregroundColor(theme.currentTheme.labelColor) + .frame(maxWidth: .infinity, alignment: .leading) + Text(String(customMoodTintUpdateNumber)) + .hidden() + } } private func homeViewTwoMonthListView(month: Int, year: Int, entries: [MoodEntry]) -> some View {