mirror of
https://github.com/cranci1/Sora.git
synced 2026-05-16 06:42:15 +00:00
macos support
This commit is contained in:
parent
f030f65ce0
commit
794c4993d4
4 changed files with 0 additions and 349 deletions
|
|
@ -1,215 +0,0 @@
|
||||||
//
|
|
||||||
// DownloadManager.swift
|
|
||||||
// Sulfur
|
|
||||||
//
|
|
||||||
// Created by Francesco on 09/03/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import FFmpegSupport
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension Notification.Name {
|
|
||||||
static let DownloadManagerStatusUpdate = Notification.Name("DownloadManagerStatusUpdate")
|
|
||||||
}
|
|
||||||
|
|
||||||
class DownloadManager {
|
|
||||||
static let shared = DownloadManager()
|
|
||||||
|
|
||||||
private var backgroundTaskIdentifier: UIBackgroundTaskIdentifier = .invalid
|
|
||||||
private var activeConversions = [String: Bool]()
|
|
||||||
|
|
||||||
private init() {
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc private func applicationWillResignActive() {
|
|
||||||
if !activeConversions.isEmpty {
|
|
||||||
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask { [weak self] in
|
|
||||||
self?.endBackgroundTask()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func endBackgroundTask() {
|
|
||||||
if backgroundTaskIdentifier != .invalid {
|
|
||||||
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
|
|
||||||
backgroundTaskIdentifier = .invalid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadAndConvertHLS(from url: URL, title: String, episode: Int, subtitleURL: URL? = nil, module: ScrapingModule, completion: @escaping (Bool, URL?) -> Void) {
|
|
||||||
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
|
||||||
completion(false, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let folderURL = documentsDirectory.appendingPathComponent(title + "-" + module.metadata.sourceName)
|
|
||||||
if (!FileManager.default.fileExists(atPath: folderURL.path)) {
|
|
||||||
do {
|
|
||||||
try FileManager.default.createDirectory(at: folderURL, withIntermediateDirectories: true, attributes: nil)
|
|
||||||
} catch {
|
|
||||||
Logger.shared.log("Error creating folder: \(error)")
|
|
||||||
completion(false, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let outputFileName = "\(title)_Episode\(episode)_\(module.metadata.sourceName).mp4"
|
|
||||||
let outputFileURL = folderURL.appendingPathComponent(outputFileName)
|
|
||||||
|
|
||||||
let fileExtension = url.pathExtension.lowercased()
|
|
||||||
|
|
||||||
if fileExtension == "mp4" {
|
|
||||||
NotificationCenter.default.post(name: .DownloadManagerStatusUpdate, object: nil, userInfo: [
|
|
||||||
"title": title,
|
|
||||||
"episode": episode,
|
|
||||||
"type": "mp4",
|
|
||||||
"status": "Downloading",
|
|
||||||
"progress": 0.0
|
|
||||||
])
|
|
||||||
|
|
||||||
let task = URLSession.custom.downloadTask(with: url) { tempLocalURL, response, error in
|
|
||||||
if let tempLocalURL = tempLocalURL {
|
|
||||||
do {
|
|
||||||
try FileManager.default.moveItem(at: tempLocalURL, to: outputFileURL)
|
|
||||||
NotificationCenter.default.post(name: .DownloadManagerStatusUpdate, object: nil, userInfo: [
|
|
||||||
"title": title,
|
|
||||||
"episode": episode,
|
|
||||||
"type": "mp4",
|
|
||||||
"status": "Completed",
|
|
||||||
"progress": 1.0
|
|
||||||
])
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
Logger.shared.log("Download successful: \(outputFileURL)")
|
|
||||||
completion(true, outputFileURL)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
Logger.shared.log("Download failed: \(error)")
|
|
||||||
completion(false, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
Logger.shared.log("Download failed: \(error?.localizedDescription ?? "Unknown error")")
|
|
||||||
completion(false, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
task.resume()
|
|
||||||
} else if fileExtension == "m3u8" {
|
|
||||||
let conversionKey = "\(title)_\(episode)_\(module.metadata.sourceName)"
|
|
||||||
activeConversions[conversionKey] = true
|
|
||||||
|
|
||||||
if UIApplication.shared.applicationState != .active && backgroundTaskIdentifier == .invalid {
|
|
||||||
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask { [weak self] in
|
|
||||||
self?.endBackgroundTask()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchQueue.global(qos: .background).async {
|
|
||||||
NotificationCenter.default.post(name: .DownloadManagerStatusUpdate, object: nil, userInfo: [
|
|
||||||
"title": title,
|
|
||||||
"episode": episode,
|
|
||||||
"type": "hls",
|
|
||||||
"status": "Converting",
|
|
||||||
"progress": 0.0
|
|
||||||
])
|
|
||||||
|
|
||||||
let processorCount = ProcessInfo.processInfo.processorCount
|
|
||||||
let physicalMemory = ProcessInfo.processInfo.physicalMemory / (1024 * 1024)
|
|
||||||
|
|
||||||
var ffmpegCommand = ["ffmpeg", "-y"]
|
|
||||||
|
|
||||||
ffmpegCommand.append(contentsOf: ["-protocol_whitelist", "file,http,https,tcp,tls"])
|
|
||||||
|
|
||||||
ffmpegCommand.append(contentsOf: ["-fflags", "+genpts"])
|
|
||||||
ffmpegCommand.append(contentsOf: ["-reconnect", "1", "-reconnect_streamed", "1", "-reconnect_delay_max", "5"])
|
|
||||||
ffmpegCommand.append(contentsOf: ["-headers", "Referer: \(module.metadata.baseUrl)"])
|
|
||||||
|
|
||||||
let multiThreads = UserDefaults.standard.bool(forKey: "multiThreads")
|
|
||||||
if multiThreads {
|
|
||||||
let threadCount = max(2, processorCount - 1)
|
|
||||||
ffmpegCommand.append(contentsOf: ["-threads", "\(threadCount)"])
|
|
||||||
} else {
|
|
||||||
ffmpegCommand.append(contentsOf: ["-threads", "2"])
|
|
||||||
}
|
|
||||||
|
|
||||||
let bufferSize = min(32, max(8, Int(physicalMemory) / 256))
|
|
||||||
ffmpegCommand.append(contentsOf: ["-bufsize", "\(bufferSize)M"])
|
|
||||||
ffmpegCommand.append(contentsOf: ["-i", url.absoluteString])
|
|
||||||
|
|
||||||
if let subtitleURL = subtitleURL {
|
|
||||||
do {
|
|
||||||
let subtitleData = try Data(contentsOf: subtitleURL)
|
|
||||||
let subtitleFileExtension = subtitleURL.pathExtension.lowercased()
|
|
||||||
if subtitleFileExtension != "srt" && subtitleFileExtension != "vtt" {
|
|
||||||
Logger.shared.log("Unsupported subtitle format: \(subtitleFileExtension)")
|
|
||||||
}
|
|
||||||
let subtitleFileName = "\(title)_Episode\(episode).\(subtitleFileExtension)"
|
|
||||||
let subtitleLocalURL = folderURL.appendingPathComponent(subtitleFileName)
|
|
||||||
try subtitleData.write(to: subtitleLocalURL)
|
|
||||||
ffmpegCommand.append(contentsOf: ["-i", subtitleLocalURL.path])
|
|
||||||
|
|
||||||
ffmpegCommand.append(contentsOf: [
|
|
||||||
"-c:v", "copy",
|
|
||||||
"-c:a", "copy",
|
|
||||||
"-c:s", "mov_text",
|
|
||||||
"-disposition:s:0", "default+forced",
|
|
||||||
"-metadata:s:s:0", "handler_name=English",
|
|
||||||
"-metadata:s:s:0", "language=eng"
|
|
||||||
])
|
|
||||||
|
|
||||||
ffmpegCommand.append(outputFileURL.path)
|
|
||||||
} catch {
|
|
||||||
Logger.shared.log("Subtitle download failed: \(error)")
|
|
||||||
ffmpegCommand.append(contentsOf: ["-c:v", "copy", "-c:a", "copy"])
|
|
||||||
ffmpegCommand.append(contentsOf: ["-movflags", "+faststart"])
|
|
||||||
ffmpegCommand.append(outputFileURL.path)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ffmpegCommand.append(contentsOf: ["-c:v", "copy", "-c:a", "copy"])
|
|
||||||
ffmpegCommand.append(contentsOf: ["-movflags", "+faststart"])
|
|
||||||
ffmpegCommand.append(outputFileURL.path)
|
|
||||||
}
|
|
||||||
Logger.shared.log("FFmpeg command: \(ffmpegCommand.joined(separator: " "))", type: "Debug")
|
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .DownloadManagerStatusUpdate, object: nil, userInfo: [
|
|
||||||
"title": title,
|
|
||||||
"episode": episode,
|
|
||||||
"type": "hls",
|
|
||||||
"status": "Converting",
|
|
||||||
"progress": 0.5
|
|
||||||
])
|
|
||||||
|
|
||||||
let success = ffmpeg(ffmpegCommand)
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
|
||||||
if success == 0 {
|
|
||||||
NotificationCenter.default.post(name: .DownloadManagerStatusUpdate, object: nil, userInfo: [
|
|
||||||
"title": title,
|
|
||||||
"episode": episode,
|
|
||||||
"type": "hls",
|
|
||||||
"status": "Completed",
|
|
||||||
"progress": 1.0
|
|
||||||
])
|
|
||||||
Logger.shared.log("Conversion successful: \(outputFileURL)")
|
|
||||||
completion(true, outputFileURL)
|
|
||||||
} else {
|
|
||||||
Logger.shared.log("Conversion failed")
|
|
||||||
completion(false, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
self?.activeConversions[conversionKey] = nil
|
|
||||||
|
|
||||||
if self?.activeConversions.isEmpty ?? true {
|
|
||||||
self?.endBackgroundTask()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Logger.shared.log("Unsupported file type: \(fileExtension)")
|
|
||||||
completion(false, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
//
|
|
||||||
// DownloadView.swift
|
|
||||||
// Sulfur
|
|
||||||
//
|
|
||||||
// Created by Francesco on 12/03/25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct DownloadItem: Identifiable {
|
|
||||||
let id = UUID()
|
|
||||||
let title: String
|
|
||||||
let episode: Int
|
|
||||||
let type: String
|
|
||||||
var progress: Double
|
|
||||||
var status: String
|
|
||||||
}
|
|
||||||
|
|
||||||
class DownloadViewModel: ObservableObject {
|
|
||||||
@Published var downloads: [DownloadItem] = []
|
|
||||||
|
|
||||||
init() {
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(updateStatus(_:)), name: .DownloadManagerStatusUpdate, object: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func updateStatus(_ notification: Notification) {
|
|
||||||
guard let info = notification.userInfo,
|
|
||||||
let title = info["title"] as? String,
|
|
||||||
let episode = info["episode"] as? Int,
|
|
||||||
let type = info["type"] as? String,
|
|
||||||
let status = info["status"] as? String,
|
|
||||||
let progress = info["progress"] as? Double else { return }
|
|
||||||
|
|
||||||
if let index = downloads.firstIndex(where: { $0.title == title && $0.episode == episode }) {
|
|
||||||
downloads[index] = DownloadItem(title: title, episode: episode, type: type, progress: progress, status: status)
|
|
||||||
} else {
|
|
||||||
let newDownload = DownloadItem(title: title, episode: episode, type: type, progress: progress, status: status)
|
|
||||||
downloads.append(newDownload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DownloadView: View {
|
|
||||||
@StateObject var viewModel = DownloadViewModel()
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
NavigationView {
|
|
||||||
List(viewModel.downloads) { download in
|
|
||||||
HStack(spacing: 16) {
|
|
||||||
Image(systemName: iconName(for: download))
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 30, height: 30)
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
|
||||||
Text("\(download.title) - Episode \(download.episode)")
|
|
||||||
.font(.headline)
|
|
||||||
|
|
||||||
ProgressView(value: download.progress)
|
|
||||||
.progressViewStyle(LinearProgressViewStyle(tint: .accentColor))
|
|
||||||
.frame(height: 8)
|
|
||||||
|
|
||||||
Text(download.status)
|
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(.vertical, 8)
|
|
||||||
}
|
|
||||||
.navigationTitle("Downloads")
|
|
||||||
}
|
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
|
||||||
}
|
|
||||||
|
|
||||||
func iconName(for download: DownloadItem) -> String {
|
|
||||||
if download.type == "hls" {
|
|
||||||
return download.status.lowercased().contains("converting") ? "arrow.triangle.2.circlepath.circle.fill" : "checkmark.circle.fill"
|
|
||||||
} else {
|
|
||||||
return download.progress >= 1.0 ? "checkmark.circle.fill" : "arrow.down.circle.fill"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
130217CC2D81C55E0011EFF5 /* DownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130217CB2D81C55E0011EFF5 /* DownloadView.swift */; };
|
|
||||||
130C6BFA2D53AB1F00DC1432 /* SettingsViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130C6BF92D53AB1F00DC1432 /* SettingsViewData.swift */; };
|
130C6BFA2D53AB1F00DC1432 /* SettingsViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130C6BF92D53AB1F00DC1432 /* SettingsViewData.swift */; };
|
||||||
13103E892D58A39A000F0673 /* AniListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E882D58A39A000F0673 /* AniListItem.swift */; };
|
13103E892D58A39A000F0673 /* AniListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E882D58A39A000F0673 /* AniListItem.swift */; };
|
||||||
13103E8B2D58E028000F0673 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E8A2D58E028000F0673 /* View.swift */; };
|
13103E8B2D58E028000F0673 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E8A2D58E028000F0673 /* View.swift */; };
|
||||||
|
|
@ -53,8 +52,6 @@
|
||||||
13DB46902D900A38008CBC03 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB468F2D900A38008CBC03 /* URL.swift */; };
|
13DB46902D900A38008CBC03 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB468F2D900A38008CBC03 /* URL.swift */; };
|
||||||
13DB46922D900BCE008CBC03 /* SettingsViewTrackers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB46912D900BCE008CBC03 /* SettingsViewTrackers.swift */; };
|
13DB46922D900BCE008CBC03 /* SettingsViewTrackers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB46912D900BCE008CBC03 /* SettingsViewTrackers.swift */; };
|
||||||
13DB7CC32D7D99C0004371D3 /* SubtitleSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB7CC22D7D99C0004371D3 /* SubtitleSettingsManager.swift */; };
|
13DB7CC32D7D99C0004371D3 /* SubtitleSettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB7CC22D7D99C0004371D3 /* SubtitleSettingsManager.swift */; };
|
||||||
13DB7CC62D7DC7D2004371D3 /* FFmpeg-iOS-Lame in Frameworks */ = {isa = PBXBuildFile; productRef = 13DB7CC52D7DC7D2004371D3 /* FFmpeg-iOS-Lame */; };
|
|
||||||
13DB7CEC2D7DED5D004371D3 /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DB7CEB2D7DED5D004371D3 /* DownloadManager.swift */; };
|
|
||||||
13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DC0C452D302C7500D0F966 /* VideoPlayer.swift */; };
|
13DC0C462D302C7500D0F966 /* VideoPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13DC0C452D302C7500D0F966 /* VideoPlayer.swift */; };
|
||||||
13EA2BD52D32D97400C1EBD7 /* CustomPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD12D32D97400C1EBD7 /* CustomPlayer.swift */; };
|
13EA2BD52D32D97400C1EBD7 /* CustomPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD12D32D97400C1EBD7 /* CustomPlayer.swift */; };
|
||||||
13EA2BD62D32D97400C1EBD7 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD32D32D97400C1EBD7 /* Double+Extension.swift */; };
|
13EA2BD62D32D97400C1EBD7 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EA2BD32D32D97400C1EBD7 /* Double+Extension.swift */; };
|
||||||
|
|
@ -65,7 +62,6 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
130217CB2D81C55E0011EFF5 /* DownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadView.swift; sourceTree = "<group>"; };
|
|
||||||
130C6BF82D53A4C200DC1432 /* Sora.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sora.entitlements; sourceTree = "<group>"; };
|
130C6BF82D53A4C200DC1432 /* Sora.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sora.entitlements; sourceTree = "<group>"; };
|
||||||
130C6BF92D53AB1F00DC1432 /* SettingsViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewData.swift; sourceTree = "<group>"; };
|
130C6BF92D53AB1F00DC1432 /* SettingsViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewData.swift; sourceTree = "<group>"; };
|
||||||
13103E882D58A39A000F0673 /* AniListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AniListItem.swift; sourceTree = "<group>"; };
|
13103E882D58A39A000F0673 /* AniListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AniListItem.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -111,7 +107,6 @@
|
||||||
13DB468F2D900A38008CBC03 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
13DB468F2D900A38008CBC03 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||||
13DB46912D900BCE008CBC03 /* SettingsViewTrackers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewTrackers.swift; sourceTree = "<group>"; };
|
13DB46912D900BCE008CBC03 /* SettingsViewTrackers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewTrackers.swift; sourceTree = "<group>"; };
|
||||||
13DB7CC22D7D99C0004371D3 /* SubtitleSettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleSettingsManager.swift; sourceTree = "<group>"; };
|
13DB7CC22D7D99C0004371D3 /* SubtitleSettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleSettingsManager.swift; sourceTree = "<group>"; };
|
||||||
13DB7CEB2D7DED5D004371D3 /* DownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManager.swift; sourceTree = "<group>"; };
|
|
||||||
13DC0C412D2EC9BA00D0F966 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
13DC0C412D2EC9BA00D0F966 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||||
13DC0C452D302C7500D0F966 /* VideoPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayer.swift; sourceTree = "<group>"; };
|
13DC0C452D302C7500D0F966 /* VideoPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayer.swift; sourceTree = "<group>"; };
|
||||||
13EA2BD12D32D97400C1EBD7 /* CustomPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPlayer.swift; sourceTree = "<group>"; };
|
13EA2BD12D32D97400C1EBD7 /* CustomPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPlayer.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -127,7 +122,6 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
13DB7CC62D7DC7D2004371D3 /* FFmpeg-iOS-Lame in Frameworks */,
|
|
||||||
1359ED1A2D76FA7D00C13034 /* Drops in Frameworks */,
|
1359ED1A2D76FA7D00C13034 /* Drops in Frameworks */,
|
||||||
133D7C972D2BE2AF0075467E /* Kingfisher in Frameworks */,
|
133D7C972D2BE2AF0075467E /* Kingfisher in Frameworks */,
|
||||||
);
|
);
|
||||||
|
|
@ -253,7 +247,6 @@
|
||||||
1399FAD22D3AB34F00E97C31 /* SettingsView */,
|
1399FAD22D3AB34F00E97C31 /* SettingsView */,
|
||||||
133F55B92D33B53E00E08EEA /* LibraryView */,
|
133F55B92D33B53E00E08EEA /* LibraryView */,
|
||||||
133D7C7C2D2BE2630075467E /* SearchView.swift */,
|
133D7C7C2D2BE2630075467E /* SearchView.swift */,
|
||||||
130217CB2D81C55E0011EFF5 /* DownloadView.swift */,
|
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -284,7 +277,6 @@
|
||||||
133D7C852D2BE2640075467E /* Utils */ = {
|
133D7C852D2BE2640075467E /* Utils */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
13DB7CEA2D7DED50004371D3 /* DownloadManager */,
|
|
||||||
13C0E5E82D5F85DD00E7F619 /* ContinueWatching */,
|
13C0E5E82D5F85DD00E7F619 /* ContinueWatching */,
|
||||||
13103E8C2D58E037000F0673 /* SkeletonCells */,
|
13103E8C2D58E037000F0673 /* SkeletonCells */,
|
||||||
13DC0C442D302C6A00D0F966 /* MediaPlayer */,
|
13DC0C442D302C6A00D0F966 /* MediaPlayer */,
|
||||||
|
|
@ -400,14 +392,6 @@
|
||||||
path = Auth;
|
path = Auth;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
13DB7CEA2D7DED50004371D3 /* DownloadManager */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
13DB7CEB2D7DED5D004371D3 /* DownloadManager.swift */,
|
|
||||||
);
|
|
||||||
path = DownloadManager;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
13DC0C442D302C6A00D0F966 /* MediaPlayer */ = {
|
13DC0C442D302C6A00D0F966 /* MediaPlayer */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -456,7 +440,6 @@
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
133D7C962D2BE2AF0075467E /* Kingfisher */,
|
133D7C962D2BE2AF0075467E /* Kingfisher */,
|
||||||
1359ED192D76FA7D00C13034 /* Drops */,
|
1359ED192D76FA7D00C13034 /* Drops */,
|
||||||
13DB7CC52D7DC7D2004371D3 /* FFmpeg-iOS-Lame */,
|
|
||||||
);
|
);
|
||||||
productName = Sora;
|
productName = Sora;
|
||||||
productReference = 133D7C6A2D2BE2500075467E /* Sulfur.app */;
|
productReference = 133D7C6A2D2BE2500075467E /* Sulfur.app */;
|
||||||
|
|
@ -488,7 +471,6 @@
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
133D7C952D2BE2AF0075467E /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
133D7C952D2BE2AF0075467E /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
||||||
1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */,
|
1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */,
|
||||||
13DB7CC42D7DC7D2004371D3 /* XCRemoteSwiftPackageReference "FFmpeg-iOS-Lame" */,
|
|
||||||
);
|
);
|
||||||
productRefGroup = 133D7C6B2D2BE2500075467E /* Products */;
|
productRefGroup = 133D7C6B2D2BE2500075467E /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
|
@ -534,7 +516,6 @@
|
||||||
133D7C932D2BE2640075467E /* Modules.swift in Sources */,
|
133D7C932D2BE2640075467E /* Modules.swift in Sources */,
|
||||||
13DB7CC32D7D99C0004371D3 /* SubtitleSettingsManager.swift in Sources */,
|
13DB7CC32D7D99C0004371D3 /* SubtitleSettingsManager.swift in Sources */,
|
||||||
133D7C702D2BE2500075467E /* ContentView.swift in Sources */,
|
133D7C702D2BE2500075467E /* ContentView.swift in Sources */,
|
||||||
13DB7CEC2D7DED5D004371D3 /* DownloadManager.swift in Sources */,
|
|
||||||
1334FF522D7871B7007E289F /* TMDBItem.swift in Sources */,
|
1334FF522D7871B7007E289F /* TMDBItem.swift in Sources */,
|
||||||
13D99CF72D4E73C300250A86 /* ModuleAdditionSettingsView.swift in Sources */,
|
13D99CF72D4E73C300250A86 /* ModuleAdditionSettingsView.swift in Sources */,
|
||||||
13C0E5EC2D5F85F800E7F619 /* ContinueWatchingItem.swift in Sources */,
|
13C0E5EC2D5F85F800E7F619 /* ContinueWatchingItem.swift in Sources */,
|
||||||
|
|
@ -554,7 +535,6 @@
|
||||||
133D7C942D2BE2640075467E /* JSController.swift in Sources */,
|
133D7C942D2BE2640075467E /* JSController.swift in Sources */,
|
||||||
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
133D7C922D2BE2640075467E /* URLSession.swift in Sources */,
|
||||||
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
|
133D7C912D2BE2640075467E /* SettingsViewModule.swift in Sources */,
|
||||||
130217CC2D81C55E0011EFF5 /* DownloadView.swift in Sources */,
|
|
||||||
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */,
|
133F55BB2D33B55100E08EEA /* LibraryManager.swift in Sources */,
|
||||||
133D7C8E2D2BE2640075467E /* LibraryView.swift in Sources */,
|
133D7C8E2D2BE2640075467E /* LibraryView.swift in Sources */,
|
||||||
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */,
|
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */,
|
||||||
|
|
@ -814,14 +794,6 @@
|
||||||
kind = branch;
|
kind = branch;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
13DB7CC42D7DC7D2004371D3 /* XCRemoteSwiftPackageReference "FFmpeg-iOS-Lame" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/kewlbear/FFmpeg-iOS-Lame";
|
|
||||||
requirement = {
|
|
||||||
branch = main;
|
|
||||||
kind = branch;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
|
@ -835,11 +807,6 @@
|
||||||
package = 1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */;
|
package = 1359ED182D76FA7D00C13034 /* XCRemoteSwiftPackageReference "Drops" */;
|
||||||
productName = Drops;
|
productName = Drops;
|
||||||
};
|
};
|
||||||
13DB7CC52D7DC7D2004371D3 /* FFmpeg-iOS-Lame */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 13DB7CC42D7DC7D2004371D3 /* XCRemoteSwiftPackageReference "FFmpeg-iOS-Lame" */;
|
|
||||||
productName = "FFmpeg-iOS-Lame";
|
|
||||||
};
|
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 133D7C622D2BE2500075467E /* Project object */;
|
rootObject = 133D7C622D2BE2500075467E /* Project object */;
|
||||||
|
|
|
||||||
|
|
@ -10,24 +10,6 @@
|
||||||
"version": null
|
"version": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"package": "FFmpeg-iOS-Lame",
|
|
||||||
"repositoryURL": "https://github.com/kewlbear/FFmpeg-iOS-Lame",
|
|
||||||
"state": {
|
|
||||||
"branch": "main",
|
|
||||||
"revision": "1808fa5a1263c5e216646cd8421fc7dcb70520cc",
|
|
||||||
"version": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "FFmpeg-iOS-Support",
|
|
||||||
"repositoryURL": "https://github.com/kewlbear/FFmpeg-iOS-Support",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "be3bd9149ac53760e8725652eee99c405b2be47a",
|
|
||||||
"version": "0.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"package": "Kingfisher",
|
"package": "Kingfisher",
|
||||||
"repositoryURL": "https://github.com/onevcat/Kingfisher.git",
|
"repositoryURL": "https://github.com/onevcat/Kingfisher.git",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue