feat(apple/widgets): Xcode canvas previews for the Live Activity + Hosts widget

Every surface renders in the canvas without running the app or starting a
real Activity: Lock Screen banner across all four session stages
(streaming/backgrounded/reconnecting/ended), Dynamic Island
expanded/compact/minimal, and the Hosts widget in all four families with
sample hosts (plus the empty state one timeline click away). Sample state is
fileprivate to the widget files — never in PunktfunkShared.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 16:18:04 +02:00
parent 62af85eaea
commit f250db96f4
2 changed files with 120 additions and 0 deletions
@@ -184,3 +184,47 @@ private struct EmptyHostView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
// MARK: - Previews (Xcode canvas)
//
// Select the PunktfunkWidgetsExtension scheme and open the canvas (). The widget
// `#Preview(as:widget:timeline:)` form feeds sample entries directly the App-Group store is
// never read, so the canvas works without a paired device or saved hosts. The small preview's
// second entry shows the empty state one timeline click away.
private let previewHosts: [StoredHost] = [
StoredHost(
name: "Studio", address: "192.168.1.20",
lastConnected: .now.addingTimeInterval(-40 * 60)),
StoredHost(
name: "Living Room", address: "192.168.1.30",
lastConnected: .now.addingTimeInterval(-26 * 3600)),
StoredHost(
name: "Workstation", address: "10.0.0.5",
lastConnected: .now.addingTimeInterval(-6 * 86400)),
]
#Preview("Small", as: .systemSmall) {
HostsWidget()
} timeline: {
HostsEntry(date: .now, hosts: previewHosts)
HostsEntry(date: .now, hosts: [])
}
#Preview("Medium", as: .systemMedium) {
HostsWidget()
} timeline: {
HostsEntry(date: .now, hosts: previewHosts)
}
#Preview("Lock Screen circular", as: .accessoryCircular) {
HostsWidget()
} timeline: {
HostsEntry(date: .now, hosts: previewHosts)
}
#Preview("Lock Screen rectangular", as: .accessoryRectangular) {
HostsWidget()
} timeline: {
HostsEntry(date: .now, hosts: previewHosts)
}