Add an Apple Watch face complication that opens the app
A static WidgetKit accessory widget (launcher only — no data sharing, App Group, or entitlements). Tapping any accessory widget opens its containing app, so this is enough to place a Workouts button on the watch face. Supports the circular, corner, inline, and rectangular accessory families. New 'Workouts Watch Widget' app-extension target embedded in the watch app via project.yml.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
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<LauncherEntry>) -> 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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user