mirror of
				https://github.com/yattee/yattee.git
				synced 2025-10-31 12:41:57 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
| #if canImport(AppKit)
 | |
|     import AppKit
 | |
| #endif
 | |
| import Foundation
 | |
| import Logging
 | |
| #if canImport(UIKit)
 | |
|     import UIKit
 | |
| #endif
 | |
| import SwiftUI
 | |
| 
 | |
| 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)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     var urlsFromClipboard: [URL] {
 | |
|         #if os(iOS)
 | |
|             if let pasteboard = UIPasteboard.general.urls {
 | |
|                 return 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 = .playNow) {
 | |
|         if urlsFromClipboard.isEmpty {
 | |
|             NavigationModel.shared.alert = Alert(title: Text("Could not find any links to open in your clipboard".localized()))
 | |
|             if NavigationModel.shared.presentingOpenVideos {
 | |
|                 NavigationModel.shared.presentingAlertInOpenVideos = true
 | |
|             } else {
 | |
|                 NavigationModel.shared.presentingAlert = true
 | |
|             }
 | |
|         } else {
 | |
|             openURLs(urlsFromClipboard, removeQueueItems: removeQueueItems, playbackMode: playbackMode)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func openURLs(_ urls: [URL], removeQueueItems: Bool = false, playbackMode: OpenVideosModel.PlaybackMode = .playNow) {
 | |
|         guard !urls.isEmpty else {
 | |
|             return
 | |
|         }
 | |
| 
 | |
|         NavigationModel.shared.presentingOpenVideos = false
 | |
| 
 | |
|         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
 | |
|         )
 | |
| 
 | |
|         WatchNextViewModel.shared.hide()
 | |
| 
 | |
|         if playbackMode == .playNow || playbackMode == .shuffleAll {
 | |
|             #if os(iOS)
 | |
|                 if player.presentingPlayer {
 | |
|                     player.advanceToNextItem()
 | |
|                 } else {
 | |
|                     player.onPresentPlayer.append { [weak player] in player?.advanceToNextItem() }
 | |
|                 }
 | |
|             #else
 | |
|                 player.advanceToNextItem()
 | |
|             #endif
 | |
|             player.show()
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     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(app: .local, 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)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func urlsFrom(_ string: String) -> [URL] {
 | |
|         string.split(whereSeparator: \.isNewline).compactMap { URL(string: String($0)) }
 | |
|     }
 | |
| 
 | |
|     var canOpenVideosByID: Bool {
 | |
|         guard let app = AccountsModel.shared.current?.app else { return false }
 | |
|         return !AccountsModel.shared.isEmpty && app.supportsOpeningVideosByID
 | |
|     }
 | |
| }
 | 
