mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +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 GroupActivities
|
||||
|
||||
class NormalPlayer: AVPlayerViewController {
|
||||
private var originalRate: Float = 1.0
|
||||
private var holdGesture: UILongPressGestureRecognizer?
|
||||
|
||||
var onSharePlayRequested: (() -> Void)?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupHoldGesture()
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -28,12 +28,9 @@ class VideoPlayerViewController: UIViewController {
|
|||
var episodeNumber: Int = 0
|
||||
var episodeImageUrl: 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 groupSessionObserver: AnyCancellable?
|
||||
|
||||
private var aniListUpdateSent = false
|
||||
private var aniListUpdatedSuccessfully = false
|
||||
|
|
@ -46,60 +43,12 @@ class VideoPlayerViewController: UIViewController {
|
|||
if UserDefaults.standard.object(forKey: "subtitlesEnabled") == nil {
|
||||
UserDefaults.standard.set(true, forKey: "subtitlesEnabled")
|
||||
}
|
||||
setupSharePlay()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
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() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
|
@ -133,13 +82,11 @@ class VideoPlayerViewController: UIViewController {
|
|||
view.addSubview(playerViewController.view)
|
||||
playerViewController.didMove(toParent: self)
|
||||
|
||||
if !subtitles.isEmpty && UserDefaults.standard.bool(forKey: "subtitlesEnabled") {
|
||||
setupSubtitles()
|
||||
playerViewController.onSharePlayRequested = { [weak self] in
|
||||
Task { @MainActor in
|
||||
await self?.startSharePlay()
|
||||
}
|
||||
}
|
||||
|
||||
// Configure SharePlay after player setup
|
||||
setupSharePlayButton(in: playerViewController)
|
||||
configureSharePlayForPlayer()
|
||||
}
|
||||
|
||||
addPeriodicTimeObserver(fullURL: fullUrl)
|
||||
|
|
@ -153,27 +100,86 @@ class VideoPlayerViewController: UIViewController {
|
|||
self.player?.play()
|
||||
}
|
||||
|
||||
observeGroupSession()
|
||||
configureGroupSession()
|
||||
}
|
||||
|
||||
private func observeGroupSession() {
|
||||
groupSessionObserver = nil
|
||||
Task { [weak self] in
|
||||
guard let self = self else { return }
|
||||
for await session in VideoWatchingActivity.sessions() {
|
||||
await self.handleIncomingGroupSession(session)
|
||||
private func configureGroupSession() {
|
||||
Task {
|
||||
for await groupSession in VideoWatchingActivity.sessions() {
|
||||
await configureGroupSession(groupSession)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func handleIncomingGroupSession(_ session: GroupSession<VideoWatchingActivity>) async {
|
||||
if sharePlayCoordinator == nil {
|
||||
sharePlayCoordinator = SharePlayCoordinator()
|
||||
private func configureGroupSession(_ groupSession: GroupSession<VideoWatchingActivity>) async {
|
||||
self.groupSession = groupSession
|
||||
|
||||
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 {
|
||||
sharePlayCoordinator?.coordinatePlayback(with: player)
|
||||
|
||||
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 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 {
|
||||
if UserDefaults.standard.bool(forKey: "alwaysLandscape") {
|
||||
return .landscape
|
||||
|
|
@ -403,13 +336,8 @@ class VideoPlayerViewController: UIViewController {
|
|||
if let timeObserverToken = timeObserverToken {
|
||||
player?.removeTimeObserver(timeObserverToken)
|
||||
}
|
||||
subtitleLabel?.removeFromSuperview()
|
||||
subtitleLabel = nil
|
||||
subtitlesLoader = nil
|
||||
|
||||
sharePlayCoordinator?.leaveGroupSession()
|
||||
sharePlayCoordinator = nil
|
||||
groupSession?.leave()
|
||||
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()
|
||||
metadata.title = mediaTitle
|
||||
metadata.subtitle = "Episode \(episodeNumber)"
|
||||
|
||||
if isMovie {
|
||||
metadata.subtitle = "Movie"
|
||||
} else {
|
||||
metadata.subtitle = "Episode \(episodeNumber)"
|
||||
}
|
||||
|
||||
if let imageData = episodeImageData,
|
||||
let uiImage = UIImage(data: imageData) {
|
||||
|
|
@ -37,32 +42,4 @@ struct VideoWatchingActivity: GroupActivity {
|
|||
let tmdbID: Int?
|
||||
let isMovie: Bool
|
||||
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 */; };
|
||||
13367ECE2DF70698009CB33F /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 13367ECD2DF70698009CB33F /* NukeUI */; };
|
||||
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 */; };
|
||||
133D7C702D2BE2500075467E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6F2D2BE2500075467E /* ContentView.swift */; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
|
|
@ -398,8 +394,6 @@
|
|||
133CF6A22DFEBE8100BD13F9 /* SharePlay */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
133CF6A42DFEBE8F00BD13F9 /* SharePlayManager.swift */,
|
||||
133CF6A52DFEBE9000BD13F9 /* SharePlayCoordinator.swift */,
|
||||
133CF6A32DFEBE8F00BD13F9 /* VideoWatchingActivity.swift */,
|
||||
);
|
||||
path = SharePlay;
|
||||
|
|
@ -899,7 +893,6 @@
|
|||
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
||||
0457C5A12DE78385000AFBD9 /* BookmarksDetailView.swift in Sources */,
|
||||
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
|
||||
133CF6A82DFEBE9000BD13F9 /* SharePlayCoordinator.swift in Sources */,
|
||||
13E62FC22DABC5830007E259 /* Trakt-Login.swift in Sources */,
|
||||
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */,
|
||||
13E62FC42DABC58C0007E259 /* Trakt-Token.swift in Sources */,
|
||||
|
|
@ -927,7 +920,6 @@
|
|||
13C0E5EA2D5F85EA00E7F619 /* ContinueWatchingManager.swift in Sources */,
|
||||
13637B8A2DE0EA1100BDA2FC /* UserDefaults.swift in Sources */,
|
||||
0457C59D2DE78267000AFBD9 /* BookmarkGridView.swift in Sources */,
|
||||
133CF6A72DFEBE9000BD13F9 /* SharePlayManager.swift in Sources */,
|
||||
0457C59E2DE78267000AFBD9 /* BookmarkLink.swift in Sources */,
|
||||
0457C59F2DE78267000AFBD9 /* BookmarkGridItemView.swift in Sources */,
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue