Renames Sources/PlumTV→TVAnarchy and PlumTVCore→TVAnarchyCore (the rename the auto-commit service couldn't stage — it git-add'd the old, now-gone paths and aborted every cycle), and commits the accumulated work: - Library: black-built index fast path (LibraryIndex + scanFromIndex) with NFS-walk fallback; incremental --add on download-complete; mtime staleness gate; loose-file series-collapse fix; determinate scan/index progress. - Cover art: keyless TVmaze cartoon-vs-live-action disambiguation (type/year). - Player: sleep timer (timed + end-of-episode); visibility-gated polling. - Home: Continue Watching cover art + live refresh; Recently Added; adult gate. - Logs: multi-line selection + copy; truncated giant tx-list errors. - Hover previews (opt-in) via black ffmpeg + scp. Also gitignores foreign project trees (governor/mcp/fleet/recommender) that sit in this directory but belong to their own repos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.6 KiB
Swift
34 lines
1.6 KiB
Swift
import Foundation
|
|
|
|
/// Reads the build identity stamped onto the app bundle's Info.plist at build
|
|
/// time (see the "Stamp version" phase in project.yml). `Bundle.main` is the
|
|
/// running .app even though this lives in the framework, so the values reflect
|
|
/// the app you actually launched — which is exactly how you tell a fresh build
|
|
/// from a stale one you forgot to relaunch.
|
|
public enum AppVersion {
|
|
/// Human version, e.g. "1.1.0" — from MARKETING_VERSION, baked into the
|
|
/// Info.plist by XcodeGen (reliable; unlike the dynamic stamp it never moves
|
|
/// between builds of the same release).
|
|
public static var marketing: String { info("CFBundleShortVersionString") ?? "?" }
|
|
/// Monotonic build number = git commit count, e.g. "212".
|
|
public static var build: String { String(BuildStamp.commitCount) }
|
|
/// Short git SHA, with a "-dirty" suffix when built from an uncommitted tree.
|
|
public static var sha: String { BuildStamp.sha }
|
|
/// Build timestamp, "yyyy-MM-dd HH:mm:ss".
|
|
public static var buildTime: String { BuildStamp.buildTime }
|
|
|
|
/// Glanceable one-liner for chrome (sidebar / title): "v1.1.0 · a1b2c3d · 14:32".
|
|
public static var short: String {
|
|
let clock = buildTime.split(separator: " ").last.map(String.init) ?? buildTime
|
|
return "v\(marketing) · \(sha) · \(clock)"
|
|
}
|
|
|
|
/// Full identity for an about/settings line.
|
|
public static var full: String {
|
|
"TVAnarchy v\(marketing) (build \(build)) · \(sha) · built \(buildTime)"
|
|
}
|
|
|
|
private static func info(_ key: String) -> String? {
|
|
Bundle.main.infoDictionary?[key] as? String
|
|
}
|
|
}
|