mirror of
https://github.com/cranci1/Sora.git
synced 2026-03-11 17:45:37 +00:00
not 100% sure byt maybe it works now
This commit is contained in:
parent
718f5b4a75
commit
04fc467cb4
6 changed files with 106 additions and 342 deletions
|
|
@ -6,15 +6,37 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import AVKit
|
import AVKit
|
||||||
|
import GroupActivities
|
||||||
|
|
||||||
class NormalPlayer: AVPlayerViewController {
|
class NormalPlayer: AVPlayerViewController {
|
||||||
private var originalRate: Float = 1.0
|
private var originalRate: Float = 1.0
|
||||||
private var holdGesture: UILongPressGestureRecognizer?
|
private var holdGesture: UILongPressGestureRecognizer?
|
||||||
|
|
||||||
|
var onSharePlayRequested: (() -> Void)?
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setupHoldGesture()
|
setupHoldGesture()
|
||||||
setupAudioSession()
|
setupAudioSession()
|
||||||
|
setupSharePlayButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupSharePlayButton() {
|
||||||
|
let sharePlayItem = UIBarButtonItem(
|
||||||
|
image: UIImage(systemName: "shareplay"),
|
||||||
|
style: .plain,
|
||||||
|
target: self,
|
||||||
|
action: #selector(sharePlayButtonTapped)
|
||||||
|
)
|
||||||
|
sharePlayItem.tintColor = .white
|
||||||
|
|
||||||
|
if responds(to: Selector(("setCustomControlItems:"))) {
|
||||||
|
setValue([sharePlayItem], forKey: "customControlItems")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func sharePlayButtonTapped() {
|
||||||
|
onSharePlayRequested?()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupHoldGesture() {
|
private func setupHoldGesture() {
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,9 @@ class VideoPlayerViewController: UIViewController {
|
||||||
var episodeNumber: Int = 0
|
var episodeNumber: Int = 0
|
||||||
var episodeImageUrl: String = ""
|
var episodeImageUrl: String = ""
|
||||||
var mediaTitle: String = ""
|
var mediaTitle: String = ""
|
||||||
var subtitlesLoader: VTTSubtitlesLoader?
|
|
||||||
var subtitleLabel: UILabel?
|
|
||||||
|
|
||||||
private var sharePlayCoordinator: SharePlayCoordinator?
|
private var groupSession: GroupSession<VideoWatchingActivity>?
|
||||||
private var subscriptions = Set<AnyCancellable>()
|
private var subscriptions = Set<AnyCancellable>()
|
||||||
private var groupSessionObserver: AnyCancellable?
|
|
||||||
|
|
||||||
private var aniListUpdateSent = false
|
private var aniListUpdateSent = false
|
||||||
private var aniListUpdatedSuccessfully = false
|
private var aniListUpdatedSuccessfully = false
|
||||||
|
|
@ -46,60 +43,12 @@ class VideoPlayerViewController: UIViewController {
|
||||||
if UserDefaults.standard.object(forKey: "subtitlesEnabled") == nil {
|
if UserDefaults.standard.object(forKey: "subtitlesEnabled") == nil {
|
||||||
UserDefaults.standard.set(true, forKey: "subtitlesEnabled")
|
UserDefaults.standard.set(true, forKey: "subtitlesEnabled")
|
||||||
}
|
}
|
||||||
setupSharePlay()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupSubtitles() {
|
|
||||||
guard !subtitles.isEmpty, UserDefaults.standard.bool(forKey: "subtitlesEnabled"), let _ = URL(string: subtitles) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
subtitlesLoader = VTTSubtitlesLoader()
|
|
||||||
setupSubtitleLabel()
|
|
||||||
|
|
||||||
subtitlesLoader?.load(from: subtitles)
|
|
||||||
|
|
||||||
let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
|
|
||||||
player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
|
|
||||||
self?.updateSubtitles(at: time.seconds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func setupSubtitleLabel() {
|
|
||||||
let label = UILabel()
|
|
||||||
label.numberOfLines = 0
|
|
||||||
label.textAlignment = .center
|
|
||||||
label.textColor = .white
|
|
||||||
label.font = .systemFont(ofSize: 16, weight: .medium)
|
|
||||||
label.layer.shadowColor = UIColor.black.cgColor
|
|
||||||
label.layer.shadowOffset = CGSize(width: 1, height: 1)
|
|
||||||
label.layer.shadowOpacity = 0.8
|
|
||||||
label.layer.shadowRadius = 2
|
|
||||||
|
|
||||||
guard let playerView = playerViewController?.view else { return }
|
|
||||||
playerView.addSubview(label)
|
|
||||||
label.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
label.leadingAnchor.constraint(equalTo: playerView.leadingAnchor, constant: 16),
|
|
||||||
label.trailingAnchor.constraint(equalTo: playerView.trailingAnchor, constant: -16),
|
|
||||||
label.bottomAnchor.constraint(equalTo: playerView.bottomAnchor, constant: -32)
|
|
||||||
])
|
|
||||||
|
|
||||||
self.subtitleLabel = label
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateSubtitles(at time: Double) {
|
|
||||||
let currentSubtitle = subtitlesLoader?.cues.first { cue in
|
|
||||||
time >= cue.startTime && time <= cue.endTime
|
|
||||||
}
|
|
||||||
subtitleLabel?.text = currentSubtitle?.text ?? ""
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
|
@ -133,13 +82,11 @@ class VideoPlayerViewController: UIViewController {
|
||||||
view.addSubview(playerViewController.view)
|
view.addSubview(playerViewController.view)
|
||||||
playerViewController.didMove(toParent: self)
|
playerViewController.didMove(toParent: self)
|
||||||
|
|
||||||
if !subtitles.isEmpty && UserDefaults.standard.bool(forKey: "subtitlesEnabled") {
|
playerViewController.onSharePlayRequested = { [weak self] in
|
||||||
setupSubtitles()
|
Task { @MainActor in
|
||||||
|
await self?.startSharePlay()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure SharePlay after player setup
|
|
||||||
setupSharePlayButton(in: playerViewController)
|
|
||||||
configureSharePlayForPlayer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addPeriodicTimeObserver(fullURL: fullUrl)
|
addPeriodicTimeObserver(fullURL: fullUrl)
|
||||||
|
|
@ -153,27 +100,86 @@ class VideoPlayerViewController: UIViewController {
|
||||||
self.player?.play()
|
self.player?.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
observeGroupSession()
|
configureGroupSession()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func observeGroupSession() {
|
private func configureGroupSession() {
|
||||||
groupSessionObserver = nil
|
Task {
|
||||||
Task { [weak self] in
|
for await groupSession in VideoWatchingActivity.sessions() {
|
||||||
guard let self = self else { return }
|
await configureGroupSession(groupSession)
|
||||||
for await session in VideoWatchingActivity.sessions() {
|
|
||||||
await self.handleIncomingGroupSession(session)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
private func handleIncomingGroupSession(_ session: GroupSession<VideoWatchingActivity>) async {
|
private func configureGroupSession(_ groupSession: GroupSession<VideoWatchingActivity>) async {
|
||||||
if sharePlayCoordinator == nil {
|
self.groupSession = groupSession
|
||||||
sharePlayCoordinator = SharePlayCoordinator()
|
|
||||||
|
groupSession.$state
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] state in
|
||||||
|
switch state {
|
||||||
|
case .joined:
|
||||||
|
self?.coordinatePlayback()
|
||||||
|
case .invalidated:
|
||||||
|
self?.groupSession = nil
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &subscriptions)
|
||||||
|
|
||||||
|
groupSession.join()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func coordinatePlayback() {
|
||||||
|
guard let player = player, let groupSession = groupSession else { return }
|
||||||
|
|
||||||
|
player.playbackCoordinator.coordinateWithSession(groupSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func startSharePlay() async {
|
||||||
|
guard let streamUrl = streamUrl else { return }
|
||||||
|
|
||||||
|
var episodeImageData: Data?
|
||||||
|
if !episodeImageUrl.isEmpty, let imageUrl = URL(string: episodeImageUrl) {
|
||||||
|
do {
|
||||||
|
episodeImageData = try await URLSession.shared.data(from: imageUrl).0
|
||||||
|
} catch {
|
||||||
|
Logger.shared.log("Failed to load episode image: \(error)", type: "Error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sharePlayCoordinator?.configureGroupSession()
|
|
||||||
if let player = self.player {
|
let activity = VideoWatchingActivity(
|
||||||
sharePlayCoordinator?.coordinatePlayback(with: player)
|
mediaTitle: mediaTitle,
|
||||||
|
episodeNumber: episodeNumber,
|
||||||
|
streamUrl: streamUrl,
|
||||||
|
subtitles: subtitles,
|
||||||
|
aniListID: aniListID,
|
||||||
|
fullUrl: fullUrl,
|
||||||
|
headers: headers,
|
||||||
|
episodeImageUrl: episodeImageUrl,
|
||||||
|
episodeImageData: episodeImageData,
|
||||||
|
totalEpisodes: totalEpisodes,
|
||||||
|
tmdbID: tmdbID,
|
||||||
|
isMovie: isMovie,
|
||||||
|
seasonNumber: seasonNumber
|
||||||
|
)
|
||||||
|
|
||||||
|
do {
|
||||||
|
_ = try await activity.activate()
|
||||||
|
Logger.shared.log("SharePlay session started successfully", type: "SharePlay")
|
||||||
|
} catch {
|
||||||
|
Logger.shared.log("Failed to start SharePlay: \(error)", type: "Error")
|
||||||
|
|
||||||
|
let alert = UIAlertController(
|
||||||
|
title: "SharePlay Unavailable",
|
||||||
|
message: "SharePlay is not available right now. Make sure you're connected to FaceTime or have SharePlay enabled in Control Center.",
|
||||||
|
preferredStyle: .alert
|
||||||
|
)
|
||||||
|
alert.addAction(UIAlertAction(title: "OK", style: .default))
|
||||||
|
present(alert, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,79 +315,6 @@ class VideoPlayerViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func setupSharePlay() {
|
|
||||||
sharePlayCoordinator = SharePlayCoordinator()
|
|
||||||
sharePlayCoordinator?.configureGroupSession()
|
|
||||||
|
|
||||||
if let playerViewController = playerViewController {
|
|
||||||
setupSharePlayButton(in: playerViewController)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func setupSharePlayButton(in playerViewController: NormalPlayer) {
|
|
||||||
// WIP
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
private func startSharePlay() {
|
|
||||||
guard let streamUrl = streamUrl else { return }
|
|
||||||
|
|
||||||
Task {
|
|
||||||
var episodeImageData: Data?
|
|
||||||
if !episodeImageUrl.isEmpty, let imageUrl = URL(string: episodeImageUrl) {
|
|
||||||
episodeImageData = try? await URLSession.shared.data(from: imageUrl).0
|
|
||||||
}
|
|
||||||
|
|
||||||
let activity = VideoWatchingActivity(
|
|
||||||
mediaTitle: mediaTitle,
|
|
||||||
episodeNumber: episodeNumber,
|
|
||||||
streamUrl: streamUrl,
|
|
||||||
subtitles: subtitles,
|
|
||||||
aniListID: aniListID,
|
|
||||||
fullUrl: fullUrl,
|
|
||||||
headers: headers,
|
|
||||||
episodeImageUrl: episodeImageUrl,
|
|
||||||
episodeImageData: episodeImageData,
|
|
||||||
totalEpisodes: totalEpisodes,
|
|
||||||
tmdbID: tmdbID,
|
|
||||||
isMovie: isMovie,
|
|
||||||
seasonNumber: seasonNumber
|
|
||||||
)
|
|
||||||
|
|
||||||
await sharePlayCoordinator?.startSharePlay(with: activity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func configureSharePlayForPlayer() {
|
|
||||||
guard let player = player else { return }
|
|
||||||
sharePlayCoordinator?.coordinatePlayback(with: player)
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func presentSharePlayInvitation() {
|
|
||||||
guard let streamUrl = streamUrl else {
|
|
||||||
Logger.shared.log("Cannot start SharePlay: Stream URL is nil", type: "Error")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
SharePlayManager.shared.presentSharePlayInvitation(
|
|
||||||
from: self,
|
|
||||||
mediaTitle: mediaTitle,
|
|
||||||
episodeNumber: episodeNumber,
|
|
||||||
streamUrl: streamUrl,
|
|
||||||
subtitles: subtitles,
|
|
||||||
aniListID: aniListID,
|
|
||||||
fullUrl: fullUrl,
|
|
||||||
headers: headers,
|
|
||||||
episodeImageUrl: episodeImageUrl,
|
|
||||||
totalEpisodes: totalEpisodes,
|
|
||||||
tmdbID: tmdbID,
|
|
||||||
isMovie: isMovie,
|
|
||||||
seasonNumber: seasonNumber
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||||
if UserDefaults.standard.bool(forKey: "alwaysLandscape") {
|
if UserDefaults.standard.bool(forKey: "alwaysLandscape") {
|
||||||
return .landscape
|
return .landscape
|
||||||
|
|
@ -403,13 +336,8 @@ class VideoPlayerViewController: UIViewController {
|
||||||
if let timeObserverToken = timeObserverToken {
|
if let timeObserverToken = timeObserverToken {
|
||||||
player?.removeTimeObserver(timeObserverToken)
|
player?.removeTimeObserver(timeObserverToken)
|
||||||
}
|
}
|
||||||
subtitleLabel?.removeFromSuperview()
|
|
||||||
subtitleLabel = nil
|
|
||||||
subtitlesLoader = nil
|
|
||||||
|
|
||||||
sharePlayCoordinator?.leaveGroupSession()
|
groupSession?.leave()
|
||||||
sharePlayCoordinator = nil
|
|
||||||
subscriptions.removeAll()
|
subscriptions.removeAll()
|
||||||
groupSessionObserver = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
//
|
|
||||||
// SharePlayCoordinator.swift
|
|
||||||
// Sora
|
|
||||||
//
|
|
||||||
// Created by Francesco on 15/06/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Combine
|
|
||||||
import Foundation
|
|
||||||
import AVFoundation
|
|
||||||
import GroupActivities
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
class SharePlayCoordinator: ObservableObject {
|
|
||||||
private var subscriptions = Set<AnyCancellable>()
|
|
||||||
private var groupSession: GroupSession<VideoWatchingActivity>?
|
|
||||||
|
|
||||||
@Published var isEligibleForGroupSession = false
|
|
||||||
@Published var groupSessionState: GroupSession<VideoWatchingActivity>.State = .waiting
|
|
||||||
|
|
||||||
private var playbackCoordinator: AVPlayerPlaybackCoordinator?
|
|
||||||
|
|
||||||
func configureGroupSession() {
|
|
||||||
Task {
|
|
||||||
for await session in VideoWatchingActivity.sessions() {
|
|
||||||
await configureGroupSession(session)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func configureGroupSession(_ groupSession: GroupSession<VideoWatchingActivity>) async {
|
|
||||||
self.groupSession = groupSession
|
|
||||||
|
|
||||||
groupSession.$state
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.assign(to: &$groupSessionState)
|
|
||||||
|
|
||||||
groupSession.$activeParticipants
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { participants in
|
|
||||||
Logger.shared.log("Active participants: \(participants.count)", type: "SharePlay")
|
|
||||||
}
|
|
||||||
.store(in: &subscriptions)
|
|
||||||
|
|
||||||
groupSession.join()
|
|
||||||
}
|
|
||||||
|
|
||||||
func startSharePlay(with activity: VideoWatchingActivity) async {
|
|
||||||
do {
|
|
||||||
_ = try await activity.activate()
|
|
||||||
Logger.shared.log("SharePlay activity activated successfully", type: "SharePlay")
|
|
||||||
} catch {
|
|
||||||
Logger.shared.log("Failed to activate SharePlay: \(error.localizedDescription)", type: "Error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func coordinatePlayback(with player: AVPlayer) {
|
|
||||||
guard let groupSession = groupSession else { return }
|
|
||||||
|
|
||||||
playbackCoordinator = player.playbackCoordinator
|
|
||||||
playbackCoordinator?.coordinateWithSession(groupSession)
|
|
||||||
|
|
||||||
Logger.shared.log("Playback coordination established", type: "SharePlay")
|
|
||||||
}
|
|
||||||
|
|
||||||
nonisolated func leaveGroupSession() {
|
|
||||||
Task { @MainActor in
|
|
||||||
self.groupSession?.leave()
|
|
||||||
self.playbackCoordinator = nil
|
|
||||||
Logger.shared.log("Left SharePlay session", type: "SharePlay")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
subscriptions.removeAll()
|
|
||||||
playbackCoordinator = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
//
|
|
||||||
// SharePlayManager.swift
|
|
||||||
// Sora
|
|
||||||
//
|
|
||||||
// Created by Francesco on 15/06/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import Foundation
|
|
||||||
import GroupActivities
|
|
||||||
|
|
||||||
class SharePlayManager {
|
|
||||||
static let shared = SharePlayManager()
|
|
||||||
|
|
||||||
private init() {}
|
|
||||||
|
|
||||||
func isSharePlayAvailable() -> Bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func presentSharePlayInvitation(from viewController: UIViewController,
|
|
||||||
mediaTitle: String,
|
|
||||||
episodeNumber: Int,
|
|
||||||
streamUrl: String,
|
|
||||||
subtitles: String = "",
|
|
||||||
aniListID: Int = 0,
|
|
||||||
fullUrl: String,
|
|
||||||
headers: [String: String]? = nil,
|
|
||||||
episodeImageUrl: String = "",
|
|
||||||
totalEpisodes: Int = 0,
|
|
||||||
tmdbID: Int? = nil,
|
|
||||||
isMovie: Bool = false,
|
|
||||||
seasonNumber: Int = 1) {
|
|
||||||
|
|
||||||
Task { @MainActor in
|
|
||||||
var episodeImageData: Data?
|
|
||||||
if !episodeImageUrl.isEmpty, let imageUrl = URL(string: episodeImageUrl) {
|
|
||||||
do {
|
|
||||||
episodeImageData = try await URLSession.shared.data(from: imageUrl).0
|
|
||||||
} catch {
|
|
||||||
Logger.shared.log("Failed to load episode image for SharePlay: \(error.localizedDescription)", type: "Error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let activity = VideoWatchingActivity(
|
|
||||||
mediaTitle: mediaTitle,
|
|
||||||
episodeNumber: episodeNumber,
|
|
||||||
streamUrl: streamUrl,
|
|
||||||
subtitles: subtitles,
|
|
||||||
aniListID: aniListID,
|
|
||||||
fullUrl: fullUrl,
|
|
||||||
headers: headers,
|
|
||||||
episodeImageUrl: episodeImageUrl,
|
|
||||||
episodeImageData: episodeImageData,
|
|
||||||
totalEpisodes: totalEpisodes,
|
|
||||||
tmdbID: tmdbID,
|
|
||||||
isMovie: isMovie,
|
|
||||||
seasonNumber: seasonNumber
|
|
||||||
)
|
|
||||||
|
|
||||||
do {
|
|
||||||
_ = try await activity.activate()
|
|
||||||
Logger.shared.log("SharePlay invitation sent successfully", type: "SharePlay")
|
|
||||||
} catch {
|
|
||||||
Logger.shared.log("Failed to send SharePlay invitation: \(error.localizedDescription)", type: "Error")
|
|
||||||
|
|
||||||
let alert = UIAlertController(
|
|
||||||
title: "SharePlay Unavailable",
|
|
||||||
message: "SharePlay is not available right now. Make sure you're connected to FaceTime or have SharePlay enabled in Control Center.",
|
|
||||||
preferredStyle: .alert
|
|
||||||
)
|
|
||||||
alert.addAction(UIAlertAction(title: "OK", style: .default))
|
|
||||||
viewController.present(alert, animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -13,7 +13,12 @@ struct VideoWatchingActivity: GroupActivity {
|
||||||
var metadata: GroupActivityMetadata {
|
var metadata: GroupActivityMetadata {
|
||||||
var metadata = GroupActivityMetadata()
|
var metadata = GroupActivityMetadata()
|
||||||
metadata.title = mediaTitle
|
metadata.title = mediaTitle
|
||||||
metadata.subtitle = "Episode \(episodeNumber)"
|
|
||||||
|
if isMovie {
|
||||||
|
metadata.subtitle = "Movie"
|
||||||
|
} else {
|
||||||
|
metadata.subtitle = "Episode \(episodeNumber)"
|
||||||
|
}
|
||||||
|
|
||||||
if let imageData = episodeImageData,
|
if let imageData = episodeImageData,
|
||||||
let uiImage = UIImage(data: imageData) {
|
let uiImage = UIImage(data: imageData) {
|
||||||
|
|
@ -37,32 +42,4 @@ struct VideoWatchingActivity: GroupActivity {
|
||||||
let tmdbID: Int?
|
let tmdbID: Int?
|
||||||
let isMovie: Bool
|
let isMovie: Bool
|
||||||
let seasonNumber: Int
|
let seasonNumber: Int
|
||||||
|
|
||||||
init(mediaTitle: String,
|
|
||||||
episodeNumber: Int,
|
|
||||||
streamUrl: String,
|
|
||||||
subtitles: String = "",
|
|
||||||
aniListID: Int = 0,
|
|
||||||
fullUrl: String,
|
|
||||||
headers: [String: String]? = nil,
|
|
||||||
episodeImageUrl: String = "",
|
|
||||||
episodeImageData: Data? = nil,
|
|
||||||
totalEpisodes: Int = 0,
|
|
||||||
tmdbID: Int? = nil,
|
|
||||||
isMovie: Bool = false,
|
|
||||||
seasonNumber: Int = 1) {
|
|
||||||
self.mediaTitle = mediaTitle
|
|
||||||
self.episodeNumber = episodeNumber
|
|
||||||
self.streamUrl = streamUrl
|
|
||||||
self.subtitles = subtitles
|
|
||||||
self.aniListID = aniListID
|
|
||||||
self.fullUrl = fullUrl
|
|
||||||
self.headers = headers
|
|
||||||
self.episodeImageUrl = episodeImageUrl
|
|
||||||
self.episodeImageData = episodeImageData
|
|
||||||
self.totalEpisodes = totalEpisodes
|
|
||||||
self.tmdbID = tmdbID
|
|
||||||
self.isMovie = isMovie
|
|
||||||
self.seasonNumber = seasonNumber
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,6 @@
|
||||||
13367ECC2DF70698009CB33F /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = 13367ECB2DF70698009CB33F /* Nuke */; };
|
13367ECC2DF70698009CB33F /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = 13367ECB2DF70698009CB33F /* Nuke */; };
|
||||||
13367ECE2DF70698009CB33F /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 13367ECD2DF70698009CB33F /* NukeUI */; };
|
13367ECE2DF70698009CB33F /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 13367ECD2DF70698009CB33F /* NukeUI */; };
|
||||||
133CF6A62DFEBE9000BD13F9 /* VideoWatchingActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */; };
|
133CF6A62DFEBE9000BD13F9 /* VideoWatchingActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */; };
|
||||||
133CF6A72DFEBE9000BD13F9 /* SharePlayManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133CF6A42DFEBE8F00BD13F9 /* SharePlayManager.swift */; };
|
|
||||||
133CF6A82DFEBE9000BD13F9 /* SharePlayCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133CF6A52DFEBE9000BD13F9 /* SharePlayCoordinator.swift */; };
|
|
||||||
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6D2D2BE2500075467E /* SoraApp.swift */; };
|
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6D2D2BE2500075467E /* SoraApp.swift */; };
|
||||||
133D7C702D2BE2500075467E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6F2D2BE2500075467E /* ContentView.swift */; };
|
133D7C702D2BE2500075467E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6F2D2BE2500075467E /* ContentView.swift */; };
|
||||||
133D7C722D2BE2520075467E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 133D7C712D2BE2520075467E /* Assets.xcassets */; };
|
133D7C722D2BE2520075467E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 133D7C712D2BE2520075467E /* Assets.xcassets */; };
|
||||||
|
|
@ -149,8 +147,6 @@
|
||||||
132AF1222D9995C300A0140B /* JSController-Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Details.swift"; sourceTree = "<group>"; };
|
132AF1222D9995C300A0140B /* JSController-Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Details.swift"; sourceTree = "<group>"; };
|
||||||
132AF1242D9995F900A0140B /* JSController-Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Search.swift"; sourceTree = "<group>"; };
|
132AF1242D9995F900A0140B /* JSController-Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Search.swift"; sourceTree = "<group>"; };
|
||||||
133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoWatchingActivity.swift; sourceTree = "<group>"; };
|
133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoWatchingActivity.swift; sourceTree = "<group>"; };
|
||||||
133CF6A42DFEBE8F00BD13F9 /* SharePlayManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharePlayManager.swift; sourceTree = "<group>"; };
|
|
||||||
133CF6A52DFEBE9000BD13F9 /* SharePlayCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SharePlayCoordinator.swift; sourceTree = "<group>"; };
|
|
||||||
133D7C6A2D2BE2500075467E /* Sulfur.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sulfur.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
133D7C6A2D2BE2500075467E /* Sulfur.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sulfur.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
133D7C6D2D2BE2500075467E /* SoraApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraApp.swift; sourceTree = "<group>"; };
|
133D7C6D2D2BE2500075467E /* SoraApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraApp.swift; sourceTree = "<group>"; };
|
||||||
133D7C6F2D2BE2500075467E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
133D7C6F2D2BE2500075467E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -398,8 +394,6 @@
|
||||||
133CF6A22DFEBE8100BD13F9 /* SharePlay */ = {
|
133CF6A22DFEBE8100BD13F9 /* SharePlay */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
133CF6A42DFEBE8F00BD13F9 /* SharePlayManager.swift */,
|
|
||||||
133CF6A52DFEBE9000BD13F9 /* SharePlayCoordinator.swift */,
|
|
||||||
133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */,
|
133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */,
|
||||||
);
|
);
|
||||||
path = SharePlay;
|
path = SharePlay;
|
||||||
|
|
@ -899,7 +893,6 @@
|
||||||
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
||||||
0457C5A12DE78385000AFBD9 /* BookmarksDetailView.swift in Sources */,
|
0457C5A12DE78385000AFBD9 /* BookmarksDetailView.swift in Sources */,
|
||||||
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
|
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
|
||||||
133CF6A82DFEBE9000BD13F9 /* SharePlayCoordinator.swift in Sources */,
|
|
||||||
13E62FC22DABC5830007E259 /* Trakt-Login.swift in Sources */,
|
13E62FC22DABC5830007E259 /* Trakt-Login.swift in Sources */,
|
||||||
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */,
|
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */,
|
||||||
13E62FC42DABC58C0007E259 /* Trakt-Token.swift in Sources */,
|
13E62FC42DABC58C0007E259 /* Trakt-Token.swift in Sources */,
|
||||||
|
|
@ -927,7 +920,6 @@
|
||||||
13C0E5EA2D5F85EA00E7F619 /* ContinueWatchingManager.swift in Sources */,
|
13C0E5EA2D5F85EA00E7F619 /* ContinueWatchingManager.swift in Sources */,
|
||||||
13637B8A2DE0EA1100BDA2FC /* UserDefaults.swift in Sources */,
|
13637B8A2DE0EA1100BDA2FC /* UserDefaults.swift in Sources */,
|
||||||
0457C59D2DE78267000AFBD9 /* BookmarkGridView.swift in Sources */,
|
0457C59D2DE78267000AFBD9 /* BookmarkGridView.swift in Sources */,
|
||||||
133CF6A72DFEBE9000BD13F9 /* SharePlayManager.swift in Sources */,
|
|
||||||
0457C59E2DE78267000AFBD9 /* BookmarkLink.swift in Sources */,
|
0457C59E2DE78267000AFBD9 /* BookmarkLink.swift in Sources */,
|
||||||
0457C59F2DE78267000AFBD9 /* BookmarkGridItemView.swift in Sources */,
|
0457C59F2DE78267000AFBD9 /* BookmarkGridItemView.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue