266 lines
8.3 KiB
Swift
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?.forDate ?? Date(), formatter: formatter)
|
|
.font(.system(.footnote))
|
|
Text(" - ")
|
|
.font(.system(.footnote))
|
|
Text(firstGroup.last?.forDate ?? 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?.forDate ?? Date(), formatter: formatter)
|
|
.font(.system(.footnote))
|
|
Text(" - ")
|
|
.font(.system(.footnote))
|
|
Text(firstGroup.last?.forDate ?? 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?.forDate ?? Date(), formatter: formatter)
|
|
.font(.system(.footnote))
|
|
Text(" - ")
|
|
Text(lastGroup.last?.forDate ?? 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)
|
|
}
|
|
}
|
|
}
|