diff --git a/Sora/Utils/JSLoader/JSController+M3U8Download.swift b/Sora/Utils/JSLoader/Downloads/JSController+M3U8Download.swift similarity index 100% rename from Sora/Utils/JSLoader/JSController+M3U8Download.swift rename to Sora/Utils/JSLoader/Downloads/JSController+M3U8Download.swift diff --git a/Sora/Utils/JSLoader/JSController+MP4Download.swift b/Sora/Utils/JSLoader/Downloads/JSController+MP4Download.swift similarity index 100% rename from Sora/Utils/JSLoader/JSController+MP4Download.swift rename to Sora/Utils/JSLoader/Downloads/JSController+MP4Download.swift diff --git a/Sora/Utils/JSLoader/JSController-Downloads.swift b/Sora/Utils/JSLoader/Downloads/JSController-Downloads.swift similarity index 100% rename from Sora/Utils/JSLoader/JSController-Downloads.swift rename to Sora/Utils/JSLoader/Downloads/JSController-Downloads.swift diff --git a/Sora/Utils/JSLoader/JSController-HeaderManager.swift b/Sora/Utils/JSLoader/Downloads/JSController-HeaderManager.swift similarity index 100% rename from Sora/Utils/JSLoader/JSController-HeaderManager.swift rename to Sora/Utils/JSLoader/Downloads/JSController-HeaderManager.swift diff --git a/Sora/Utils/JSLoader/JSController-StreamTypeDownload.swift b/Sora/Utils/JSLoader/Downloads/JSController-StreamTypeDownload.swift similarity index 100% rename from Sora/Utils/JSLoader/JSController-StreamTypeDownload.swift rename to Sora/Utils/JSLoader/Downloads/JSController-StreamTypeDownload.swift diff --git a/Sora/Utils/JSLoader/JSController.swift b/Sora/Utils/JSLoader/JSController.swift index 486693d..c50eb0d 100644 --- a/Sora/Utils/JSLoader/JSController.swift +++ b/Sora/Utils/JSLoader/JSController.swift @@ -11,39 +11,26 @@ import SwiftUI import AVKit import AVFoundation -// Use ScrapingModule from Modules.swift as Module typealias Module = ScrapingModule class JSController: NSObject, ObservableObject { - // Shared instance that can be used across the app static let shared = JSController() var context: JSContext - // Downloaded assets storage @Published var savedAssets: [DownloadedAsset] = [] @Published var activeDownloads: [JSActiveDownload] = [] - - // Tracking map for download tasks var activeDownloadMap: [URLSessionTask: UUID] = [:] - - // Download queue management @Published var downloadQueue: [JSActiveDownload] = [] var isProcessingQueue: Bool = false + var maxConcurrentDownloads: Int { UserDefaults.standard.object(forKey: "maxConcurrentDownloads") as? Int ?? 3 } - // Track downloads that have been cancelled to prevent completion processing var cancelledDownloadIDs: Set = [] - - // Download session var downloadURLSession: AVAssetDownloadURLSession? - - // For MP4 download progress tracking var mp4ProgressObservations: [UUID: NSKeyValueObservation]? - - // For storing custom URLSessions used for MP4 downloads var mp4CustomSessions: [UUID: URLSession]? override init() { @@ -58,9 +45,7 @@ class JSController: NSObject, ObservableObject { setupDownloadSession() } - // Setup download functionality separately from general context setup private func setupDownloadSession() { - // Only initialize download session if it doesn't exist already if downloadURLSession == nil { initializeDownloadSession() setupDownloadFunction() @@ -69,7 +54,6 @@ class JSController: NSObject, ObservableObject { func loadScript(_ script: String) { context = JSContext() - // Only set up the JavaScript environment without reinitializing the download session context.setupJavaScriptEnvironment() context.evaluateScript(script) if let exception = context.exception { @@ -77,23 +61,15 @@ class JSController: NSObject, ObservableObject { } } - // MARK: - Download Settings - - /// Updates the maximum number of concurrent downloads and processes the queue if new slots are available func updateMaxConcurrentDownloads(_ newLimit: Int) { print("Updating max concurrent downloads from \(maxConcurrentDownloads) to \(newLimit)") - - // The maxConcurrentDownloads computed property will automatically use the new UserDefaults value - // If the new limit is higher and we have queued downloads, process the queue if !downloadQueue.isEmpty && !isProcessingQueue { print("Processing download queue due to increased concurrent limit. Queue has \(downloadQueue.count) items.") - // Force UI update before processing queue DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.objectWillChange.send() - // Process the queue with a slight delay to ensure UI is ready DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in self?.processDownloadQueue() } @@ -102,21 +78,4 @@ class JSController: NSObject, ObservableObject { print("No queued downloads to process or queue is already being processed") } } - - // MARK: - Stream URL Functions - Convenience methods - - func fetchStreamUrl(episodeUrl: String, module: Module, completion: @escaping ((streams: [String]?, subtitles: [String]?)) -> Void) { - // Implementation for the main fetchStreamUrl method - } - - func fetchStreamUrlJS(episodeUrl: String, module: Module, completion: @escaping ((streams: [String]?, subtitles: [String]?)) -> Void) { - // Implementation for the JS based stream URL fetching - } - - func fetchStreamUrlJSSecond(episodeUrl: String, module: Module, completion: @escaping ((streams: [String]?, subtitles: [String]?)) -> Void) { - // Implementation for the secondary JS based stream URL fetching - } - - // MARK: - Header Management - // Header management functions are implemented in JSController-HeaderManager.swift extension file } diff --git a/Sulfur.xcodeproj/project.pbxproj b/Sulfur.xcodeproj/project.pbxproj index c4553d9..110a1b0 100644 --- a/Sulfur.xcodeproj/project.pbxproj +++ b/Sulfur.xcodeproj/project.pbxproj @@ -339,11 +339,7 @@ 133D7C8A2D2BE2640075467E /* JSLoader */ = { isa = PBXGroup; children = ( - 7272206F2DD642B100C2A4A2 /* JSController-StreamTypeDownload.swift */, - 727220702DD642B100C2A4A2 /* JSController+MP4Download.swift */, - 722248652DCBC13E00CABE2D /* JSController-Downloads.swift */, - 722248612DCBAA4700CABE2D /* JSController-HeaderManager.swift */, - 722248622DCBAA4700CABE2D /* JSController+M3U8Download.swift */, + 134A387B2DE4B5B90041B687 /* Downloads */, 133D7C8B2D2BE2640075467E /* JSController.swift */, 132AF1202D99951700A0140B /* JSController-Streams.swift */, 132AF1222D9995C300A0140B /* JSController-Details.swift */, @@ -361,6 +357,18 @@ path = LibraryView; sourceTree = ""; }; + 134A387B2DE4B5B90041B687 /* Downloads */ = { + isa = PBXGroup; + children = ( + 7272206F2DD642B100C2A4A2 /* JSController-StreamTypeDownload.swift */, + 727220702DD642B100C2A4A2 /* JSController+MP4Download.swift */, + 722248652DCBC13E00CABE2D /* JSController-Downloads.swift */, + 722248612DCBAA4700CABE2D /* JSController-HeaderManager.swift */, + 722248622DCBAA4700CABE2D /* JSController+M3U8Download.swift */, + ); + path = Downloads; + sourceTree = ""; + }; 1384DCDF2D89BE870094797A /* Helpers */ = { isa = PBXGroup; children = (