| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- //
- // 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(.blue)
-
- var id: String { name }
-
- init() {}
-
- init(name: String, color: Color) {
- self.name = name
- self.color = color
- }
-
- var valid: Bool { !name.isEmpty }
- }
|