You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LeCountdown/LaunchWidget/LaunchWidget.swift

154 lines
4.7 KiB

//
// LaunchWidget.swift
// LaunchWidget
//
// Created by Laurent Morvillier on 25/01/2023.
//
import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(countdowns: [], date: Date(), configuration: SelectCountdownIntent())
}
func getSnapshot(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
guard let cp = configuration.countdown
else {
completion(placeholder(in: context))
return
}
let countdowns: [Countdown] = cp.compactMap {
if let id = $0.identifier {
return IntentDataProvider.main.countdown(id: id)
} else {
return nil
}
}
let entry = SimpleEntry(countdowns: countdowns,
date: Date(),
configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: SelectCountdownIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
getSnapshot(for: configuration, in: context) { entry in
let timeline = Timeline(entries: [entry], policy: .atEnd)
completion(timeline)
}
}
}
struct SimpleEntry: TimelineEntry {
let countdowns: [Countdown]
let date: Date
let configuration: SelectCountdownIntent
}
struct CountdownSimpleWidgetView: View {
let countdown: Countdown
var body: some View {
SingleCountdownView(countdown: countdown)
.widgetURL(countdown.url)
}
}
struct CountdownMultiWidgetView: View {
let countdowns: [Countdown]
var body: some View {
MultiCountdownView(countdowns: countdowns)
}
}
struct VoidView : View {
var body: some View {
VStack {
Text("Tea!")
Text("4:00")
}
}
}
struct LaunchWidgetEntryView : View {
@Environment(\.widgetFamily) var family: WidgetFamily
var entry: Provider.Entry
@ViewBuilder
var body: some View {
switch family {
case .systemSmall, .accessoryInline:
if let countdown = entry.countdowns.first {
CountdownSimpleWidgetView(countdown: countdown)
.background(Image(countdown.imageName))
} else {
VoidView()
}
case .accessoryCircular:
if let countdown = entry.countdowns.first {
CountdownSimpleWidgetView(countdown: countdown)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black)
} else {
VoidView()
}
case .accessoryRectangular:
if let countdown = entry.countdowns.first {
CountdownSimpleWidgetView(countdown: countdown)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black)
.cornerRadius(16.0)
} else {
VoidView()
}
default:
MultiCountdownView(countdowns: entry.countdowns)
}
}
}
struct LaunchWidget: Widget {
let kind: String = "com.staxriver.launch-widget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind,
intent: SelectCountdownIntent.self,
provider: Provider()) { entry in
LaunchWidgetEntryView(entry: entry)
}
.configurationDisplayName("Launch Widget")
.description("Select and launch your countdowns")
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .accessoryRectangular, .accessoryCircular])
}
}
struct LaunchWidget_Previews: PreviewProvider {
static var previews: some View {
let fake = Countdown.fake(context: PersistenceController.preview.container.viewContext)
LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake], date: Date(), configuration: SelectCountdownIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake, fake, fake, fake], date: Date(), configuration: SelectCountdownIntent()))
.previewContext(WidgetPreviewContext(family: .systemMedium))
LaunchWidgetEntryView(entry: SimpleEntry(countdowns: [fake], date: Date(), configuration: SelectCountdownIntent()))
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
}
}