Files
KisaniCal/KisaniCal/WidgetBridge.swift
kutesir 5e232f2d81 feat: add widget extension — small, medium, large
- 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
2026-05-28 19:48:01 +03:00

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