Skip to content

Commit 79bd443

Browse files
committed
dynamic list of goal names for countdown widget
todo: handle optional goalname
1 parent fbb929b commit 79bd443

File tree

5 files changed

+55
-30
lines changed

5 files changed

+55
-30
lines changed

BeeSwift/Gallery/GalleryViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,12 @@ class GalleryViewController: UIViewController, UICollectionViewDelegateFlowLayou
447447
@objc func openGoalFromNotification(_ notification: Notification) {
448448
var matchingGoal: Goal?
449449

450-
if let identifier = notif.userInfo?["identifier"] as? String {
450+
if let identifier = notification.userInfo?["identifier"] as? String {
451451
if let url = URL(string: identifier), let objectID = viewContext.persistentStoreCoordinator?.managedObjectID(forURIRepresentation: url) {
452452
matchingGoal = viewContext.object(with: objectID) as? Goal
453453
}
454454
}
455-
else if let slug = notif.userInfo?["slug"] as? String {
455+
else if let slug = notification.userInfo?["slug"] as? String {
456456
matchingGoal = self.filteredGoals.filter({ (goal) -> Bool in
457457
return goal.slug == slug
458458
}).last

BeeminderWidget/BeeminderGoalCountdownWidget.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,25 @@ import WidgetKit
1111

1212
struct BeeminderGoalCountdownWidgetProvider: AppIntentTimelineProvider {
1313
func placeholder(in _: Context) -> BeeminderGoalCountdownWidgetEntry {
14-
let goalDTO = usersGoals.randomElement()
15-
16-
return .init(date: Date(),
17-
configuration: GoalCountdownConfigurationAppIntent(),
18-
updatedAt: Date().addingTimeInterval(-60 * 1000).timeIntervalSince1970,
19-
username: username,
20-
goalDTO: goalDTO)
14+
.init(date: Date(),
15+
configuration: GoalCountdownConfigurationAppIntent(),
16+
updatedAt: Date().addingTimeInterval(-60 * 1000).timeIntervalSince1970,
17+
username: "username",
18+
goalDTO: BeeminderGoalCountdownGoalDTO(name: "goal1",
19+
limSum: "+3 in 3 days",
20+
countdownColor: Color.cyan,
21+
lastTouch: ""))
2122
}
2223

2324
func snapshot(for _: GoalCountdownConfigurationAppIntent, in context: Context) async -> BeeminderGoalCountdownWidgetEntry {
2425
placeholder(in: context)
2526
}
2627

2728
func timeline(for configuration: GoalCountdownConfigurationAppIntent, in _: Context) async -> Timeline<BeeminderGoalCountdownWidgetEntry> {
28-
let goal = usersGoals.first { $0.name.caseInsensitiveCompare(configuration.goalName) == .orderedSame }
29+
var goal: BeeminderGoalCountdownGoalDTO? {
30+
guard let goalName = configuration.goalName else { return nil }
31+
return usersGoals.first { $0.name.caseInsensitiveCompare(goalName) == .orderedSame }
32+
}
2933

3034
let updatedAt: TimeInterval? = {
3135
guard let lastTouch = goal?.lastTouch else { return nil }
@@ -38,7 +42,7 @@ struct BeeminderGoalCountdownWidgetProvider: AppIntentTimelineProvider {
3842
return date?.timeIntervalSince1970
3943
}()
4044

41-
let entries: [BeeminderGoalCountdownWidgetEntry] = [
45+
let entries: [BeeminderGoalCountdownWidgetEntry] = await [
4246
BeeminderGoalCountdownWidgetEntry(date: Date(),
4347
configuration: configuration,
4448
updatedAt: updatedAt,
@@ -52,10 +56,12 @@ struct BeeminderGoalCountdownWidgetProvider: AppIntentTimelineProvider {
5256

5357
private extension BeeminderGoalCountdownWidgetProvider {
5458
private var username: String? {
55-
ServiceLocator.currentUserManager.username
59+
get async {
60+
await ServiceLocator.currentUserManager.username
61+
}
5662
}
5763

58-
private var usersGoals: [BeeminderGoalCountdownGoalDTO] {
64+
var usersGoals: [BeeminderGoalCountdownGoalDTO] {
5965
ServiceLocator.goalManager
6066
.staleGoals(context: ServiceLocator.persistentContainer.viewContext)?
6167
.sorted(using: SortDescriptor(\.urgencyKey))
@@ -99,7 +105,7 @@ struct BeeminderGoalCountdownWidgetEntry: TimelineEntry {
99105
// let goal: Goal?
100106
let goalDTO: BeeminderGoalCountdownGoalDTO?
101107

102-
var userProvidedGoalName: String {
108+
var userProvidedGoalName: String? {
103109
configuration.goalName
104110
}
105111

@@ -148,7 +154,7 @@ struct BeeminderGoalCountdownWidgetEntryView: View {
148154
Spacer()
149155
Spacer()
150156

151-
Text(entry.userProvidedGoalName)
157+
Text(entry.userProvidedGoalName ?? "Edit Widget")
152158
.font(.title)
153159
.frame(width: .infinity)
154160
.minimumScaleFactor(0.2)
@@ -177,7 +183,7 @@ struct BeeminderGoalCountdownWidgetEntryView: View {
177183

178184
Spacer()
179185

180-
Text(entry.userProvidedGoalName)
186+
Text(entry.userProvidedGoalName ?? "Edit Widget")
181187
.font(.title)
182188
.frame(width: .infinity)
183189
.minimumScaleFactor(0.2)

BeeminderWidget/BeeminderGoalListWidget.swift

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct BeeminderGoalListProvider: TimelineProvider {
1919
: BeeminderGoalListEntryGoalDTO.goalDTOs.shuffled()
2020

2121
return .init(date: Date(),
22-
username: username ?? "Player1",
22+
username: "Player1",
2323
goals: goals.prefix(numGoals).map { $0 })
2424
}
2525

@@ -28,21 +28,26 @@ struct BeeminderGoalListProvider: TimelineProvider {
2828
}
2929

3030
func getTimeline(in _: Context, completion: @escaping @Sendable (Timeline<BeeminderGoalListEntry>) -> Void) {
31-
let entries: [BeeminderGoalListEntry] = [
32-
.init(date: Date(),
33-
username: username,
34-
goals: usersGoals),
35-
]
31+
Task {
32+
let entries: [BeeminderGoalListEntry] = await [
33+
.init(date: Date(),
34+
username: username,
35+
goals: usersGoals),
36+
]
3637

37-
let timeline = Timeline(entries: entries, policy: .atEnd)
38+
let timeline = Timeline(entries: entries, policy: .atEnd)
3839

39-
completion(timeline)
40+
completion(timeline)
41+
}
42+
4043
}
4144
}
4245

4346
private extension BeeminderGoalListProvider {
4447
private var username: String? {
45-
ServiceLocator.currentUserManager.username
48+
get async {
49+
await ServiceLocator.currentUserManager.username
50+
}
4651
}
4752

4853
private var usersGoals: [BeeminderGoalListEntryGoalDTO] {

BeeminderWidget/BeeminderPledgedTodayWidget.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ struct BeeminderPledgedTodayWidgetProvider: AppIntentTimelineProvider {
3838

3939
private extension BeeminderPledgedTodayWidgetProvider {
4040
private var username: String? {
41-
ServiceLocator.currentUserManager.username
41+
get async {
42+
await ServiceLocator.currentUserManager.username
43+
}
4244
}
4345

4446
private var usersGoals: [Goal] {

BeeminderWidget/BeeminderWidgetConfigurationIntents.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,27 @@ struct PledgedConfigurationAppIntent: WidgetConfigurationIntent {
3737
var denomination: BeeminderPledgeDenomination
3838
}
3939

40-
struct GoalCountdownConfigurationAppIntent: WidgetConfigurationIntent {
40+
struct GoalCountdownConfigurationAppIntent: AppIntent, WidgetConfigurationIntent {
4141
static let title: LocalizedStringResource = "Colored Goal"
4242
static let description = IntentDescription("Shows a goal in its countdown color!")
4343

4444
@Parameter(title: "Goal Name (aka slug)",
45-
default: "dial",
46-
inputOptions: String.IntentInputOptions(keyboardType: .default, capitalizationType: .none, autocorrect: false))
47-
var goalName: String
45+
optionsProvider: BeeminderGoalCountdownWidgetProvider.GoalNameProvider())
46+
var goalName: String?
4847

4948
@Parameter(title: "Show Summary of what you need to do to eke by, e.g., \"+2 within 1 day\".", default: true)
5049
var showLimSum: Bool
5150
}
51+
52+
// namespace?
53+
extension BeeminderGoalCountdownWidgetProvider {
54+
struct GoalNameProvider: DynamicOptionsProvider {
55+
func results() async throws -> [String] {
56+
ServiceLocator.goalManager
57+
.staleGoals(context: ServiceLocator.persistentContainer.viewContext)?
58+
.sorted(using: SortDescriptor(\.slug))
59+
.map { $0.slug }
60+
?? []
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)