// ── Siri Shortcuts (App Intents) ────────────────────────────── // "Set a timer for 25 minutes", "Start Pomodoro", etc. // iOS 17+ App Intents framework import AppIntents import Foundation // MARK: - Set Timer Intent struct SetTimerIntent: AppIntent { static var title: LocalizedStringResource = "Set a Timer" static var description: IntentDescription = "Creates a countdown timer for the specified duration" static var openAppWhenRun: Bool = false @Parameter(title: "Duration (minutes)", default: 25) var minutes: Int @Parameter(title: "Label", default: "Timer") var label: String static var parameterSummary: some ParameterSummary { Summary("Set a \(\.$minutes) minute timer called \(\.$label)") } func perform() async throws -> some IntentResult & ProvidesDialog { let now = Date() let targetTime = now.addingTimeInterval(TimeInterval(minutes * 60)) let intervals = CascadePreset.minimal.defaultIntervals let snapshot = TimerSnapshot( id: UUID().uuidString, label: label, type: .countdown, urgency: .standard, state: .active, targetTime: targetTime, duration: TimeInterval(minutes * 60), startedAt: now, elapsedBeforePause: 0, snoozeCount: 0, category: nil, pomodoroCurrentRound: nil, pomodoroTotalRounds: nil, pomodoroIsBreak: nil, nextWarningTime: intervals.first.map { targetTime.addingTimeInterval(-Double($0) * 60) }, totalWarnings: intervals.count, firedWarnings: 0 ) // Write to shared data let manager = SharedTimerDataManager.shared var timers = manager.readSnapshots() timers.append(snapshot) manager.writeSnapshots(timers) manager.writeActiveTimer(nil) // Let iOS app recalculate return .result(dialog: "Timer set for \(minutes) minutes: \(label)") } } // MARK: - Start Pomodoro Intent struct StartPomodoroIntent: AppIntent { static var title: LocalizedStringResource = "Start Pomodoro" static var description: IntentDescription = "Starts a 25-minute Pomodoro focus session" static var openAppWhenRun: Bool = true @Parameter(title: "Work Minutes", default: 25) var workMinutes: Int static var parameterSummary: some ParameterSummary { Summary("Start a \(\.$workMinutes) minute Pomodoro session") } func perform() async throws -> some IntentResult & ProvidesDialog { let now = Date() let durationSeconds = TimeInterval(workMinutes * 60) let targetTime = now.addingTimeInterval(durationSeconds) let snapshot = TimerSnapshot( id: UUID().uuidString, label: "Pomodoro Focus", type: .pomodoro, urgency: .standard, state: .active, targetTime: targetTime, duration: durationSeconds, startedAt: now, elapsedBeforePause: 0, snoozeCount: 0, category: nil, pomodoroCurrentRound: 1, pomodoroTotalRounds: 4, pomodoroIsBreak: false, nextWarningTime: targetTime.addingTimeInterval(-60), totalWarnings: 1, firedWarnings: 0 ) let manager = SharedTimerDataManager.shared var timers = manager.readSnapshots() timers.append(snapshot) manager.writeSnapshots(timers) return .result(dialog: "Pomodoro started: \(workMinutes) minutes of focus time!") } } // MARK: - What's My Next Timer Intent struct NextTimerInfoIntent: AppIntent { static var title: LocalizedStringResource = "What's My Next Timer?" static var description: IntentDescription = "Tells you about your next upcoming timer" static var openAppWhenRun: Bool = false func perform() async throws -> some IntentResult & ProvidesDialog { let manager = SharedTimerDataManager.shared guard let next = manager.readNextFiringTimer() else { return .result(dialog: "You don't have any active timers right now.") } let remaining = next.remainingSeconds() let compact = formatDurationCompact(remaining) let timeStr = formatTime(next.targetTime) return .result(dialog: "\(next.label) fires in \(compact), at \(timeStr).") } } // MARK: - Shortcuts Provider struct ChronoMindShortcutsProvider: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: SetTimerIntent(), phrases: [ "Set a timer in \(.applicationName)", "Set a \(\.$minutes) minute timer in \(.applicationName)", "Start a \(\.$minutes) minute timer called \(\.$label) in \(.applicationName)", ], shortTitle: "Set Timer", systemImageName: "timer" ) AppShortcut( intent: StartPomodoroIntent(), phrases: [ "Start Pomodoro in \(.applicationName)", "Start a focus session in \(.applicationName)", "Start a \(\.$workMinutes) minute Pomodoro in \(.applicationName)", ], shortTitle: "Start Pomodoro", systemImageName: "target" ) AppShortcut( intent: NextTimerInfoIntent(), phrases: [ "What's my next timer in \(.applicationName)", "When's my next alarm in \(.applicationName)", "Next timer in \(.applicationName)", ], shortTitle: "Next Timer", systemImageName: "clock" ) } }