Skip to content

Commit

Permalink
dynamic list of goal names for countdown widget
Browse files Browse the repository at this point in the history
todo: handle optional goalname
  • Loading branch information
krugerk committed Nov 26, 2024
1 parent 1229f68 commit 94262a3
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 30 deletions.
6 changes: 4 additions & 2 deletions BeeKit/Managers/CurrentUserManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@ public actor CurrentUserManager {
return keychain.get(CurrentUserManager.accessTokenKey)
}

public var username :String? {
return user(context: modelContext)?.username
public var username: String? {
get async {
user(context: modelContext)?.username
}
}

public nonisolated func signedIn(context: NSManagedObjectContext) -> Bool {
Expand Down
34 changes: 20 additions & 14 deletions BeeminderWidget/BeeminderGoalCountdownWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,25 @@ import WidgetKit

struct BeeminderGoalCountdownWidgetProvider: AppIntentTimelineProvider {
func placeholder(in _: Context) -> BeeminderGoalCountdownWidgetEntry {
let goalDTO = usersGoals.randomElement()

return .init(date: Date(),
configuration: GoalCountdownConfigurationAppIntent(),
updatedAt: Date().addingTimeInterval(-60 * 1000).timeIntervalSince1970,
username: username,
goalDTO: goalDTO)
.init(date: Date(),
configuration: GoalCountdownConfigurationAppIntent(),
updatedAt: Date().addingTimeInterval(-60 * 1000).timeIntervalSince1970,
username: "username",
goalDTO: BeeminderGoalCountdownGoalDTO(name: "goal1",
limSum: "+3 in 3 days",
countdownColor: Color.cyan,
lastTouch: ""))
}

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

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

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

let entries: [BeeminderGoalCountdownWidgetEntry] = [
let entries: [BeeminderGoalCountdownWidgetEntry] = await [
BeeminderGoalCountdownWidgetEntry(date: Date(),
configuration: configuration,
updatedAt: updatedAt,
Expand All @@ -52,10 +56,12 @@ struct BeeminderGoalCountdownWidgetProvider: AppIntentTimelineProvider {

private extension BeeminderGoalCountdownWidgetProvider {
private var username: String? {
ServiceLocator.currentUserManager.username
get async {
await ServiceLocator.currentUserManager.username
}
}

private var usersGoals: [BeeminderGoalCountdownGoalDTO] {
var usersGoals: [BeeminderGoalCountdownGoalDTO] {
ServiceLocator.goalManager
.staleGoals(context: ServiceLocator.persistentContainer.viewContext)?
.sorted(using: SortDescriptor(\.urgencyKey))
Expand Down Expand Up @@ -99,7 +105,7 @@ struct BeeminderGoalCountdownWidgetEntry: TimelineEntry {
// let goal: Goal?
let goalDTO: BeeminderGoalCountdownGoalDTO?

var userProvidedGoalName: String {
var userProvidedGoalName: String? {
configuration.goalName
}

Expand Down Expand Up @@ -148,7 +154,7 @@ struct BeeminderGoalCountdownWidgetEntryView: View {
Spacer()
Spacer()

Text(entry.userProvidedGoalName)
Text(entry.userProvidedGoalName ?? "Edit Widget")
.font(.title)
.frame(width: .infinity)
.minimumScaleFactor(0.2)
Expand Down Expand Up @@ -177,7 +183,7 @@ struct BeeminderGoalCountdownWidgetEntryView: View {

Spacer()

Text(entry.userProvidedGoalName)
Text(entry.userProvidedGoalName ?? "Edit Widget")
.font(.title)
.frame(width: .infinity)
.minimumScaleFactor(0.2)
Expand Down
23 changes: 14 additions & 9 deletions BeeminderWidget/BeeminderGoalListWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct BeeminderGoalListProvider: TimelineProvider {
: BeeminderGoalListEntryGoalDTO.goalDTOs.shuffled()

return .init(date: Date(),
username: username ?? "Player1",
username: "Player1",
goals: goals.prefix(numGoals).map { $0 })
}

Expand All @@ -28,21 +28,26 @@ struct BeeminderGoalListProvider: TimelineProvider {
}

func getTimeline(in _: Context, completion: @escaping @Sendable (Timeline<BeeminderGoalListEntry>) -> Void) {
let entries: [BeeminderGoalListEntry] = [
.init(date: Date(),
username: username,
goals: usersGoals),
]
Task {
let entries: [BeeminderGoalListEntry] = await [
.init(date: Date(),
username: username,
goals: usersGoals),
]

let timeline = Timeline(entries: entries, policy: .atEnd)
let timeline = Timeline(entries: entries, policy: .atEnd)

completion(timeline)
completion(timeline)
}

}
}

private extension BeeminderGoalListProvider {
private var username: String? {
ServiceLocator.currentUserManager.username
get async {
await ServiceLocator.currentUserManager.username
}
}

private var usersGoals: [BeeminderGoalListEntryGoalDTO] {
Expand Down
4 changes: 3 additions & 1 deletion BeeminderWidget/BeeminderPledgedTodayWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ struct BeeminderPledgedTodayWidgetProvider: AppIntentTimelineProvider {

private extension BeeminderPledgedTodayWidgetProvider {
private var username: String? {
ServiceLocator.currentUserManager.username
get async {
await ServiceLocator.currentUserManager.username
}
}

private var usersGoals: [Goal] {
Expand Down
20 changes: 16 additions & 4 deletions BeeminderWidget/BeeminderWidgetConfigurationIntents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,27 @@ struct PledgedConfigurationAppIntent: WidgetConfigurationIntent {
var denomination: BeeminderPledgeDenomination
}

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

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

@Parameter(title: "Show Summary of what you need to do to eke by, e.g., \"+2 within 1 day\".", default: true)
var showLimSum: Bool
}

// namespace?
extension BeeminderGoalCountdownWidgetProvider {
struct GoalNameProvider: DynamicOptionsProvider {
func results() async throws -> [String] {
ServiceLocator.goalManager
.staleGoals(context: ServiceLocator.persistentContainer.viewContext)?
.sorted(using: SortDescriptor(\.slug))
.map { $0.slug }
?? []
}
}
}

0 comments on commit 94262a3

Please sign in to comment.