work around widgets ... not sure if they work

This commit is contained in:
Trey t
2022-01-15 18:05:48 -06:00
parent 0298b3bf5e
commit 7c2de764b4
23 changed files with 375 additions and 199 deletions

View File

@@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "meh-regular.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="meh" class="svg-inline--fa fa-meh fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"></path></svg>

After

Width:  |  Height:  |  Size: 610 B

View File

@@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "frown-regular.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="frown" class="svg-inline--fa fa-frown fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"></path></svg>

After

Width:  |  Height:  |  Size: 748 B

View File

@@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "grin-regular.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="grin" class="svg-inline--fa fa-grin fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm105.6-151.4c-25.9 8.3-64.4 13.1-105.6 13.1s-79.6-4.8-105.6-13.1c-9.9-3.1-19.4 5.4-17.7 15.3 7.9 47.1 71.3 80 123.3 80s115.3-32.9 123.3-80c1.6-9.8-7.7-18.4-17.7-15.3zM168 240c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32z"></path></svg>

After

Width:  |  Height:  |  Size: 690 B

View File

@@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "smile-beam-regular.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="smile-beam" class="svg-inline--fa fa-smile-beam fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm84-143.4c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.6-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.2-8.4-25.3-7.1-33.8 3.1zM136.5 211c7.7-13.7 19.2-21.6 31.5-21.6s23.8 7.9 31.5 21.6l9.5 17c2.1 3.7 6.2 4.7 9.3 3.7 3.6-1.1 6-4.5 5.7-8.3-3.3-42.1-32.2-71.4-56-71.4s-52.7 29.3-56 71.4c-.3 3.7 2.1 7.2 5.7 8.3 3.4 1.1 7.4-.5 9.3-3.7l9.5-17zM328 152c-23.8 0-52.7 29.3-56 71.4-.3 3.7 2.1 7.2 5.7 8.3 3.5 1.1 7.4-.5 9.3-3.7l9.5-17c7.7-13.7 19.2-21.6 31.5-21.6s23.8 7.9 31.5 21.6l9.5 17c2.1 3.7 6.2 4.7 9.3 3.7 3.6-1.1 6-4.5 5.7-8.3-3.3-42.1-32.2-71.4-56-71.4z"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "sad-tear-regular.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="sad-tear" class="svg-inline--fa fa-sad-tear fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm8-152c-13.2 0-24 10.8-24 24s10.8 24 24 24c23.8 0 46.3 10.5 61.6 28.8 8.1 9.8 23.2 11.9 33.8 3.1 10.2-8.5 11.6-23.6 3.1-33.8C330 320.8 294.1 304 256 304zm-88-64c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-165.6 98.8C151 290.1 126 325.4 126 342.9c0 22.7 18.8 41.1 42 41.1s42-18.4 42-41.1c0-17.5-25-52.8-36.4-68.1-2.8-3.7-8.4-3.7-11.2 0z"></path></svg>

After

Width:  |  Height:  |  Size: 817 B

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "exclamation-solid.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="exclamation" class="svg-inline--fa fa-exclamation fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M176 432c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zM25.26 25.199l13.6 272C39.499 309.972 50.041 320 62.83 320h66.34c12.789 0 23.331-10.028 23.97-22.801l13.6-272C167.425 11.49 156.496 0 142.77 0H49.23C35.504 0 24.575 11.49 25.26 25.199z"></path></svg>

After

Width:  |  Height:  |  Size: 508 B

View File

