import Foundationenum LoadingPattern: String, CaseIterable, Identifiable { case knightRider case cylon case outsideIn case race case pulse case unbraid var id: String { self.rawValue } var displayName: String { switch self { case .knightRider: "Knight Rider" case .cylon: "Cylon" case .outsideIn: "Outside-In" case .race: "Race" case .pulse: "Pulse" case .unbraid: "Unbraid (logo → bars)" } } // Secondary offset so the lower bar moves differently. var secondaryOffset: Double { switch self { case .knightRider: .pi case .cylon: .pi / 2 case .outsideIn: .pi case .race: .pi / 3 case .pulse: .pi / 2 case .unbraid: .pi / 2 } } func value(phase: Double) -> Double { let v: Double switch self { case .knightRider: v = 0.5 + 0.5 * sin(phase) // ping-pong case .cylon: let t = phase.truncatingRemainder(dividingBy: .pi * 2) / (.pi * 2) v = t // sawtooth 0→1 case .outsideIn: v = abs(cos(phase)) // high at edges, dip center case .race: let t = (phase * 1.2).truncatingRemainder(dividingBy: .pi * 2) / (.pi * 2) v = t case .pulse: v = 0.4 + 0.6 * (0.5 + 0.5 * sin(phase)) // 40–100% case .unbraid: v = 0.5 + 0.5 * sin(phase) // smooth 0→1 for morph } return max(0, min(v * 100, 100)) }}extension Notification.Name { static let codexbarDebugReplayAllAnimations = Notification.Name("codexbarDebugReplayAllAnimations")}
import Foundation
enum LoadingPattern: String, CaseIterable, Identifiable {
case knightRider
case cylon
case outsideIn
case race
case pulse
case unbraid
var id: String { self.rawValue }
var displayName: String {
switch self {
case .knightRider: "Knight Rider"
case .cylon: "Cylon"
case .outsideIn: "Outside-In"
case .race: "Race"
case .pulse: "Pulse"
case .unbraid: "Unbraid (logo → bars)"
}
}
// Secondary offset so the lower bar moves differently.
var secondaryOffset: Double {
switch self {
case .knightRider: .pi
case .cylon: .pi / 2
case .outsideIn: .pi
case .race: .pi / 3
case .pulse: .pi / 2
case .unbraid: .pi / 2
}
}
func value(phase: Double) -> Double {
let v: Double
switch self {
case .knightRider:
v = 0.5 + 0.5 * sin(phase) // ping-pong
case .cylon:
let t = phase.truncatingRemainder(dividingBy: .pi * 2) / (.pi * 2)
v = t // sawtooth 0→1
case .outsideIn:
v = abs(cos(phase)) // high at edges, dip center
case .race:
let t = (phase * 1.2).truncatingRemainder(dividingBy: .pi * 2) / (.pi * 2)
v = t
case .pulse:
v = 0.4 + 0.6 * (0.5 + 0.5 * sin(phase)) // 40–100%
case .unbraid:
v = 0.5 + 0.5 * sin(phase) // smooth 0→1 for morph
}
return max(0, min(v * 100, 100))
}
}
extension Notification.Name {
static let codexbarDebugReplayAllAnimations = Notification.Name("codexbarDebugReplayAllAnimations")
}