From 69a9d30475cab17fd23be474f2ad46fc378fda44 Mon Sep 17 00:00:00 2001 From: kingbri Date: Sun, 2 Jun 2024 23:08:05 -0400 Subject: [PATCH] Debrid: Add InstantAvailability and download to protocol Unify IA into a passable client side structure and add a common download method to the DebridSource protocol. Signed-off-by: kingbri --- Ferrite.xcodeproj/project.pbxproj | 2 +- Ferrite/API/AllDebridWrapper.swift | 23 ++- Ferrite/API/PremiumizeWrapper.swift | 30 ++-- Ferrite/API/RealDebridWrapper.swift | 61 ++++---- Ferrite/Models/DebridModels.swift | 22 ++- Ferrite/Models/RealDebridModels.swift | 13 -- Ferrite/Protocols/Debrid.swift | 5 +- Ferrite/ViewModels/DebridManager.swift | 134 +++++++----------- .../Views/CommonViews/HybridSecureField.swift | 4 +- Ferrite/Views/SettingsView.swift | 2 +- .../Views/SheetViews/BatchChoiceView.swift | 6 +- 11 files changed, 160 insertions(+), 142 deletions(-) diff --git a/Ferrite.xcodeproj/project.pbxproj b/Ferrite.xcodeproj/project.pbxproj index 14919aa..ed626ca 100644 --- a/Ferrite.xcodeproj/project.pbxproj +++ b/Ferrite.xcodeproj/project.pbxproj @@ -394,6 +394,7 @@ 0C6C7C9C29315292002DF910 /* AllDebridModels.swift */, 0C7ED14028D61BBA009E29AD /* BackupModels.swift */, 0C0755C7293425B500ECA142 /* DebridManagerModels.swift */, + 0CF1ABE12C0C3D2F009F6C26 /* DebridModels.swift */, 0C84FCE629E4B61A00B0DFE4 /* FilterModels.swift */, 0C68135128BC1A7C00FAD890 /* GithubModels.swift */, 0C422E7F293542F300486D65 /* PremiumizeModels.swift */, @@ -403,7 +404,6 @@ 0C3E00D7296F5B9A00ECECB2 /* PluginModels.swift */, 0C6771F929B3D1AE005D38D2 /* KodiModels.swift */, 0C1A3E5129C8A7F500DA9730 /* SettingsModels.swift */, - 0CF1ABE12C0C3D2F009F6C26 /* DebridModels.swift */, ); path = Models; sourceTree = ""; diff --git a/Ferrite/API/AllDebridWrapper.swift b/Ferrite/API/AllDebridWrapper.swift index 0f2c50e..c5616ee 100644 --- a/Ferrite/API/AllDebridWrapper.swift +++ b/Ferrite/API/AllDebridWrapper.swift @@ -9,7 +9,6 @@ import Foundation // TODO: Fix errors public class AllDebrid: PollingDebridSource { - public let id = "AllDebrid" public var authTask: Task? @@ -96,7 +95,7 @@ public class AllDebrid: PollingDebridSource { } public func getToken() -> String? { - return FerriteKeychain.shared.get("AllDebrid.ApiKey") + FerriteKeychain.shared.get("AllDebrid.ApiKey") } // Clears tokens. No endpoint to deregister a device @@ -146,6 +145,20 @@ public class AllDebrid: PollingDebridSource { } } + // Wrapper function to fetch a download link from the API + public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { + let magnetID = try await addMagnet(magnet: magnet) + let lockedLink = try await fetchMagnetStatus( + magnetId: magnetID, + selectedIndex: iaFile?.fileId ?? 0 + ) + + try await saveLink(link: lockedLink) + let downloadUrl = try await unlockLink(lockedLink: lockedLink) + + return downloadUrl + } + // Adds a magnet link to the user's AD account public func addMagnet(magnet: Magnet) async throws -> Int { guard let magnetLink = magnet.link else { @@ -255,7 +268,7 @@ public class AllDebrid: PollingDebridSource { try await performRequest(request: &request, requestName: #function) } - public func instantAvailability(magnets: [Magnet]) async throws -> [IA] { + public func instantAvailability(magnets: [Magnet]) async throws -> [DebridIA] { let queryItems = magnets.map { URLQueryItem(name: "magnets[]", value: $0.hash) } var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/instant", queryItems: queryItems)) @@ -266,10 +279,10 @@ public class AllDebrid: PollingDebridSource { let availableHashes = filteredMagnets.map { magnetResp in // Force unwrap is OK here since the filter caught any nil values let files = magnetResp.files!.enumerated().map { index, magnetFile in - IAFile(id: index, fileName: magnetFile.name) + DebridIAFile(fileId: index, name: magnetFile.name) } - return IA( + return DebridIA( magnet: Magnet(hash: magnetResp.hash, link: magnetResp.magnet), expiryTimeStamp: Date().timeIntervalSince1970 + 300, files: files diff --git a/Ferrite/API/PremiumizeWrapper.swift b/Ferrite/API/PremiumizeWrapper.swift index d771536..d0ab2eb 100644 --- a/Ferrite/API/PremiumizeWrapper.swift +++ b/Ferrite/API/PremiumizeWrapper.swift @@ -8,7 +8,6 @@ import Foundation public class Premiumize: OAuthDebridSource { - public let id = "Premiumize" let baseAuthUrl = "https://www.premiumize.me/authorize" @@ -58,7 +57,7 @@ public class Premiumize: OAuthDebridSource { } public func getToken() -> String? { - return FerriteKeychain.shared.get("Premiumize.AccessToken") + FerriteKeychain.shared.get("Premiumize.AccessToken") } // Clears tokens. No endpoint to deregister a device @@ -162,15 +161,15 @@ public class Premiumize: OAuthDebridSource { // Function to divide and execute DDL endpoint requests in parallel // Calls this for 10 requests at a time to not overwhelm API servers - public func divideDDLRequests(magnetChunk: [Magnet]) async throws -> [IA] { - let tempIA = try await withThrowingTaskGroup(of: Premiumize.IA.self) { group in + public func divideDDLRequests(magnetChunk: [Magnet]) async throws -> [DebridIA] { + let tempIA = try await withThrowingTaskGroup(of: DebridIA.self) { group in for magnet in magnetChunk { group.addTask { try await self.fetchDDL(magnet: magnet) } } - var chunkedIA: [Premiumize.IA] = [] + var chunkedIA: [DebridIA] = [] for try await ia in group { chunkedIA.append(ia) } @@ -181,7 +180,7 @@ public class Premiumize: OAuthDebridSource { } // Grabs DDL links - func fetchDDL(magnet: Magnet) async throws -> IA { + func fetchDDL(magnet: Magnet) async throws -> DebridIA { if magnet.hash == nil { throw PMError.EmptyData } @@ -200,13 +199,14 @@ public class Premiumize: OAuthDebridSource { if !rawResponse.content.isEmpty { let files = rawResponse.content.map { file in - IAFile( + DebridIAFile( + fileId: 0, name: file.path.split(separator: "/").last.flatMap { String($0) } ?? file.path, streamUrlString: file.link ) } - return IA( + return DebridIA( magnet: magnet, expiryTimeStamp: Date().timeIntervalSince1970 + 300, files: files @@ -216,6 +216,20 @@ public class Premiumize: OAuthDebridSource { } } + // Wrapper function to fetch a DDL link from the API + public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { + // Store the item in PM cloud for later use + try await createTransfer(magnet: magnet) + + if let iaFile, let streamUrlString = iaFile.streamUrlString { + return streamUrlString + } else if let premiumizeItem = ia, let firstFile = premiumizeItem.files[safe: 0], let streamUrlString = firstFile.streamUrlString { + return streamUrlString + } else { + throw PMError.FailedRequest(description: "Could not fetch your file from the Premiumize API") + } + } + func createTransfer(magnet: Magnet) async throws { guard let magnetLink = magnet.link else { throw PMError.FailedRequest(description: "The magnet link is invalid") diff --git a/Ferrite/API/RealDebridWrapper.swift b/Ferrite/API/RealDebridWrapper.swift index 14e46a5..f11812d 100644 --- a/Ferrite/API/RealDebridWrapper.swift +++ b/Ferrite/API/RealDebridWrapper.swift @@ -8,7 +8,6 @@ import Foundation public class RealDebrid: PollingDebridSource { - public let id = "RealDebrid" public var authTask: Task? @@ -87,7 +86,7 @@ public class RealDebrid: PollingDebridSource { let (data, _) = try await URLSession.shared.data(for: request) // We don't care if this fails - let rawResponse = try? self.jsonDecoder.decode(DeviceCredentialsResponse.self, from: data) + let rawResponse = try? jsonDecoder.decode(DeviceCredentialsResponse.self, from: data) // If there's a client ID from the response, end the task successfully if let clientId = rawResponse?.clientID, let clientSecret = rawResponse?.clientSecret { @@ -169,7 +168,7 @@ public class RealDebrid: PollingDebridSource { return FerriteKeychain.shared.get("RealDebrid.AccessToken") == key } - + // Deletes tokens from device and RD's servers public func logout() async { FerriteKeychain.shared.delete("RealDebrid.RefreshToken") @@ -213,9 +212,8 @@ public class RealDebrid: PollingDebridSource { } // Checks if the magnet is streamable on RD - // Currently does not work for batch links - public func instantAvailability(magnets: [Magnet]) async throws -> [IA] { - var availableHashes: [RealDebrid.IA] = [] + public func instantAvailability(magnets: [Magnet]) async throws -> [DebridIA] { + var availableHashes: [DebridIA] = [] var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/instantAvailability/\(magnets.compactMap(\.hash).joined(separator: "/"))")!) let data = try await performRequest(request: &request, requestName: #function) @@ -232,7 +230,7 @@ public class RealDebrid: PollingDebridSource { continue } - // Is this a batch + // Is this a batch? if data.rd.count > 1 || data.rd[0].count > 1 { // Batch array let batches = data.rd.map { fileDict in @@ -244,22 +242,18 @@ public class RealDebrid: PollingDebridSource { return RealDebrid.IABatch(files: batchFiles) } - // RD files array - // Possibly sort this in the future, but not sure how at the moment - var files: [RealDebrid.IAFile] = [] + var files: [DebridIAFile] = [] - for index in batches.indices { - let batchFiles = batches[index].files + for batch in batches { + let batchFileIds = batch.files.map(\.id) - for batchFileIndex in batchFiles.indices { - let batchFile = batchFiles[batchFileIndex] - - if !files.contains(where: { $0.name == batchFile.fileName }) { + for batchFile in batch.files { + if !files.contains(where: { $0.fileId == batchFile.id }) { files.append( - RealDebrid.IAFile( + DebridIAFile( + fileId: batchFile.id, name: batchFile.fileName, - batchIndex: index, - batchFileIndex: batchFileIndex + batchIds: batchFileIds ) ) } @@ -268,18 +262,18 @@ public class RealDebrid: PollingDebridSource { // TTL: 5 minutes availableHashes.append( - RealDebrid.IA( + DebridIA( magnet: Magnet(hash: hash, link: nil), expiryTimeStamp: Date().timeIntervalSince1970 + 300, - files: files, - batches: batches + files: files ) ) } else { availableHashes.append( - RealDebrid.IA( + DebridIA( magnet: Magnet(hash: hash, link: nil), - expiryTimeStamp: Date().timeIntervalSince1970 + 300 + expiryTimeStamp: Date().timeIntervalSince1970 + 300, + files: [] ) ) } @@ -288,6 +282,21 @@ public class RealDebrid: PollingDebridSource { return availableHashes } + // Wrapper function to fetch a download link from the API + public func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String { + let selectedMagnetId = try await addMagnet(magnet: magnet) + + try await selectFiles(debridID: selectedMagnetId, fileIds: iaFile?.batchIds ?? []) + + let torrentLink = try await torrentInfo( + debridID: selectedMagnetId, + selectedIndex: iaFile?.fileId ?? 0 + ) + let downloadLink = try await unrestrictLink(debridDownloadLink: torrentLink) + + return downloadLink + } + // Adds a magnet link to the user's RD account public func addMagnet(magnet: Magnet) async throws -> String { guard let magnetLink = magnet.link else { @@ -335,9 +344,11 @@ public class RealDebrid: PollingDebridSource { let data = try await performRequest(request: &request, requestName: #function) let rawResponse = try jsonDecoder.decode(TorrentInfoResponse.self, from: data) + let filteredFiles = rawResponse.files.filter { $0.selected == 1 } + let linkIndex = filteredFiles.firstIndex(where: { $0.id == selectedIndex }) // Let the user know if a torrent is downloading - if let torrentLink = rawResponse.links[safe: selectedIndex ?? -1], rawResponse.status == "downloaded" { + if let torrentLink = rawResponse.links[safe: linkIndex ?? -1], rawResponse.status == "downloaded" { return torrentLink } else if rawResponse.status == "downloading" || rawResponse.status == "queued" { throw RDError.EmptyTorrents diff --git a/Ferrite/Models/DebridModels.swift b/Ferrite/Models/DebridModels.swift index 011c61f..14a46a1 100644 --- a/Ferrite/Models/DebridModels.swift +++ b/Ferrite/Models/DebridModels.swift @@ -7,10 +7,24 @@ import Foundation -public struct DebridIAFile { - +public struct DebridIA: Sendable, Hashable { + let magnet: Magnet + let expiryTimeStamp: Double + var files: [DebridIAFile] } -public struct DebridCloudFile { - +public struct DebridIAFile: Hashable, Sendable { + let fileId: Int + let name: String + let streamUrlString: String? + let batchIds: [Int] + + init(fileId: Int, name: String, streamUrlString: String? = nil, batchIds: [Int] = []) { + self.fileId = fileId + self.name = name + self.streamUrlString = streamUrlString + self.batchIds = batchIds + } } + +public struct DebridCloudFile {} diff --git a/Ferrite/Models/RealDebridModels.swift b/Ferrite/Models/RealDebridModels.swift index 393acb6..134026f 100644 --- a/Ferrite/Models/RealDebridModels.swift +++ b/Ferrite/Models/RealDebridModels.swift @@ -92,13 +92,6 @@ public extension RealDebrid { // MARK: - Instant Availability client side structures - struct IA: Codable, Hashable, Sendable { - let magnet: Magnet - let expiryTimeStamp: Double - var files: [IAFile] = [] - var batches: [IABatch] = [] - } - struct IABatch: Codable, Hashable, Sendable { let files: [IABatchFile] } @@ -108,12 +101,6 @@ public extension RealDebrid { let fileName: String } - struct IAFile: Codable, Hashable, Sendable { - let name: String - let batchIndex: Int - let batchFileIndex: Int - } - // MARK: - addMagnet endpoint struct AddMagnetResponse: Codable, Sendable { diff --git a/Ferrite/Protocols/Debrid.swift b/Ferrite/Protocols/Debrid.swift index 3a51061..396ebe6 100644 --- a/Ferrite/Protocols/Debrid.swift +++ b/Ferrite/Protocols/Debrid.swift @@ -14,6 +14,10 @@ public protocol DebridSource { // Common authentication functions func setApiKey(_ key: String) -> Bool func logout() async + + // Fetches a download link from a source + // Include the instant availability information with the args + func getDownloadLink(magnet: Magnet, ia: DebridIA?, iaFile: DebridIAFile?) async throws -> String } public protocol PollingDebridSource: DebridSource { @@ -25,7 +29,6 @@ public protocol PollingDebridSource: DebridSource { } public protocol OAuthDebridSource: DebridSource { - // Fetches the auth URL func getAuthUrl() throws -> URL diff --git a/Ferrite/ViewModels/DebridManager.swift b/Ferrite/ViewModels/DebridManager.swift index 5d464fd..c39c904 100644 --- a/Ferrite/ViewModels/DebridManager.swift +++ b/Ferrite/ViewModels/DebridManager.swift @@ -59,12 +59,12 @@ public class DebridManager: ObservableObject { var realDebridAuthProcessing: Bool = false // RealDebrid fetch variables - @Published var realDebridIAValues: [RealDebrid.IA] = [] + @Published var realDebridIAValues: [DebridIA] = [] @Published var showDeleteAlert: Bool = false - var selectedRealDebridItem: RealDebrid.IA? - var selectedRealDebridFile: RealDebrid.IAFile? + var selectedRealDebridItem: DebridIA? + var selectedRealDebridFile: DebridIAFile? var selectedRealDebridID: String? // TODO: Maybe make these generic? @@ -77,10 +77,10 @@ public class DebridManager: ObservableObject { var allDebridAuthProcessing: Bool = false // AllDebrid fetch variables - @Published var allDebridIAValues: [AllDebrid.IA] = [] + @Published var allDebridIAValues: [DebridIA] = [] - var selectedAllDebridItem: AllDebrid.IA? - var selectedAllDebridFile: AllDebrid.IAFile? + var selectedAllDebridItem: DebridIA? + var selectedAllDebridFile: DebridIAFile? // AllDebrid cloud variables @Published var allDebridCloudMagnets: [AllDebrid.MagnetStatusData] = [] @@ -91,10 +91,10 @@ public class DebridManager: ObservableObject { var premiumizeAuthProcessing: Bool = false // Premiumize fetch variables - @Published var premiumizeIAValues: [Premiumize.IA] = [] + @Published var premiumizeIAValues: [DebridIA] = [] - var selectedPremiumizeItem: Premiumize.IA? - var selectedPremiumizeFile: Premiumize.IAFile? + var selectedPremiumizeItem: DebridIA? + var selectedPremiumizeFile: DebridIAFile? // Premiumize cloud variables @Published var premiumizeCloudItems: [Premiumize.UserItem] = [] @@ -282,10 +282,10 @@ public class DebridManager: ObservableObject { return .none } - if realDebridMatch.batches.isEmpty { - return .full - } else { + if realDebridMatch.files.count > 1 { return .partial + } else { + return .full } case .allDebrid: guard let allDebridMatch = allDebridIAValues.first(where: { magnetHash == $0.magnet.hash }) else { @@ -578,7 +578,7 @@ public class DebridManager: ObservableObject { case .allDebrid: await fetchAdDownload(magnet: magnet, existingLockedLink: cloudInfo) case .premiumize: - await fetchPmDownload(cloudItemId: cloudInfo) + await fetchPmDownload(magnet: magnet, cloudItemId: cloudInfo) case .none: break } @@ -586,6 +586,7 @@ public class DebridManager: ObservableObject { func fetchRdDownload(magnet: Magnet?, existingLink: String?) async { // If an existing link is passed in args, set it to that. Otherwise, find one from RD cloud. + /* let torrentLink: String? if let existingLink { torrentLink = existingLink @@ -596,42 +597,23 @@ public class DebridManager: ObservableObject { let existingTorrent = realDebridCloudTorrents.first { $0.hash == selectedRealDebridItem?.magnet.hash && $0.status == "downloaded" } torrentLink = existingTorrent?.links[safe: selectedRealDebridFile?.batchFileIndex ?? 0] } + */ do { // If the links match from a user's downloads, no need to re-run a download + /* if let torrentLink, let downloadLink = await checkRdUserDownloads(userTorrentLink: torrentLink) { downloadUrl = downloadLink - } else if let magnet { - // Add a magnet after all the cache checks fail - selectedRealDebridID = try await realDebrid.addMagnet(magnet: magnet) + } else */ + if let magnet { + let downloadLink = try await realDebrid.getDownloadLink( + magnet: magnet, ia: selectedRealDebridItem, iaFile: selectedRealDebridFile + ) - var fileIds: [Int] = [] - if let iaFile = selectedRealDebridFile { - guard let iaBatchFromFile = selectedRealDebridItem?.batches[safe: iaFile.batchIndex] else { - return - } - - fileIds = iaBatchFromFile.files.map(\.id) - } - - if let realDebridId = selectedRealDebridID { - try await realDebrid.selectFiles(debridID: realDebridId, fileIds: fileIds) - - let torrentLink = try await realDebrid.torrentInfo( - debridID: realDebridId, - selectedIndex: selectedRealDebridFile?.batchFileIndex ?? 0 - ) - let downloadLink = try await realDebrid.unrestrictLink(debridDownloadLink: torrentLink) - - downloadUrl = downloadLink - } else { - logManager?.error( - "RealDebrid: Could not cache torrent with hash \(String(describing: magnet.hash))", - description: "Could not cache this torrent. Aborting." - ) - } + // Update the UI + downloadUrl = downloadLink } else { throw RealDebrid.RDError.FailedRequest(description: "Could not fetch your file from RealDebrid's cache or API") } @@ -645,7 +627,7 @@ public class DebridManager: ObservableObject { default: await sendDebridError(error, prefix: "RealDebrid download error", cancelString: "Download cancelled") - await deleteRdTorrent(torrentID: selectedRealDebridID, presentError: false) + // await deleteRdTorrent(torrentID: selectedRealDebridID, presentError: false) } logManager?.hideIndeterminateToast() @@ -695,8 +677,6 @@ public class DebridManager: ObservableObject { do { if let torrentID { try await realDebrid.deleteTorrent(debridID: torrentID) - } else if let selectedTorrentID = selectedRealDebridID { - try await realDebrid.deleteTorrent(debridID: selectedTorrentID) } else { throw RealDebrid.RDError.FailedRequest(description: "No torrent ID was provided") } @@ -720,34 +700,36 @@ public class DebridManager: ObservableObject { } } - // TODO: Integrate with AD saved links func fetchAdDownload(magnet: Magnet?, existingLockedLink: String?) async { // If an existing link is passed in args, set it to that. Otherwise, find one from AD cloud. - let lockedLink: String? - if let existingLockedLink { - lockedLink = existingLockedLink - } else { - // Bypass the TTL for up to date information - await fetchAdCloud(bypassTTL: true) + /* + let lockedLink: String? + if let existingLockedLink { + lockedLink = existingLockedLink + } else { + // Bypass the TTL for up to date information + await fetchAdCloud(bypassTTL: true) - let existingMagnet = allDebridCloudMagnets.first { $0.hash == selectedAllDebridItem?.magnet.hash && $0.status == "Ready" } - lockedLink = existingMagnet?.links[safe: selectedAllDebridFile?.id ?? 0]?.link - } + let existingMagnet = allDebridCloudMagnets.first { $0.hash == selectedAllDebridItem?.magnet.hash && $0.status == "Ready" } + lockedLink = existingMagnet?.links[safe: selectedAllDebridFile?.fileId ?? 0]?.link + } + */ do { - if let lockedLink, - let unlockedLink = await checkAdUserLinks(lockedLink: lockedLink) - { - downloadUrl = unlockedLink - } else if let magnet { - let magnetID = try await allDebrid.addMagnet(magnet: magnet) - let lockedLink = try await allDebrid.fetchMagnetStatus( - magnetId: magnetID, - selectedIndex: selectedAllDebridFile?.id ?? 0 + /* + if let lockedLink, + let unlockedLink = await checkAdUserLinks(lockedLink: lockedLink) + { + downloadUrl = unlockedLink + } else if let magnet { + */ + if let magnet { + let downloadLink = try await allDebrid.getDownloadLink( + magnet: magnet, ia: selectedAllDebridItem, iaFile: selectedAllDebridFile ) - try await allDebrid.saveLink(link: lockedLink) - downloadUrl = try await allDebrid.unlockLink(lockedLink: lockedLink) + // Update UI + downloadUrl = downloadLink } else { throw AllDebrid.ADError.FailedRequest(description: "Could not fetch your file from AllDebrid's cache or API") } @@ -810,28 +792,22 @@ public class DebridManager: ObservableObject { } } - func fetchPmDownload(cloudItemId: String? = nil) async { + func fetchPmDownload(magnet: Magnet?, cloudItemId: String? = nil) async { do { if let cloudItemId { downloadUrl = try await premiumize.itemDetails(itemID: cloudItemId).link - } else if let premiumizeFile = selectedPremiumizeFile { - downloadUrl = premiumizeFile.streamUrlString - } else if - let premiumizeItem = selectedPremiumizeItem, - let firstFile = premiumizeItem.files[safe: 0] - { - downloadUrl = firstFile.streamUrlString + } else if let magnet { + let downloadLink = try await premiumize.getDownloadLink( + magnet: magnet, ia: selectedPremiumizeItem, iaFile: selectedPremiumizeFile + ) + + downloadUrl = downloadLink } else { - throw Premiumize.PMError.FailedRequest(description: "There were no items or files found!") + throw Premiumize.PMError.FailedRequest(description: "Could not fetch your file from Premiumize's cache or API") } // Fetch one more time to add updated data into the PM cloud cache await fetchPmCloud(bypassTTL: true) - - // Add a PM transfer if the item exists - if let premiumizeItem = selectedPremiumizeItem { - try await premiumize.createTransfer(magnet: premiumizeItem.magnet) - } } catch { await sendDebridError(error, prefix: "Premiumize download error", cancelString: "Download or transfer cancelled") } diff --git a/Ferrite/Views/CommonViews/HybridSecureField.swift b/Ferrite/Views/CommonViews/HybridSecureField.swift index d1ac923..665623e 100644 --- a/Ferrite/Views/CommonViews/HybridSecureField.swift +++ b/Ferrite/Views/CommonViews/HybridSecureField.swift @@ -21,7 +21,7 @@ struct HybridSecureField: View { private var isFieldDisabled: Bool = false init(text: Binding, onCommit: (() -> Void)? = nil, showPassword: Bool = false) { - self._text = text + _text = text if let onCommit { self.onCommit = onCommit } @@ -57,6 +57,6 @@ struct HybridSecureField: View { extension HybridSecureField { public func fieldDisabled(_ isFieldDisabled: Bool) -> Self { - modifyViewProp({ $0.isFieldDisabled = isFieldDisabled }) + modifyViewProp { $0.isFieldDisabled = isFieldDisabled } } } diff --git a/Ferrite/Views/SettingsView.swift b/Ferrite/Views/SettingsView.swift index 28f18fc..019c6bb 100644 --- a/Ferrite/Views/SettingsView.swift +++ b/Ferrite/Views/SettingsView.swift @@ -96,7 +96,7 @@ struct SettingsView: View { if changed { Task { let dataRecords = await WKWebsiteDataStore.default().dataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) - + await WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: dataRecords) } } diff --git a/Ferrite/Views/SheetViews/BatchChoiceView.swift b/Ferrite/Views/SheetViews/BatchChoiceView.swift index 771395f..5e7e9da 100644 --- a/Ferrite/Views/SheetViews/BatchChoiceView.swift +++ b/Ferrite/Views/SheetViews/BatchChoiceView.swift @@ -36,11 +36,11 @@ struct BatchChoiceView: View { } case .allDebrid: ForEach(debridManager.selectedAllDebridItem?.files ?? [], id: \.self) { file in - if file.fileName.lowercased().contains(searchText.lowercased()) || searchText.isEmpty { - Button(file.fileName) { + if file.name.lowercased().contains(searchText.lowercased()) || searchText.isEmpty { + Button(file.name) { debridManager.selectedAllDebridFile = file - queueCommonDownload(fileName: file.fileName) + queueCommonDownload(fileName: file.name) } } }