mirror of
https://github.com/aculix/knotchy.git
synced 2026-10-27 07:15:53 +00:00
40 lines
1.4 KiB
Swift
40 lines
1.4 KiB
Swift
/// Decides when Starting ends. Frames and progress before NAVIGATED come from the agent's
|
|
/// about:blank bootstrap and never count; `afterHello` is a backstop if NAVIGATED never arrives.
|
|
public struct ContentReadiness: Sendable {
|
|
public static let afterNavigated: Duration = .seconds(15)
|
|
public static let afterHello: Duration = .seconds(25)
|
|
|
|
public private(set) var isReady = false
|
|
private var helloAt: ContinuousClock.Instant?
|
|
private var navigatedAt: ContinuousClock.Instant?
|
|
|
|
public init() {}
|
|
|
|
public mutating func hello(at now: ContinuousClock.Instant) {
|
|
if helloAt == nil { helloAt = now }
|
|
}
|
|
|
|
public mutating func navigated(at now: ContinuousClock.Instant) {
|
|
if navigatedAt == nil { navigatedAt = now }
|
|
}
|
|
|
|
public mutating func frame(isUniform: Bool) {
|
|
if navigatedAt != nil, !isUniform { isReady = true }
|
|
}
|
|
|
|
public mutating func progress(_ percent: Int) {
|
|
if navigatedAt != nil, percent >= 100 { isReady = true }
|
|
}
|
|
|
|
public mutating func tick(now: ContinuousClock.Instant) {
|
|
if let deadline = nextDeadline, now >= deadline { isReady = true }
|
|
}
|
|
|
|
public var nextDeadline: ContinuousClock.Instant? {
|
|
guard !isReady else { return nil }
|
|
return [navigatedAt.map { $0 + Self.afterNavigated }, helloAt.map { $0 + Self.afterHello }]
|
|
.compactMap { $0 }
|
|
.min()
|
|
}
|
|
}
|