Section 11/181 menit

11. Control Widgets (iOS 18+)

11. Control Widgets (iOS 18+)

Control Widgets adalah shortcut interaktif di Control Center dan Lock Screen — satu tap langsung eksekusi App Intent.

swift
import WidgetKit
import SwiftUI
import AppIntents

// Toggle Control: dua state (on/off), tap untuk toggle
struct FocusModeControl: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlWidget(kind: "FocusModeControl") {
            FocusModeControlView()
        }
        .displayName("Mode Fokus")
        .description("Aktifkan atau nonaktifkan mode fokus.")
    }
}

struct FocusModeControlView: View {
    // Baca state dari App
    @Environment(\.controlWidgetValue) var isFocusActive: Bool
    
    var body: some View {
        // ControlWidgetToggle: tombol toggle dengan intent
        ControlWidgetToggle(
            "Mode Fokus",
            isOn: isFocusActive,
            action: ToggleFocusModeIntent()
        ) { isActive in
            Label(
                isActive ? "Fokus Aktif" : "Fokus Nonaktif",
                systemImage: isActive ? "moon.fill" : "moon"
            )
        }
    }
}

struct ToggleFocusModeIntent: SetValueIntent {
    static var title: LocalizedStringResource = "Toggle Mode Fokus"
    
    @Parameter(title: "Aktif")
    var value: Bool
    
    func perform() async throws -> some IntentResult {
        await FocusService.shared.setActive(value)
        return .result()
    }
}

// Button Control: aksi satu arah (tidak ada state toggle)
struct QuickTimerControl: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlWidget(kind: "QuickTimerControl") {
            ControlWidgetButton(action: StartQuickTimerIntent()) {
                Label("25 Menit", systemImage: "timer")
            }
        }
        .displayName("Timer Cepat")
        .description("Mulai timer 25 menit sekali tap.")
    }
}

struct StartQuickTimerIntent: AppIntent {
    static var title: LocalizedStringResource = "Mulai Timer Cepat"
    
    func perform() async throws -> some IntentResult {
        try await TimerService.shared.start(minutes: 25, label: "Fokus")
        return .result()
    }
}