Files
Reflect/FeelsWidget/FeelsWidget.swift
2022-01-10 15:27:34 -06:00

266 lines
8.3 KiB
Swift

//
// FeelsWidget.swift
// FeelsWidget
//
// Created by Trey Tartt on 1/7/22.
//
import WidgetKit
import SwiftUI
import Intents
import CoreData
struct Provider: IntentTimelineProvider {
/*
placeholder for widget, no data
gets redacted auto
*/
func placeholder(in context: Context) -> SimpleEntry {
let date = Date()
let moodEntry = PersistenceController.shared.moodEntries(forStartDate: date, count: 10)
return SimpleEntry(date: date, configuration: ConfigurationIntent(), mood: moodEntry)
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
if context.isPreview {
}
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
let todayStart = calendar.startOfDay(for: Date())
let userEntries = PersistenceController.shared.moodEntries(forStartDate: todayStart, count: 10)
let entry = SimpleEntry(date: Date(), configuration: configuration, mood: userEntries)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
let todayStart = calendar.startOfDay(for: Date())
let userEntries = PersistenceController.shared.moodEntries(forStartDate: todayStart, count: 10)
let entry = SimpleEntry(date: Date(), configuration: configuration, mood: userEntries)
let timeline = Timeline(entries: [entry], policy: .after(Random.widgetUpdateTime))
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
let mood: [MoodEntry]
let showStats: Bool
init(date: Date, configuration: ConfigurationIntent, mood: [MoodEntry], showStats: Bool = false) {
self.date = date
self.configuration = configuration
self.mood = mood
self.showStats = showStats
}
}
struct FeelsWidgetEntryView : View {
@Environment(\.sizeCategory) var sizeCategory
@Environment(\.widgetFamily) var family
var entry: Provider.Entry
@ViewBuilder
var body: some View {
ZStack {
Color(UIColor.systemBackground)
switch family {
case .systemSmall:
SmallWidgetView(entry: entry)
case .systemMedium:
MediumWidgetView(entry: entry)
case .systemLarge:
LargeWidgetView(entry: entry)
case .systemExtraLarge:
LargeWidgetView(entry: entry)
@unknown default:
fatalError()
}
}
}
}
struct SmallWidgetView: View {
var entry: Provider.Entry
var body: some View {
VStack {
if let first = entry.mood.first {
EntryCardCollectionView(moodEntries: Array([first]))
.padding()
} else {
Text("🤷‍♂️")
.font(.system(size: 50))
}
}
}
}
struct MediumWidgetView: View {
var entry: Provider.Entry
var formatter: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
return dateFormatter
}
var firstGroup: [MoodEntry] {
Array(self.entry.mood.prefix(5))
}
var body: some View {
VStack {
Spacer()
HStack {
Text(firstGroup.first?.date ?? Date(), formatter: formatter)
.font(.system(.footnote))
Text(" - ")
.font(.system(.footnote))
Text(firstGroup.last?.date ?? Date(), formatter: formatter)
.font(.system(.footnote))
}
.frame(minWidth: 0, maxWidth: .infinity)
.multilineTextAlignment(.leading)
EntryCardCollectionView(moodEntries: firstGroup)
.frame(minHeight: 0, maxHeight: 55)
.padding()
Spacer()
}
}
}
struct LargeWidgetView: View {
var entry: Provider.Entry
var formatter: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
return dateFormatter
}
var firstGroup: [MoodEntry] {
Array(self.entry.mood.prefix(5))
}
var lastGroup: [MoodEntry] {
Array(self.entry.mood.suffix(5))
}
var body: some View {
VStack {
Spacer()
HStack {
Text(firstGroup.first?.date ?? Date(), formatter: formatter)
.font(.system(.footnote))
Text(" - ")
.font(.system(.footnote))
Text(firstGroup.last?.date ?? Date(), formatter: formatter)
.font(.system(.footnote))
}
.frame(minWidth: 0, maxWidth: .infinity)
.multilineTextAlignment(.leading)
EntryCardCollectionView(moodEntries: firstGroup)
.frame(minHeight: 0, maxHeight: 55)
.padding()
Spacer()
HStack {
Text(lastGroup.first?.date ?? Date(), formatter: formatter)
.font(.system(.footnote))
Text(" - ")
Text(lastGroup.last?.date ?? Date(), formatter: formatter)
.font(.system(.footnote))
}
.frame(minWidth: 0, maxWidth: .infinity)
.multilineTextAlignment(.leading)
EntryCardCollectionView(moodEntries: lastGroup)
.frame(minHeight: 0, maxHeight: 55)
.padding()
Spacer()
}
}
}
struct EntryCardCollectionView: View {
var moodEntries: [MoodEntry]
var body: some View {
ZStack {
Color(UIColor.secondarySystemBackground)
HStack {
ForEach(moodEntries) { mood in
EntryCard(moodEntry: mood)
}
}
.padding()
}
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
}
}
struct EntryCard: View {
var moodEntry: MoodEntry
var body: some View {
moodEntry.mood.icon.font(.system(size: 50))
}
}
@main
struct FeelsWidget: Widget {
let kind: String = "FeelsWidget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind,
intent: ConfigurationIntent.self,
provider: Provider()) { entry in
FeelsWidgetEntryView(entry: entry)
}
.configurationDisplayName("Feels")
.description("")
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
}
}
struct FeelsWidget_Previews: PreviewProvider {
static var previews: some View {
Group {
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
mood: PersistenceController.shared.randomEntries(count: 1)))
.previewContext(WidgetPreviewContext(family: .systemSmall))
.environment(\.sizeCategory, .small)
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
mood: PersistenceController.shared.randomEntries(count: 3)))
.previewContext(WidgetPreviewContext(family: .systemMedium))
.environment(\.sizeCategory, .medium)
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
mood: PersistenceController.shared.randomEntries(count: 10)))
.previewContext(WidgetPreviewContext(family: .systemLarge))
.environment(\.sizeCategory, .large)
}
}
}