Files
Reflect/Shared/Models/MoodTintable.swift
Trey t bea2d3bbc9 Update Neon colors and show color circles in theme picker
- Update NeonMoodTint to use synthwave colors matching Neon voting style
  (cyan, lime, yellow, orange, magenta)
- Replace text label with 5 color circles in theme preview Colors row
- Remove unused textColor customization code and picker views
- Add .id(moodTint) to Month/Year views for color refresh
- Clean up various unused color-related code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:08:01 -06:00

354 lines
11 KiB
Swift

//
// 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 Neon
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 .Custom:
return CustomMoodTint.color(forMood: mood)
case .Neon:
return NeonMoodTint.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 .Custom:
return CustomMoodTint.secondary(forMood: mood)
case .Neon:
return NeonMoodTint.secondary(forMood: mood)
case .Pastel:
return PastelTint.secondary(forMood: mood)
}
}
/// Returns black or white text color based on the mood's background luminance
func contrastingTextColor(forMood mood: Mood) -> Color {
color(forMood: mood).contrastingTextColor
}
var moodTints: MoodTintable.Type {
switch self {
case .Default:
return DefaultMoodTint.self
case .Custom:
return CustomMoodTint.self
case .Neon:
return NeonMoodTint.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.darker(by: 40)
case .bad:
return UserDefaultsStore.getCustomMoodTint().colorFour.darker(by: 40)
case .average:
return UserDefaultsStore.getCustomMoodTint().colorThree.darker(by: 40)
case .good:
return UserDefaultsStore.getCustomMoodTint().colorTwo.darker(by: 40)
case .great:
return UserDefaultsStore.getCustomMoodTint().colorOne.darker(by: 40)
case .missing:
return Color(uiColor: UIColor.lightGray).darker(by: 40)
case .placeholder:
return Color(uiColor: UIColor.lightGray).darker(by: 40)
}
}
}
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.systemGray2)
case .placeholder:
return Color(uiColor: UIColor.systemGray2)
}
}
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 {
// Synthwave color palette matching the Neon voting style
private static let neonCyan = Color(red: 0.0, green: 1.0, blue: 0.82)
private static let neonLime = Color(red: 0.2, green: 1.0, blue: 0.6)
private static let neonYellow = Color(red: 1.0, green: 0.9, blue: 0.0)
private static let neonOrange = Color(red: 1.0, green: 0.5, blue: 0.0)
private static let neonMagenta = Color(red: 1.0, green: 0.0, blue: 0.8)
static func color(forMood mood: Mood) -> Color {
switch mood {
case .horrible:
return neonMagenta
case .bad:
return neonOrange
case .average:
return neonYellow
case .good:
return neonLime
case .great:
return neonCyan
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 neonMagenta.opacity(0.6)
case .bad:
return neonOrange.opacity(0.6)
case .average:
return neonYellow.opacity(0.6)
case .good:
return neonLime.opacity(0.6)
case .great:
return neonCyan.opacity(0.6)
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 Color(hex: "#000000")
case .bad:
return Color(hex: "#47474a")
case .average:
return Color(hex: "#7b7b81")
case .good:
return Color(hex: "#a3a3ab")
case .great:
return Color(hex: "#c2c1cb")
case .missing:
return Color(hex: "#ff0000")
case .placeholder:
return Color(hex: "#efeffb")
}
}
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.systemGray2)
}
}
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.label)
case .placeholder:
return Color(uiColor: UIColor.label)
}
}
}