2026-06-03 12:27:45 +03:00
|
|
|
|
import WidgetKit
|
|
|
|
|
|
import SwiftUI
|
|
|
|
|
|
import AppIntents
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Shared Entry
|
|
|
|
|
|
|
|
|
|
|
|
struct KisaniEntry: TimelineEntry {
|
|
|
|
|
|
let date: Date
|
|
|
|
|
|
let task: WidgetTask?
|
|
|
|
|
|
let allTasks: [WidgetTask]
|
|
|
|
|
|
let streak: Int
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Shared Provider
|
|
|
|
|
|
|
|
|
|
|
|
struct KisaniProvider: TimelineProvider {
|
|
|
|
|
|
func placeholder(in context: Context) -> KisaniEntry {
|
|
|
|
|
|
let sample = WidgetTask(id: UUID(), title: "Mums Birthday", dueDate: Date().addingTimeInterval(86400 * 60),
|
|
|
|
|
|
isComplete: false, quadrant: "Urgent + Important", category: "birthday")
|
|
|
|
|
|
return KisaniEntry(date: .now, task: sample, allTasks: [sample], streak: 7)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func getSnapshot(in context: Context, completion: @escaping (KisaniEntry) -> Void) {
|
|
|
|
|
|
let tasks = loadWidgetTasks()
|
|
|
|
|
|
completion(KisaniEntry(date: .now, task: nextDueTask(from: tasks), allTasks: tasks, streak: loadWorkoutStreak()))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func getTimeline(in context: Context, completion: @escaping (Timeline<KisaniEntry>) -> Void) {
|
|
|
|
|
|
let tasks = loadWidgetTasks()
|
|
|
|
|
|
let entry = KisaniEntry(date: .now, task: nextDueTask(from: tasks), allTasks: tasks, streak: loadWorkoutStreak())
|
|
|
|
|
|
// Refresh every 30 minutes or when app triggers WidgetCenter.reloadAllTimelines()
|
|
|
|
|
|
let next = Calendar.current.date(byAdding: .minute, value: 30, to: .now)!
|
|
|
|
|
|
completion(Timeline(entries: [entry], policy: .after(next)))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Day Progress Widget ("Day done %")
|
|
|
|
|
|
|
|
|
|
|
|
struct DayProgressWidget: Widget {
|
|
|
|
|
|
let kind = "KisaniDayProgress"
|
|
|
|
|
|
var body: some WidgetConfiguration {
|
|
|
|
|
|
StaticConfiguration(kind: kind, provider: KisaniProvider()) { _ in
|
|
|
|
|
|
ProgressDotView(period: .day, accent: Color(red: 0.48, green: 0.87, blue: 0.80))
|
|
|
|
|
|
}
|
|
|
|
|
|
.configurationDisplayName("Day Progress")
|
|
|
|
|
|
.description("How much of today has elapsed, as a dot grid.")
|
|
|
|
|
|
.supportedFamilies([.systemSmall, .systemMedium])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Tasks Done Today Widget ("Tasks complete %")
|
|
|
|
|
|
|
|
|
|
|
|
struct TasksCompleteWidget: Widget {
|
|
|
|
|
|
let kind = "KisaniTasksComplete"
|
|
|
|
|
|
var body: some WidgetConfiguration {
|
|
|
|
|
|
StaticConfiguration(kind: kind, provider: KisaniProvider()) { _ in
|
|
|
|
|
|
TasksCompleteView()
|
|
|
|
|
|
}
|
|
|
|
|
|
.configurationDisplayName("Tasks Done Today")
|
|
|
|
|
|
.description("Percentage of today's tasks you've completed.")
|
|
|
|
|
|
.supportedFamilies([.systemSmall, .systemMedium])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Lock Screen Widgets
|
|
|
|
|
|
|
|
|
|
|
|
struct LockScreenWidget: Widget {
|
|
|
|
|
|
let kind = "KisaniLockScreen"
|
|
|
|
|
|
|
|
|
|
|
|
var body: some WidgetConfiguration {
|
|
|
|
|
|
StaticConfiguration(kind: kind, provider: KisaniProvider()) { entry in
|
|
|
|
|
|
if let task = entry.task {
|
|
|
|
|
|
LockScreenRectView(task: task)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LockScreenRectView(task: WidgetTask(id: UUID(), title: "No tasks",
|
|
|
|
|
|
dueDate: nil, isComplete: false, quadrant: "Urgent + Important", category: "reminder"))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.configurationDisplayName("Task (Lock Screen)")
|
|
|
|
|
|
.description("Glass countdown on your lock screen.")
|
|
|
|
|
|
.supportedFamilies([.accessoryRectangular])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct LockScreenCircularWidget: Widget {
|
|
|
|
|
|
let kind = "KisaniLockCircle"
|
|
|
|
|
|
|
|
|
|
|
|
var body: some WidgetConfiguration {
|
|
|
|
|
|
StaticConfiguration(kind: kind, provider: KisaniProvider()) { entry in
|
|
|
|
|
|
if let task = entry.task {
|
|
|
|
|
|
LockScreenCircularView(task: task)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LockScreenCircularView(task: WidgetTask(id: UUID(), title: "–",
|
|
|
|
|
|
dueDate: nil, isComplete: false, quadrant: "Urgent + Important", category: "reminder"))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.configurationDisplayName("Days Left (Lock Screen)")
|
|
|
|
|
|
.description("Circular countdown on your lock screen.")
|
|
|
|
|
|
.supportedFamilies([.accessoryCircular])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: - Widget Bundle
|
|
|
|
|
|
|
|
|
|
|
|
@main
|
|
|
|
|
|
struct KisaniWidgetBundle: WidgetBundle {
|
|
|
|
|
|
var body: some Widget {
|
|
|
|
|
|
EventCountdownWidget()
|
2026-06-03 13:31:04 +03:00
|
|
|
|
MyTasksWidget()
|
2026-06-03 12:27:45 +03:00
|
|
|
|
DayProgressWidget()
|
|
|
|
|
|
TasksCompleteWidget()
|
|
|
|
|
|
LockScreenWidget()
|
|
|
|
|
|
LockScreenCircularWidget()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|