Intent Configuration lets the user personalise the widget
by long pressing it and tapping Edit Widget.

Instead of showing the same thing to everyone,
each user can configure what they want to see.

Static vs Intent Configuration

StaticConfiguration   → same for everyone, no customisation
AppIntentConfiguration → user can configure it from home screen

From the Project — 3 Parts

1. FocusWidgetIntent  → defines what can be configured
2. SessionOption      → the options the user can pick from
3. AppIntentConfiguration → wires it all into the widget

Part 1 — The Intent

struct FocusWidgetIntent: WidgetConfigurationIntent {
    static var title: LocalizedStringResource = "Focus Session"
    static var description = IntentDescription("Choose which session to display.")

    @Parameter(title: "Session")
    var session: SessionOption?
}
WidgetConfigurationIntent → tells system this is a widget intent
@Parameter → the thing the user can actually change
session: SessionOption? → optional because user may not have picked yet

Part 2 — The Options

enum SessionOption: String, AppEnum {
    case focus, breakTime, plan, learn, review

    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Session"
    static var caseDisplayRepresentations: [SessionOption: DisplayRepresentation] = [
        .focus:     "Focus",
        .breakTime: "Break",
        .plan:      "Plan",
        .learn:     "Learn",
        .review:    "Review"
    ]
}
AppEnum → tells system to show these as a list of options in the editor
typeDisplayRepresentation → label for the type e.g. "Session"
caseDisplayRepresentations → human readable label for each option

Part 3 — Wiring it in

struct SampleWidget: Widget {
    var body: some WidgetConfiguration {
        AppIntentConfiguration(kind: kind, intent: FocusWidgetIntent.self, provider: Provider()) { entry in
            SampleWidgetEntryView(entry: entry)
        }
    }
}
StaticConfiguration  → replaced with AppIntentConfiguration
intent: FocusWidgetIntent.self → tells system which intent to use
everything else stays the same

How the Intent Flows into the Provider

func timeline(for configuration: FocusWidgetIntent, in context: Context) async -> Timeline<SimpleEntry> {
    let index = selectedIndex(for: configuration.session)
    let entry = makeEntry(from: FocusState.all[index], index: index, date: Date())
    return Timeline(entries: [entry], policy: .never)
}
configuration.session → whatever the user picked in the editor
selectedIndex() → maps it to an array index
makeEntry() → builds the entry from that index

The Full Flow

User long presses widget
→ taps Edit Widget
→ sees "Session" picker (from @Parameter)
→ picks "Break"
→ system calls timeline() with configuration.session = .breakTime
→ widget updates to show Break / Rest / Recharge

selectedIndex — Mapping Intent to Data