import WidgetKit import SwiftUI import UIKit struct BanYaroEntry: TimelineEntry { let date: Date let data: HomeWidgetData? } struct BanYaroProvider: TimelineProvider { func placeholder(in context: Context) -> BanYaroEntry { BanYaroEntry(date: Date(), data: nil) } func getSnapshot(in context: Context, completion: @escaping (BanYaroEntry) -> Void) { completion(BanYaroEntry(date: Date(), data: HomeWidgetStore.load())) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { let entry = BanYaroEntry(date: Date(), data: HomeWidgetStore.load()) // Die App pusht bei Updates reloadAllTimelines(); als Sicherheitsnetz // stündlich neu laden. let next = Calendar.current.date(byAdding: .hour, value: 1, to: Date()) ?? Date().addingTimeInterval(3600) completion(Timeline(entries: [entry], policy: .after(next))) } } struct BanYaroHomeWidgetEntryView: View { @Environment(\.widgetFamily) private var family let entry: BanYaroEntry var body: some View { VStack(alignment: .leading, spacing: 4) { Spacer() Text(entry.data?.dogName ?? "Ban Yaro") .font(family == .systemSmall ? .headline : .title3) .bold() .foregroundStyle(.white) .shadow(radius: 3) if family != .systemSmall { if let appt = entry.data?.nextAppointment, !appt.isEmpty { Label(appt, systemImage: "calendar") .font(.caption) .foregroundStyle(.white) .shadow(radius: 3) } else if let n = entry.data?.diaryCount, n > 0 { Label("\(n) Tagebuch-Einträge", systemImage: "book") .font(.caption) .foregroundStyle(.white.opacity(0.9)) .shadow(radius: 3) } else { Text("Schön, dass du da bist 🐾") .font(.caption) .foregroundStyle(.white.opacity(0.9)) .shadow(radius: 3) } } } .frame(maxWidth: .infinity, alignment: .leading) } } struct BanYaroHomeWidget: Widget { let kind = "BanYaroHomeWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: BanYaroProvider()) { entry in BanYaroHomeWidgetEntryView(entry: entry) .containerBackground(for: .widget) { if let jpeg = entry.data?.photoJPEG, let ui = UIImage(data: jpeg) { ZStack { Image(uiImage: ui).resizable().scaledToFill() LinearGradient( colors: [.black.opacity(0.0), .black.opacity(0.55)], startPoint: .center, endPoint: .bottom ) } } else { Color.accentColor.opacity(0.25) } } } .configurationDisplayName("Ban Yaro") .description("Tagesfoto deines Hundes und nächster Termin.") .supportedFamilies([.systemSmall, .systemMedium]) } }