tv-anarchy/Sources/TVAnarchyCore/PlayerStatusCache.swift
Natalie 92b38b1bae refactor(tv-anarchy): rename PlumTV→TVAnarchy and land session work
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>
2026-06-08 22:04:22 -07:00

38 lines
1.6 KiB
Swift

import Foundation
/// Persists the last-known playback status per host so the player shows cached
/// values immediately on a cold launch the first live poll can take several
/// seconds over a flapping link (the dead-LAN endpoint costs a ConnectTimeout),
/// and "Nothing playing" for that window is worse than a slightly-stale state.
public enum PlayerStatusCache {
public struct Entry: Codable, Sendable, Equatable {
public var status: PlaybackStatus
public var capturedAt: Date
public init(status: PlaybackStatus, capturedAt: Date) {
self.status = status; self.capturedAt = capturedAt
}
}
static func url() -> URL {
FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent(".local/state/tv-anarchy/player-status.json")
}
public static func load() -> [String: Entry] {
guard let data = try? Data(contentsOf: url()) else { return [:] }
let dec = JSONDecoder()
dec.dateDecodingStrategy = .iso8601
return (try? dec.decode([String: Entry].self, from: data)) ?? [:]
}
public static func save(_ map: [String: Entry]) {
let u = url()
try? FileManager.default.createDirectory(at: u.deletingLastPathComponent(),
withIntermediateDirectories: true)
let enc = JSONEncoder()
enc.dateEncodingStrategy = .iso8601
enc.outputFormatting = [.withoutEscapingSlashes]
guard let data = try? enc.encode(map) else { return }
try? data.write(to: u, options: .atomic)
}
}