ios-tracker/Shared/Shared.swift
rene 22b8f5d806 Initiales HabitTracker-Projekt: SwiftUI + SwiftData Gewohnheiten-Tracker
Natives iOS-App-Gerüst (Xcode 26, synchronisierte Ordner, iOS 18+).

Features:
- Gewohnheiten anlegen (Name, SF-Symbol, Farbe), heute abhaken, Streaks, Löschen
- Detailansicht mit Monatskalender (Tage nachtragbar) und Statistiken
- Tägliche Erinnerungen via lokale Notifications
- Home-Screen-Widget (klein/mittel) mit App-Group-Datenaustausch
2026-05-29 21:12:45 +02:00

61 lines
1.8 KiB
Swift

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)
}
}
}