import SwiftUI // MARK: - Snapshot shared between app and widget struct WidgetSnapshot: Codable { struct Item: Codable, Identifiable { var id: UUID var name: String var symbolName: String var colorHex: String var isDoneToday: Bool } var generatedAt: Date var items: [Item] static let empty = WidgetSnapshot(generatedAt: .now, items: []) } // MARK: - App Group backed store enum SharedStore { static let appGroupID = "group.de.motocamp.HabitTracker" private static let key = "widgetSnapshot" private static var defaults: UserDefaults? { UserDefaults(suiteName: appGroupID) } static func save(_ snapshot: WidgetSnapshot) { guard let data = try? JSONEncoder().encode(snapshot) else { return } defaults?.set(data, forKey: key) } static func load() -> WidgetSnapshot { guard let data = defaults?.data(forKey: key), let snapshot = try? JSONDecoder().decode(WidgetSnapshot.self, from: data) else { return .empty } return snapshot } } // MARK: - Color from hex (used by both targets) extension Color { /// Creates a color from a "#RRGGBB" hex string. Falls back to system green on bad input. init(hex: String) { let cleaned = hex.trimmingCharacters(in: CharacterSet(charactersIn: "#")) var value: UInt64 = 0 Scanner(string: cleaned).scanHexInt64(&value) if cleaned.count == 6 { let r = Double((value >> 16) & 0xFF) / 255 let g = Double((value >> 8) & 0xFF) / 255 let b = Double(value & 0xFF) / 255 self.init(.sRGB, red: r, green: g, blue: b) } else { self.init(.sRGB, red: 52 / 255, green: 199 / 255, blue: 89 / 255) } } }