Skip to content

Commit

Permalink
A working version
Browse files Browse the repository at this point in the history
  • Loading branch information
Supereg committed Sep 4, 2024
1 parent 102dd7d commit 7848353
Show file tree
Hide file tree
Showing 12 changed files with 665 additions and 190 deletions.
51 changes: 37 additions & 14 deletions Sources/SpeziScheduler/InfinityLoop/EventQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,75 @@ import SwiftUI
@propertyWrapper
@MainActor
public struct EventQuery {
private let range: Range<Date>
public struct Configuration {
fileprivate let range: Range<Date>
fileprivate let taskPredicate: Predicate<ILTask>

public fileprivate(set) var fetchError: (any Error)?

init(range: Range<Date>, taskPredicate: Predicate<ILTask>) {
self.range = range
self.taskPredicate = taskPredicate
}
}


@Environment(ILScheduler.self)
private var scheduler

@State private var viewUpdate: UInt64 = 0
@State private var cancelable: AnyCancellable?

public private(set) var wrappedValue: [ILEvent]
@State private var configuration: Configuration
@State private var fetchedEvents: [ILEvent] = []

public var wrappedValue: [ILEvent] {
fetchedEvents
}

// TODO: projected value?
public var projectedValue: Configuration {
configuration
}

public init(in range: Range<Date>) {
// TODO: more flexibility in the query Predicate (e.g., query additional properties)?
self.range = range
self.wrappedValue = []
public init(
in range: Range<Date>, // TODO: eventually support closed date range?
predicate: Predicate<ILTask> = #Predicate { _ in true }
) {
self.configuration = Configuration(range: range, taskPredicate: predicate)
}
}


extension EventQuery: DynamicProperty {
public mutating nonisolated func update() {
MainActor.assumeIsolated { // TODO: this is not great, update is public!
MainActor.assumeIsolated { // TODO: this is not great, `update()` is public!
doUpdate()
}
}

private mutating func doUpdate() {
guard let context = try? scheduler.context else {
return // TODO: what do do?
guard let context = try? scheduler.context else { // TODO: just embed this into the Scheduler?
configuration.fetchError = ILScheduler.DataError.invalidContainer
return
}

if cancelable != nil {
let viewUpdate = $viewUpdate
cancelable = NotificationCenter.default.publisher(for: ModelContext.didSave, object: context)
.sink { _ in
viewUpdate.wrappedValue &+= 1 // increment that automatically wraps around
// TODO: on which thread are we running, MainActor?
// we are using the Main Context, that always runs on the Main Actor
// TODO: this is implementation details (make sure it doesnt change)
MainActor.assumeIsolated {
viewUpdate.wrappedValue &+= 1 // increment that automatically wraps around
}
}
}

do {
// TODO: should this run on the main thread?
wrappedValue = try scheduler.queryEvents(for: range)
fetchedEvents = try scheduler.queryEvents(for: configuration.range, predicate: configuration.taskPredicate)
} catch {
// TODO: log error!
configuration.fetchError = error
}
}
}
Loading

0 comments on commit 7848353

Please sign in to comment.