// // Group.swift // Todos // // Created by Sam Jaffe on 3/2/26. // import Foundation import SwiftUI // https://gist.github.com/peterfriese/bb2fc5df202f6a15cc807bd87ff15193 // Inspired by https://cocoacasts.com/from-hex-to-uicolor-and-back-in-swift // Make Color codable. This includes support for transparency. // See https://www.digitalocean.com/community/tutorials/css-hex-code-colors-alpha-values extension Color: @retroactive Codable { #if os(macOS) fileprivate typealias UnifiedColor = NSColor #endif #if os(iOS) fileprivate typealias UnifiedColor = UIColor #endif init(hex: String) { var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines) hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "") var rgb: UInt64 = 0 var r: CGFloat = 0.0 var g: CGFloat = 0.0 var b: CGFloat = 0.0 var a: CGFloat = 1.0 let length = hexSanitized.count Scanner(string: hexSanitized).scanHexInt64(&rgb) if length == 6 { r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0 g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0 b = CGFloat(rgb & 0x0000FF) / 255.0 } else if length == 8 { r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0 g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0 b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0 a = CGFloat(rgb & 0x000000FF) / 255.0 } self.init(.sRGB, red: Double(r), green: Double(g), blue: Double(b), opacity: Double(a)) } public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let hex = try container.decode(String.self) self.init(hex: hex) } public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(hex) } var hex: String? { return toHex() } func toHex(alpha: Bool = false) -> String? { guard let components = UnifiedColor(self).cgColor.components, components.count >= 3 else { return nil } let r = Float(components[0]) let g = Float(components[1]) let b = Float(components[2]) var a = Float(1.0) if components.count >= 4 { a = Float(components[3]) } if alpha { return String(format: "%02lX%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255), lroundf(a * 255)) } else { return String(format: "%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255)) } } } final class Group : Identifiable, Codable { var name: String = "" var color: Color = Color(.gray) var id: String { name } init() {} init(name: String, color: Color) { self.name = name self.color = color } var valid: Bool { !name.isEmpty } }