import SwiftUI import WidgetKit // A launcher complication: a static button on the watch face that opens the // Workouts app. It carries no data, so the timeline is a single entry that // never refreshes. Tapping any accessory widget launches its containing app, // so no deep link or App Group is needed. private struct LauncherEntry: TimelineEntry { let date: Date } private struct LauncherProvider: TimelineProvider { func placeholder(in context: Context) -> LauncherEntry { LauncherEntry(date: .now) } func getSnapshot(in context: Context, completion: @escaping (LauncherEntry) -> Void) { completion(LauncherEntry(date: .now)) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { // Nothing ever changes — one entry, never reload. completion(Timeline(entries: [LauncherEntry(date: .now)], policy: .never)) } } private struct LauncherView: View { @Environment(\.widgetFamily) private var family private let glyph = "dumbbell.fill" var body: some View { switch family { case .accessoryInline: Label("Workouts", systemImage: glyph) case .accessoryRectangular: Label("Workouts", systemImage: glyph) .font(.headline) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) case .accessoryCorner: Image(systemName: glyph) .font(.title2) .widgetLabel("Workouts") default: // .accessoryCircular and any future families ZStack { AccessoryWidgetBackground() Image(systemName: glyph) .font(.title3) } } } } struct WorkoutsLauncherComplication: Widget { private let kind = "WorkoutsLauncher" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: LauncherProvider()) { _ in LauncherView() .containerBackground(.clear, for: .widget) } .configurationDisplayName("Open Workouts") .description("Tap to open the Workouts app.") .supportedFamilies([ .accessoryCircular, .accessoryCorner, .accessoryInline, .accessoryRectangular, ]) } } @main struct WorkoutsWatchWidgetBundle: WidgetBundle { var body: some Widget { WorkoutsLauncherComplication() } }