@@ -10,39 +10,97 @@ import SwiftUI
import Intents
import CoreData
class WatchTimelineView: Identifiable {
let id = UUID()
let image: Image
let date: Date
let color: Color
init(image: Image, date: Date, color: Color) {
self.image = image
self.date = date
self.color = color
}
}
struct TimeLineCreator {
static func getData() -> [MoodEntry] {
let dateAtEnd = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: Date())!
var tenDaysAgo = Calendar.current.date(byAdding: .day, value: -10, to: dateAtEnd)!
tenDaysAgo = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: tenDaysAgo)!
let moodEntry = PersistenceController.shared.getData(startDate: tenDaysAgo, endDate: dateAtEnd, includedDays: [1,2,3,4,5,6,7])
return moodEntry
}
static func createTimeLineViews(fromEntries: [MoodEntry]) -> [WatchTimelineView] {
var returnViews = [WatchTimelineView]()
for pastDays in 0...10 {
let pastDate = Calendar.current.date(byAdding: .day, value: -pastDays, to: Date())!
if let item = fromEntries.filter({ entry in
let components = Calendar.current.dateComponents([.day, .month, .year], from: pastDate)
let day = components.day
let month = components.month
let year = components.year
let entryComponents = Calendar.current.dateComponents([.day, .month, .year], from: entry.forDate!)
let entryDay = entryComponents.day
let entryMonth = entryComponents.month
let entryYear = entryComponents.year
return day == entryDay && month == entryMonth && year == entryYear
}).first {
let timeLineView = WatchTimelineView(image: item.mood.icon, date: pastDate, color: item.mood.color)
returnViews.append(timeLineView)
} else {
let timeLineView = WatchTimelineView(image: Mood.missing.icon, date: pastDate, color: Mood.missing.color)
returnViews.append(timeLineView)
}
}
return returnViews
}
}
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)
var sampleViews = [WatchTimelineView]()
for pastDay in 0...10 {
let pastDate = Calendar.current.date(byAdding: .day, value: -pastDay, to: Date())!
let mood = Mood.allValues.randomElement()!
sampleViews.append( WatchTimelineView(image: mood.icon, date: pastDate, color: mood.color) )
}
return SimpleEntry(date: Date(), configuration: ConfigurationIntent(), timeLineViews: sampleViews)
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
var timeLineViews = [WatchTimelineView]()
if context.isPreview {
for pastDay in 0...10 {
let pastDate = Calendar.current.date(byAdding: .day, value: -pastDay, to: Date())!
let mood = Mood.allValues.randomElement()!
timeLineViews.append( WatchTimelineView(image: mood.icon, date: pastDate, color: mood.color) )
}
} else {
let data = TimeLineCreator.getData()
timeLineViews = TimeLineCreator.createTimeLineViews(fromEntries: data)
}
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 entry = SimpleEntry(date: Date(), configuration: configuration, timeLineViews: timeLineViews)
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 data = TimeLineCreator.getData()
let views = TimeLineCreator.createTimeLineViews(fromEntries: data)
let entry = SimpleEntry(date: Date(), configuration: configuration, mood: userEntries)
let timeline = Timeline(entries: [entry], policy: .after(Random.widgetUpdateTime))
let entry = SimpleEntry(date: Date(), configuration: configuration, timeLineViews: views)
let timeline = Timeline(entries: [entry], policy: .after(Random.tomorrowMidnightThirty))
completion(timeline)
}
}
@@ -50,13 +108,13 @@ struct Provider: IntentTimelineProvider {
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
let mood: [MoodEntry]
let timeLineViews: [WatchTimelineView]
let showStats: Bool
init(date: Date, configuration: ConfigurationIntent, mood: [MoodEntry], showStats: Bool = false) {
init(date: Date, configuration: ConfigurationIntent, timeLineViews: [WatchTimelineView], showStats: Bool = false) {
self.date = date
self.configuration = configuration
self.mood = mood
self.timeLineViews = timeLineViews
self.showStats = showStats
}
}
@@ -71,19 +129,21 @@ struct FeelsWidgetEntryView : View {
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)
MediumWidgetView(entry: entry)
case .systemExtraLarge:
LargeWidgetView(entry: entry)
MediumWidgetView(entry: entry)
@unknown default:
fatalError()
}
}.onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
// make sure you don't call this too often
WidgetCenter.shared.reloadAllTimelines()
}
}
}
@@ -92,14 +152,55 @@ 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))
ZStack {
Color(UIColor.secondarySystemBackground)
HStack {
ForEach([entry.timeLineViews.first!]) { watchView in
EntryCard(timeLineView: watchView)
}
}
.padding()
}
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
.frame(minHeight: 0, maxHeight: 55)
.padding()
}
}
struct TimeHeaderView: View {
let startDate: Date
let endDate: Date
var formatter: DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
return dateFormatter
}
var body: some View {
HStack {
Text(startDate, formatter: formatter)
.font(.system(.footnote))
Text(" - ")
.font(.system(.footnote))
Text(endDate, formatter: formatter)
.font(.system(.footnote))
}
}
}
struct TimeBodyView: View {
let group: [WatchTimelineView]
var body: some View {
ZStack {
Color(UIColor.secondarySystemBackground)
HStack {
ForEach(group) { watchView in
EntryCard(timeLineView: watchView)
}
}
.padding()
}
}
}
@@ -107,32 +208,20 @@ struct SmallWidgetView: View {
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 firstGroup: [WatchTimelineView] {
Array(self.entry.timeLineViews.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)
TimeHeaderView(startDate: firstGroup.first!.date, endDate: firstGroup.last!.date)
.frame(minWidth: 0, maxWidth: .infinity)
.multilineTextAlignment(.leading)
EntryCardCollectionView(moodEntries: firstGroup)
TimeBodyView(group: firstGroup)
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
.frame(minHeight: 0, maxHeight: 55)
.padding()
@@ -141,86 +230,47 @@ struct MediumWidgetView: View {
}
}
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 LargeWidgetView: View {
// var entry: Provider.Entry
//
// var formatter: DateFormatter {
// let dateFormatter = DateFormatter()
// dateFormatter.dateStyle = .medium
// return dateFormatter
// }
//
//
// var body: some View {
// VStack {
// Spacer()
//
// ForEach([Array(self.entry.timeLineViews.prefix(5)), Array(self.entry.timeLineViews.suffix(5))]) { group in
//
// TimeHeaderView(startDate: group.first!, endDate: group.last!)
// .frame(minWidth: 0, maxWidth: .infinity)
// .multilineTextAlignment(.leading)
//
// TimeBodyView(group: group)
// .clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
// .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 timeLineView: WatchTimelineView
var body: some View {
moodEntry.mood.icon.font(.system(size: 50))
timeLineView.image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50, alignment: .center)
.foregroundColor(timeLineView.color)
}
}
@@ -236,30 +286,37 @@ struct FeelsWidget: Widget {
}
.configurationDisplayName("Feels")
.description("")
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
.supportedFamilies([.systemSmall, .systemMedium])
}
}
struct FeelsWidget_Previews: PreviewProvider {
static var data: [WatchTimelineView] {
var data = PersistenceController.shared.randomEntries(count: 10)
data.remove(at: 2)
let views = TimeLineCreator.createTimeLineViews(fromEntries: data)
return views
}
static var previews: some View {
Group {
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
mood: PersistenceController.shared.randomEntries(count: 1)))
timeLineViews: FeelsWidget_Previews.data))
.previewContext(WidgetPreviewContext(family: .systemSmall))
.environment(\.sizeCategory, .small)
FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent(),
mood: PersistenceController.shared.randomEntries(count: 3)))
timeLineViews: FeelsWidget_Previews.data))
.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)
//
// FeelsWidgetEntryView(entry: SimpleEntry(date: Date(),
// configuration: ConfigurationIntent(),
// timeLineViews: FeelsWidget_Previews.data))
// .previewContext(WidgetPreviewContext(family: .systemLarge))
// .environment(\.sizeCategory, .large)
}
}
}