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(timers: [], date: Date(), configuration: SelectTimerIntent())
}
func getSnapshot(for configuration: SelectTimerIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
guard let cp = configuration.timer
else {
completion(placeholder(in: context))
return
}
let timers: [AbstractTimer] = cp.compactMap {
if let id = $0.identifier {
return IntentDataProvider.main.timer(id: id)
} else {
return nil
}
}
let entry = SimpleEntry(timers: timers,
date: Date(),
configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: SelectTimerIntent, 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 timers: [AbstractTimer]
let date: Date
let configuration: SelectTimerIntent
}
struct CountdownSimpleWidgetView: View {
let timer: AbstractTimer
var body: some View {
SingleTimerView(timer: timer)
.widgetURL(timer.url)
}
}
struct CountdownMultiWidgetView: View {
let timers: [AbstractTimer]
var body: some View {
MultiCountdownView(timers: timers)
}
}
struct LaunchWidgetEntryView : View {
@Environment(\.widgetFamily) var family: WidgetFamily
var entry: Provider.Entry
let backgroundOpacity = 0.3
@ViewBuilder
var body: some View {
switch family {
case .systemSmall, .accessoryInline:
if let timer = entry.timers.first {
CountdownSimpleWidgetView(timer: timer)
} else {
DefaultView()
}
case .accessoryCircular:
Group {
if let countdown = entry.timers.first {
LockScreenCountdownView(timer: countdown)
} else {
DefaultView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.white.opacity(backgroundOpacity))
.cornerRadius(16.0)
case .accessoryRectangular:
Group {
if let timer = entry.timers.first {
LockScreenCountdownView(timer: timer)
} else {
DefaultView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.white.opacity(backgroundOpacity))
.cornerRadius(16.0)
default:
MultiCountdownView(timers: entry.timers)
}
}
}
struct LaunchWidget: Widget {
let kind: String = "com.staxriver.launch-widget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind,
intent: SelectTimerIntent.self,
provider: Provider()) { entry in
LaunchWidgetEntryView(entry: entry)
}
.configurationDisplayName("Launch Widget")
.description("Select and launch your timers")
.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(timers: [fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake, fake, fake, fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .systemMedium))
LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
LaunchWidgetEntryView(entry: SimpleEntry(timers: [fake], date: Date(), configuration: SelectTimerIntent()))
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
}
}