ce69aec988
Mark the dumbbell .widgetAccentable() so the watch face paints it with its main accent color instead of leaving it white.
93 lines
3.0 KiB
Swift
93 lines
3.0 KiB
Swift
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"
|
|
|
|
// The app icon's dumbbell runs lower-left to upper-right; tilt the glyph
|
|
// counter-clockwise to match (SwiftUI rotates clockwise for positive angles).
|
|
// `.widgetAccentable()` puts it in the accent group so the watch face tints
|
|
// it with its main color instead of leaving it white.
|
|
private var dumbbell: some View {
|
|
Image(systemName: glyph)
|
|
.rotationEffect(.degrees(-35))
|
|
.widgetAccentable()
|
|
}
|
|
|
|
var body: some View {
|
|
switch family {
|
|
case .accessoryInline:
|
|
// Inline templates render the symbol upright next to text; leave as-is.
|
|
Label("Workouts", systemImage: glyph)
|
|
case .accessoryRectangular:
|
|
HStack(spacing: 6) {
|
|
dumbbell.font(.title3)
|
|
Text("Workouts").font(.headline)
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
|
|
case .accessoryCorner:
|
|
dumbbell
|
|
.font(.title2)
|
|
.widgetLabel("Workouts")
|
|
default: // .accessoryCircular and any future families
|
|
ZStack {
|
|
AccessoryWidgetBackground()
|
|
dumbbell
|
|
.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()
|
|
}
|
|
}
|