feat: add independent CLI launches and preserve shared video bookmarks

This commit is contained in:
2026-10-11 12:47:08 +02:00
parent 537e8e2624
commit 0dce073287
10 changed files with 254 additions and 40 deletions
+14 -8
View File
@@ -2,28 +2,34 @@ import Foundation
struct PlaybackProgress {
private let defaults: UserDefaults
private var positions: [String: Double]
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
positions = defaults.dictionary(forKey: "playbackPositions") as? [String: Double] ?? [:]
// Migrate the old shared dictionary once; separate keys prevent cross-player lost updates.
if let positions = defaults.dictionary(forKey: "playbackPositions") as? [String: Double] {
for (identity, position) in positions where position.isFinite && position > 0 {
let key = "playbackPosition:" + identity
if defaults.object(forKey: key) == nil { defaults.set(position, forKey: key) }
}
defaults.removeObject(forKey: "playbackPositions")
}
}
func position(for url: URL) -> Double? {
guard let position = positions[key(for: url)], position.isFinite, position > 0 else { return nil }
guard let position = defaults.object(forKey: key(for: url)) as? Double,
position.isFinite, position > 0 else { return nil }
return position
}
mutating func save(_ position: Double?, for url: URL) {
func save(_ position: Double?, for url: URL) {
let key = key(for: url)
let position = position.flatMap { $0.isFinite && $0 > 0 ? $0 : nil }
guard positions[key] != position else { return }
positions[key] = position
defaults.set(positions, forKey: "playbackPositions")
guard (defaults.object(forKey: key) as? Double) != position else { return }
defaults.set(position, forKey: key)
}
private func key(for url: URL) -> String {
// YouTube callers supply the canonical webpage URL, never an expiring media URL.
return url.isFileURL ? url.standardizedFileURL.resolvingSymlinksInPath().absoluteString : url.absoluteString
return "playbackPosition:" + (url.isFileURL ? url.standardizedFileURL.resolvingSymlinksInPath().absoluteString : url.absoluteString)
}
}
+5 -1
View File
@@ -55,7 +55,7 @@ final class PlayerModel: ObservableObject {
private let qualityClock: () -> Double
private var automaticQuality = AutomaticQuality()
private var qualityNow: Double { qualityClock() }
private var playbackProgress: PlaybackProgress
private let playbackProgress: PlaybackProgress
private var progressURL: URL?
private var resumePosition: Double?
private var resumePlaying = true
@@ -1369,6 +1369,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
NSApp.activate(ignoringOtherApps: true)
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(openDocuments(_:withReplyEvent:)),
forEventClass: AEEventClass(kCoreEventClass), andEventID: AEEventID(kAEOpenDocuments))
let arguments = Array(CommandLine.arguments.dropFirst())
if arguments.count == 2, arguments[0] == "--open-media", let url = URL(string: arguments[1]) {
PlayerModel.shared.open(url)
}
}
// Let SwiftUI create the initial window for a Finder/document launch.