Files
terebi/Checks/playback-progress.swift
T
hl-valdemar 0411064f0c feat: remember playback progress across player restarts
Persist authoritative per-video positions in UserDefaults. Save periodic checkpoints, pause, close, replacement, and quit; restore a validated position before autoplay. Canonical YouTube webpage URLs survive fresh stream extraction, and local symlinks share file progress.

Clear completed or out-of-duration bookmarks. Leave failed opens and live/non-seekable inputs out of persistence. Pending opens hide errors belonging to the previous source.

Verified separate-process restart, source replacement, failed-open recovery, completion, checkpoints, real YouTube short-link resume, live exclusion, and make all check.
2026-10-10 23:44:48 +02:00

50 lines
2.8 KiB
Swift

import Foundation
@main
struct PlaybackProgressChecks {
static func require(_ condition: @autoclosure () -> Bool, _ message: String) {
if !condition() { fatalError("FAIL: " + message) }
}
static func main() throws {
let suite = "terebi.progress-check.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suite)!
defer { defaults.removePersistentDomain(forName: suite) }
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(suite)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
defer { try? FileManager.default.removeItem(at: directory) }
let file = directory.appendingPathComponent("video.mp4")
let otherFile = directory.appendingPathComponent("other.mp4")
let alias = directory.appendingPathComponent("alias.mp4")
try Data().write(to: file)
try FileManager.default.createSymbolicLink(at: alias, withDestinationURL: file)
let youtube = URL(string: "https://www.youtube.com/watch?v=jNQXAC9IVRw")!
var progress = PlaybackProgress(defaults: defaults)
progress.save(123.25, for: file)
progress.save(18, for: otherFile)
progress.save(9.5, for: youtube)
let reopened = PlaybackProgress(defaults: UserDefaults(suiteName: suite)!)
require(reopened.position(for: file) == 123.25, "fractional local progress survives a fresh store")
require(reopened.position(for: alias) == 123.25, "symlink and original file share progress")
require(reopened.position(for: otherFile) == 18, "local files keep separate positions")
require(reopened.position(for: youtube) == 9.5, "canonical YouTube URL persists independently of local files")
progress.save(nil, for: alias)
let completed = PlaybackProgress(defaults: defaults)
require(completed.position(for: file) == nil, "completion clears progress through either file identity")
require(completed.position(for: otherFile) == 18 && completed.position(for: youtube) == 9.5,
"clearing one video preserves other videos")
for position in [Double.nan, Double.infinity, -Double.infinity, -1, 0] {
progress.save(position, for: file)
require(PlaybackProgress(defaults: defaults).position(for: file) == nil,
"invalid and zero positions never become resumable bookmarks")
}
let isolated = UserDefaults(suiteName: suite + ".isolated")!
defer { isolated.removePersistentDomain(forName: suite + ".isolated") }
require(PlaybackProgress(defaults: isolated).position(for: youtube) == nil,
"injected preference domains remain isolated")
print("Playback progress checks passed")
}
}