- KisaniCalWidget: 3 sizes sharing the app's design language Small: date badge + kisaniCAL. wordmark + task count Medium: badge + task list (3 items) + workout row Large: badge + full task list (6 items) + workout row - WidgetDataStore (Shared/): lightweight Codable types for App Group UserDefaults cross-process data exchange - WidgetBridge: TaskViewModel/WorkoutViewModel extensions that sync data into App Group and call WidgetCenter.reloadAllTimelines() - ContentView: calls syncWidget() on appear and scene becoming active - project.yml + entitlements updated; project regenerated via xcodegen
42 lines
1.4 KiB
Swift
42 lines
1.4 KiB
Swift
import WidgetKit
|
|
|
|
// Syncs app ViewModels into App Group UserDefaults so the widget can read them,
|
|
// then asks WidgetKit to reload all timelines.
|
|
|
|
extension TaskViewModel {
|
|
func syncWidget() {
|
|
let cal = Calendar.current
|
|
let start = cal.startOfDay(for: Date())
|
|
let end = cal.date(byAdding: .day, value: 1, to: start)!
|
|
|
|
let entries = tasks
|
|
.filter { !$0.isComplete }
|
|
.prefix(10)
|
|
.map { t in
|
|
WidgetDataStore.WidgetTask(
|
|
id: t.id,
|
|
title: t.title,
|
|
dueDate: t.dueDate,
|
|
isToday: t.dueDate.map { $0 >= start && $0 < end } ?? false,
|
|
isOverdue: t.dueDate.map { $0 < start } ?? false
|
|
)
|
|
}
|
|
WidgetDataStore.saveTasks(Array(entries))
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
}
|
|
}
|
|
|
|
extension WorkoutViewModel {
|
|
func syncWidget() {
|
|
let weekday = Calendar.current.component(.weekday, from: Date())
|
|
let todayProgram = program(for: Date())
|
|
let workout = WidgetDataStore.WidgetWorkout(
|
|
name: activeProgram?.name ?? "Workout",
|
|
sectionsCount: activeProgram?.sections.count ?? 0,
|
|
hasWorkoutToday: todayProgram != nil
|
|
)
|
|
WidgetDataStore.saveWorkout(workout)
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
}
|
|
}
|