import WidgetKit import SwiftUI struct HabitTimelineEntry: TimelineEntry { let date: Date let snapshot: WidgetSnapshot } struct Provider: TimelineProvider { func placeholder(in context: Context) -> HabitTimelineEntry { HabitTimelineEntry(date: .now, snapshot: .empty) } func getSnapshot(in context: Context, completion: @escaping (HabitTimelineEntry) -> Void) { completion(HabitTimelineEntry(date: .now, snapshot: SharedStore.load())) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { let entry = HabitTimelineEntry(date: .now, snapshot: SharedStore.load()) // Reset "today" at the next midnight. let nextMidnight = Calendar.current.startOfDay(for: .now.addingTimeInterval(86_400)) completion(Timeline(entries: [entry], policy: .after(nextMidnight))) } } struct HabitTrackerWidgetEntryView: View { var entry: Provider.Entry @Environment(\.widgetFamily) private var family private var items: [WidgetSnapshot.Item] { entry.snapshot.items } private var doneCount: Int { items.filter(\.isDoneToday).count } var body: some View { if items.isEmpty { emptyState } else { switch family { case .systemSmall: smallView default: mediumView } } } private var emptyState: some View { VStack(spacing: 6) { Image(systemName: "checklist") .font(.title) .foregroundStyle(.secondary) Text("Keine Gewohnheiten") .font(.caption) .foregroundStyle(.secondary) } } private var header: some View { HStack { Text("Heute") .font(.caption.bold()) .foregroundStyle(.secondary) Spacer() Text("\(doneCount)/\(items.count)") .font(.caption.bold()) .foregroundStyle(.secondary) } } private var smallView: some View { VStack(alignment: .leading, spacing: 8) { header Spacer(minLength: 0) Text("\(doneCount)") .font(.system(size: 44, weight: .bold)) + Text(" / \(items.count)") .font(.title3.weight(.semibold)) .foregroundColor(.secondary) Text(doneCount == items.count ? "Alles erledigt 🎉" : "erledigt") .font(.caption) .foregroundStyle(.secondary) } } private var mediumView: some View { VStack(alignment: .leading, spacing: 8) { header ForEach(items.prefix(3)) { item in HStack(spacing: 10) { Image(systemName: item.symbolName) .foregroundStyle(Color(hex: item.colorHex)) .frame(width: 22) Text(item.name) .font(.subheadline) .lineLimit(1) Spacer() Image(systemName: item.isDoneToday ? "checkmark.circle.fill" : "circle") .foregroundStyle(item.isDoneToday ? Color(hex: item.colorHex) : .secondary) } } if items.count > 3 { Text("+ \(items.count - 3) weitere") .font(.caption2) .foregroundStyle(.secondary) } } } } struct HabitTrackerWidget: Widget { let kind = "HabitTrackerWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in HabitTrackerWidgetEntryView(entry: entry) .containerBackground(.fill.tertiary, for: .widget) } .configurationDisplayName("Gewohnheiten") .description("Dein Fortschritt von heute.") .supportedFamilies([.systemSmall, .systemMedium]) } }