yattee/Model/OpenVideosModel.swift

150 lines
4.3 KiB
Swift
Raw Normal View History

2022-11-10 20:47:27 +00:00
#if canImport(AppKit)
import AppKit
#endif
2022-11-10 17:11:28 +00:00
import Foundation
import Logging
2022-11-10 20:47:27 +00:00
#if canImport(UIKit)
import UIKit
#endif
2022-11-10 17:11:28 +00:00
struct OpenVideosModel {
enum PlaybackMode: String, CaseIterable {
case playNow
case shuffleAll
case playNext
case playLast
var description: String {
switch self {
case .playNow:
return "Play Now".localized()
case .shuffleAll:
return "Shuffle All".localized()
case .playNext:
return "Play Next".localized()
case .playLast:
return "Play Last".localized()
}
}
var allowsRemovingQueueItems: Bool {
self == .playNow || self == .shuffleAll
}
var allowedWhenQueueIsEmpty: Bool {
self == .playNow || self == .shuffleAll
}
}
static let shared = OpenVideosModel()
var player: PlayerModel! = .shared
var logger = Logger(label: "stream.yattee.open-videos")
func open(_ url: URL) {
if url.startAccessingSecurityScopedResource() {
let video = Video.local(url)
player.play([video], shuffling: false)
}
}
2022-11-10 20:47:27 +00:00
var urlsFromClipboard: [URL] {
#if os(iOS)
if let pasteboard = UIPasteboard.general.string {
return urlsFrom(pasteboard)
}
#elseif os(macOS)
if let pasteboard = NSPasteboard.general.string(forType: .string) {
return urlsFrom(pasteboard)
}
#endif
return []
}
func openURLsFromClipboard(removeQueueItems: Bool = false, playbackMode: OpenVideosModel.PlaybackMode) {
openURLs(urlsFromClipboard, removeQueueItems: removeQueueItems, playbackMode: playbackMode)
}
2022-11-10 17:11:28 +00:00
func openURLs(_ urls: [URL], removeQueueItems: Bool, playbackMode: OpenVideosModel.PlaybackMode) {
2022-11-10 21:20:35 +00:00
guard !urls.isEmpty else {
return
}
2022-11-10 17:11:28 +00:00
logger.info("opening \(urls.count) urls")
urls.forEach { logger.info("\($0.absoluteString)") }
if removeQueueItems, playbackMode.allowsRemovingQueueItems {
player.removeQueueItems()
logger.info("removing queue items")
}
switch playbackMode {
case .playNow:
player.playbackMode = .queue
case .shuffleAll:
player.playbackMode = .shuffle
case .playNext:
player.playbackMode = .queue
case .playLast:
player.playbackMode = .queue
}
enqueue(
urls,
prepending: playbackMode == .playNow || playbackMode == .playNext
)
if playbackMode == .playNow || playbackMode == .shuffleAll {
player.show()
2022-11-11 11:34:55 +00:00
#if os(iOS)
if player.presentingPlayer {
player.advanceToNextItem()
} else {
player.onPresentPlayer.append { [weak player] in player?.advanceToNextItem() }
}
#else
player.advanceToNextItem()
#endif
2022-11-10 17:11:28 +00:00
}
}
func enqueue(_ urls: [URL], prepending: Bool = false) {
var videos = urls.compactMap { url in
var video: Video!
if canOpenVideosByID {
let parser = URLParser(url: url)
if parser.destination == .video, let id = parser.videoID {
video = Video(videoID: id)
logger.info("identified remote video: \(id)")
} else {
video = .local(url)
logger.info("identified local video: \(url.absoluteString)")
}
} else {
video = .local(url)
logger.info("identified local video: \(url.absoluteString)")
}
return video
}
if prepending {
videos.reverse()
}
videos.forEach { video in
player.enqueueVideo(video, play: false, prepending: prepending, loadDetails: false)
}
}
2022-11-10 20:47:27 +00:00
func urlsFrom(_ string: String) -> [URL] {
string.split(whereSeparator: \.isNewline).compactMap { URL(string: String($0)) }
}
2022-11-10 17:11:28 +00:00
var canOpenVideosByID: Bool {
guard let app = player.accounts.current?.app else { return false }
return !player.accounts.isEmpty && app.supportsOpeningVideosByID
}
}