From 243a16e3c4d2297ab2415b5871d81ca37ce0be63 Mon Sep 17 00:00:00 2001 From: kingbri Date: Thu, 6 Jun 2024 18:10:54 -0400 Subject: [PATCH] Debrid: Unify cloud views Cloud torrents and downloads are unified with the new protocol. Signed-off-by: kingbri --- Ferrite.xcodeproj/project.pbxproj | 20 +-- Ferrite/API/AllDebridWrapper.swift | 8 +- Ferrite/API/PremiumizeWrapper.swift | 8 +- Ferrite/API/RealDebridWrapper.swift | 8 +- Ferrite/Protocols/Debrid.swift | 4 +- Ferrite/ViewModels/DebridManager.swift | 153 ++++-------------- .../Library/Cloud/CloudDownloadView.swift | 57 +++++++ ...CloudView.swift => CloudTorrentView.swift} | 71 +++----- .../Library/Cloud/PremiumizeCloudView.swift | 60 ------- .../Library/Cloud/RealDebridCloudView.swift | 126 --------------- .../Library/DebridCloudView.swift | 17 +- Ferrite/Views/LibraryView.swift | 8 +- 12 files changed, 141 insertions(+), 399 deletions(-) create mode 100644 Ferrite/Views/ComponentViews/Library/Cloud/CloudDownloadView.swift rename Ferrite/Views/ComponentViews/Library/Cloud/{AllDebridCloudView.swift => CloudTorrentView.swift} (57%) delete mode 100644 Ferrite/Views/ComponentViews/Library/Cloud/PremiumizeCloudView.swift delete mode 100644 Ferrite/Views/ComponentViews/Library/Cloud/RealDebridCloudView.swift diff --git a/Ferrite.xcodeproj/project.pbxproj b/Ferrite.xcodeproj/project.pbxproj index f957fd7..3c2c2bd 100644 --- a/Ferrite.xcodeproj/project.pbxproj +++ b/Ferrite.xcodeproj/project.pbxproj @@ -20,7 +20,6 @@ 0C1A3E5229C8A7F500DA9730 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C1A3E5129C8A7F500DA9730 /* SettingsModels.swift */; }; 0C1A3E5629C9488C00DA9730 /* CodableWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C1A3E5529C9488C00DA9730 /* CodableWrapper.swift */; }; 0C2886D22960AC2800D6FC16 /* DebridCloudView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C2886D12960AC2800D6FC16 /* DebridCloudView.swift */; }; - 0C2886D72960C50900D6FC16 /* RealDebridCloudView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C2886D62960C50900D6FC16 /* RealDebridCloudView.swift */; }; 0C2B028F29E9E61E00DCF127 /* SortFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C2B028E29E9E61E00DCF127 /* SortFilterView.swift */; }; 0C2D9653299316CC00A504B6 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C2D9652299316CC00A504B6 /* Tag.swift */; }; 0C31133C28B1ABFA004DCB0D /* SourceJsonParser+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C31133A28B1ABFA004DCB0D /* SourceJsonParser+CoreDataClass.swift */; }; @@ -54,7 +53,6 @@ 0C54D36428C5086E00BFEEE2 /* History+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C54D36228C5086E00BFEEE2 /* History+CoreDataProperties.swift */; }; 0C5708EB29B8F89300BE07F9 /* SettingsLogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C5708EA29B8F89300BE07F9 /* SettingsLogView.swift */; }; 0C57D4CC289032ED008534E8 /* SearchResultInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C57D4CB289032ED008534E8 /* SearchResultInfoView.swift */; }; - 0C5FCB05296744F300849E87 /* AllDebridCloudView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FCB04296744F300849E87 /* AllDebridCloudView.swift */; }; 0C64A4B4288903680079976D /* Base32 in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B3288903680079976D /* Base32 */; }; 0C64A4B7288903880079976D /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B6288903880079976D /* KeychainSwift */; }; 0C6771F429B3B4FD005D38D2 /* KodiWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C6771F329B3B4FD005D38D2 /* KodiWrapper.swift */; }; @@ -130,12 +128,13 @@ 0CA3FB2028B91D9500FA10A8 /* IndeterminateProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */; }; 0CA429F828C5098D000D0610 /* DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA429F728C5098D000D0610 /* DateFormatter.swift */; }; 0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = 0CAF1C7A286F5C8600296F86 /* SwiftSoup */; }; - 0CAF9319296399190050812A /* PremiumizeCloudView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CAF9318296399190050812A /* PremiumizeCloudView.swift */; }; 0CB0115B29D36D9E009AFEDE /* SearchResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB0115A29D36D9E009AFEDE /* SearchResultsView.swift */; }; 0CB0AB5F29BD2A200015422C /* KodiServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB0AB5E29BD2A200015422C /* KodiServerView.swift */; }; 0CB6516328C5A57300DCA721 /* ConditionalId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6516228C5A57300DCA721 /* ConditionalId.swift */; }; 0CB6516528C5A5D700DCA721 /* InlinedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6516428C5A5D700DCA721 /* InlinedList.swift */; }; 0CB6516A28C5B4A600DCA721 /* InlineHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6516928C5B4A600DCA721 /* InlineHeader.swift */; }; + 0CB725322C123E6F0047FC0B /* CloudDownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB725312C123E6F0047FC0B /* CloudDownloadView.swift */; }; + 0CB725342C123E760047FC0B /* CloudTorrentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB725332C123E760047FC0B /* CloudTorrentView.swift */; }; 0CBAB83628D12ED500AC903E /* DisableInteraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBAB83528D12ED500AC903E /* DisableInteraction.swift */; }; 0CBC76FD288D914F0054BE44 /* BatchChoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBC76FC288D914F0054BE44 /* BatchChoiceView.swift */; }; 0CBC76FF288DAAD00054BE44 /* NavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBC76FE288DAAD00054BE44 /* NavigationViewModel.swift */; }; @@ -174,7 +173,6 @@ 0C1A3E5129C8A7F500DA9730 /* SettingsModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsModels.swift; sourceTree = ""; }; 0C1A3E5529C9488C00DA9730 /* CodableWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableWrapper.swift; sourceTree = ""; }; 0C2886D12960AC2800D6FC16 /* DebridCloudView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebridCloudView.swift; sourceTree = ""; }; - 0C2886D62960C50900D6FC16 /* RealDebridCloudView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealDebridCloudView.swift; sourceTree = ""; }; 0C2B028E29E9E61E00DCF127 /* SortFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortFilterView.swift; sourceTree = ""; }; 0C2D9652299316CC00A504B6 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; 0C31133A28B1ABFA004DCB0D /* SourceJsonParser+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceJsonParser+CoreDataClass.swift"; sourceTree = ""; }; @@ -207,7 +205,6 @@ 0C54D36228C5086E00BFEEE2 /* History+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "History+CoreDataProperties.swift"; sourceTree = ""; }; 0C5708EA29B8F89300BE07F9 /* SettingsLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsLogView.swift; sourceTree = ""; }; 0C57D4CB289032ED008534E8 /* SearchResultInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultInfoView.swift; sourceTree = ""; }; - 0C5FCB04296744F300849E87 /* AllDebridCloudView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllDebridCloudView.swift; sourceTree = ""; }; 0C6771F329B3B4FD005D38D2 /* KodiWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KodiWrapper.swift; sourceTree = ""; }; 0C6771F529B3B602005D38D2 /* SettingsKodiView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKodiView.swift; sourceTree = ""; }; 0C6771F929B3D1AE005D38D2 /* KodiModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KodiModels.swift; sourceTree = ""; }; @@ -279,12 +276,13 @@ 0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndeterminateProgressView.swift; sourceTree = ""; }; 0CA429F728C5098D000D0610 /* DateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatter.swift; sourceTree = ""; }; 0CAF1C68286F5C0E00296F86 /* Ferrite.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ferrite.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CAF9318296399190050812A /* PremiumizeCloudView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PremiumizeCloudView.swift; sourceTree = ""; }; 0CB0115A29D36D9E009AFEDE /* SearchResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsView.swift; sourceTree = ""; }; 0CB0AB5E29BD2A200015422C /* KodiServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KodiServerView.swift; sourceTree = ""; }; 0CB6516228C5A57300DCA721 /* ConditionalId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalId.swift; sourceTree = ""; }; 0CB6516428C5A5D700DCA721 /* InlinedList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlinedList.swift; sourceTree = ""; }; 0CB6516928C5B4A600DCA721 /* InlineHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineHeader.swift; sourceTree = ""; }; + 0CB725312C123E6F0047FC0B /* CloudDownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudDownloadView.swift; sourceTree = ""; }; + 0CB725332C123E760047FC0B /* CloudTorrentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudTorrentView.swift; sourceTree = ""; }; 0CBAB83528D12ED500AC903E /* DisableInteraction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableInteraction.swift; sourceTree = ""; }; 0CBC76FC288D914F0054BE44 /* BatchChoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchChoiceView.swift; sourceTree = ""; }; 0CBC76FE288DAAD00054BE44 /* NavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewModel.swift; sourceTree = ""; }; @@ -413,9 +411,8 @@ 0C2886D52960C4F800D6FC16 /* Cloud */ = { isa = PBXGroup; children = ( - 0C2886D62960C50900D6FC16 /* RealDebridCloudView.swift */, - 0CAF9318296399190050812A /* PremiumizeCloudView.swift */, - 0C5FCB04296744F300849E87 /* AllDebridCloudView.swift */, + 0CB725312C123E6F0047FC0B /* CloudDownloadView.swift */, + 0CB725332C123E760047FC0B /* CloudTorrentView.swift */, ); path = Cloud; sourceTree = ""; @@ -856,7 +853,6 @@ 0C5005522992B6750064606A /* PluginTagsView.swift in Sources */, 0CB0AB5F29BD2A200015422C /* KodiServerView.swift in Sources */, 0CF2C0A529D1EBD400E716DD /* UIApplication.swift in Sources */, - 0C2886D72960C50900D6FC16 /* RealDebridCloudView.swift in Sources */, 0C3DD44229B6ACD9006429DB /* KodiServer+CoreDataClass.swift in Sources */, 0C794B6B289DACF100DD1CC8 /* PluginCatalogButtonView.swift in Sources */, 0C54D36428C5086E00BFEEE2 /* History+CoreDataProperties.swift in Sources */, @@ -875,10 +871,10 @@ 0C44E2A828D4DDDC007711AE /* Application.swift in Sources */, 0CC389542970AD900066D06F /* Action+CoreDataProperties.swift in Sources */, 0C7ED14128D61BBA009E29AD /* BackupModels.swift in Sources */, - 0CAF9319296399190050812A /* PremiumizeCloudView.swift in Sources */, 0C84FCE529E4B43200B0DFE4 /* SelectedDebridFilterView.swift in Sources */, 0CA148EC288903F000DE2211 /* ContentView.swift in Sources */, 0CC389532970AD900066D06F /* Action+CoreDataClass.swift in Sources */, + 0CB725342C123E760047FC0B /* CloudTorrentView.swift in Sources */, 0C03EB72296F619900162E9A /* PluginList+CoreDataProperties.swift in Sources */, 0C95D8D828A55B03005E22B3 /* DefaultActionPickerView.swift in Sources */, 0C44E2AF28D52E8A007711AE /* BackupsView.swift in Sources */, @@ -905,7 +901,6 @@ 0C6C7C9D29315292002DF910 /* AllDebridModels.swift in Sources */, 0C6C7C9B2931521B002DF910 /* AllDebridWrapper.swift in Sources */, 0C68135228BC1A7C00FAD890 /* GithubModels.swift in Sources */, - 0C5FCB05296744F300849E87 /* AllDebridCloudView.swift in Sources */, 0CA3B23928C2660D00616D3A /* BookmarksView.swift in Sources */, 0C79DC072899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift in Sources */, 0CA148E6288903F000DE2211 /* WebView.swift in Sources */, @@ -959,6 +954,7 @@ 0CEC8AAE299B31B6007BFE8F /* SearchFilterHeaderView.swift in Sources */, 0C84F4822895BFED0074B7C9 /* Source+CoreDataClass.swift in Sources */, 0C3DD43F29B6968D006429DB /* KodiEditorView.swift in Sources */, + 0CB725322C123E6F0047FC0B /* CloudDownloadView.swift in Sources */, 0C3DD44329B6ACD9006429DB /* KodiServer+CoreDataProperties.swift in Sources */, 0C7C128628DAA3CD00381CD1 /* URL.swift in Sources */, 0C84F4852895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift in Sources */, diff --git a/Ferrite/API/AllDebridWrapper.swift b/Ferrite/API/AllDebridWrapper.swift index 7778aa2..cc0abb2 100644 --- a/Ferrite/API/AllDebridWrapper.swift +++ b/Ferrite/API/AllDebridWrapper.swift @@ -299,7 +299,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { // MARK: - Cloud methods // Referred to as "User magnets" in AllDebrid's API - public func getUserTorrents() async throws -> [DebridCloudTorrent] { + public func getUserTorrents() async throws { var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/status")) let data = try await performRequest(request: &request, requestName: #function) @@ -319,8 +319,6 @@ public class AllDebrid: PollingDebridSource, ObservableObject { links: magnetResponse.links.map(\.link) ) } - - return cloudTorrents } public func deleteTorrent(torrentId: String?) async throws { @@ -336,7 +334,7 @@ public class AllDebrid: PollingDebridSource, ObservableObject { try await performRequest(request: &request, requestName: #function) } - public func getUserDownloads() async throws -> [DebridCloudDownload] { + public func getUserDownloads() async throws { var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/user/links")) let data = try await performRequest(request: &request, requestName: #function) @@ -352,8 +350,6 @@ public class AllDebrid: PollingDebridSource, ObservableObject { downloadId: link.link, source: self.id, fileName: link.filename, link: link.link ) } - - return cloudDownloads } // Not used diff --git a/Ferrite/API/PremiumizeWrapper.swift b/Ferrite/API/PremiumizeWrapper.swift index 468f406..0909fb3 100644 --- a/Ferrite/API/PremiumizeWrapper.swift +++ b/Ferrite/API/PremiumizeWrapper.swift @@ -303,7 +303,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { // MARK: - Cloud methods - public func getUserDownloads() async throws -> [DebridCloudDownload] { + public func getUserDownloads() async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/item/listall")!) let data = try await performRequest(request: &request, requestName: #function) @@ -317,8 +317,6 @@ public class Premiumize: OAuthDebridSource, ObservableObject { cloudDownloads = rawResponse.files.map { file in DebridCloudDownload(downloadId: file.id, source: self.id, fileName: file.name, link: file.id) } - - return cloudDownloads } func itemDetails(itemID: String) async throws -> ItemDetailsResponse { @@ -355,9 +353,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject { } // No user torrents for Premiumize - public func getUserTorrents() async throws -> [DebridCloudTorrent] { - [] - } + public func getUserTorrents() async throws {} public func deleteTorrent(torrentId: String?) async throws {} } diff --git a/Ferrite/API/RealDebridWrapper.swift b/Ferrite/API/RealDebridWrapper.swift index daf42b0..ea6aab7 100644 --- a/Ferrite/API/RealDebridWrapper.swift +++ b/Ferrite/API/RealDebridWrapper.swift @@ -434,7 +434,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { // MARK: - Cloud methods // Gets the user's torrent library - public func getUserTorrents() async throws -> [DebridCloudTorrent] { + public func getUserTorrents() async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents")!) let data = try await performRequest(request: &request, requestName: #function) @@ -449,8 +449,6 @@ public class RealDebrid: PollingDebridSource, ObservableObject { links: response.links ) } - - return cloudTorrents } // Deletes a torrent download from RD @@ -477,7 +475,7 @@ public class RealDebrid: PollingDebridSource, ObservableObject { } // Gets the user's downloads - public func getUserDownloads() async throws -> [DebridCloudDownload] { + public func getUserDownloads() async throws { var request = URLRequest(url: URL(string: "\(baseApiUrl)/downloads")!) let data = try await performRequest(request: &request, requestName: #function) @@ -485,8 +483,6 @@ public class RealDebrid: PollingDebridSource, ObservableObject { cloudDownloads = rawResponse.map { response in DebridCloudDownload(downloadId: response.id, source: self.id, fileName: response.filename, link: response.download) } - - return cloudDownloads } // Not used diff --git a/Ferrite/Protocols/Debrid.swift b/Ferrite/Protocols/Debrid.swift index 3c0570c..eef1a33 100644 --- a/Ferrite/Protocols/Debrid.swift +++ b/Ferrite/Protocols/Debrid.swift @@ -39,12 +39,12 @@ public protocol DebridSource: AnyObservableObject { var cloudTTL: Double { get set } // User downloads functions - func getUserDownloads() async throws -> [DebridCloudDownload] + func getUserDownloads() async throws func checkUserDownloads(link: String) async throws -> String? func deleteDownload(downloadId: String) async throws // User torrent functions - func getUserTorrents() async throws -> [DebridCloudTorrent] + func getUserTorrents() async throws func deleteTorrent(torrentId: String?) async throws } diff --git a/Ferrite/ViewModels/DebridManager.swift b/Ferrite/ViewModels/DebridManager.swift index c1adfec..ede4ffd 100644 --- a/Ferrite/ViewModels/DebridManager.swift +++ b/Ferrite/ViewModels/DebridManager.swift @@ -74,27 +74,12 @@ public class DebridManager: ObservableObject { @Published var showDeleteAlert: Bool = false - // TODO: Maybe make these generic? - // RealDebrid cloud variables - @Published var realDebridCloudTorrents: [DebridCloudTorrent] = [] - @Published var realDebridCloudDownloads: [DebridCloudDownload] = [] - var realDebridCloudTTL: Double = 0.0 - // AllDebrid auth variables var allDebridAuthProcessing: Bool = false - // AllDebrid cloud variables - @Published var allDebridCloudMagnets: [DebridCloudTorrent] = [] - @Published var allDebridCloudLinks: [DebridCloudDownload] = [] - var allDebridCloudTTL: Double = 0.0 - // Premiumize auth variables var premiumizeAuthProcessing: Bool = false - // Premiumize cloud variables - @Published var premiumizeCloudItems: [DebridCloudDownload] = [] - var premiumizeCloudTTL: Double = 0.0 - init() { // Set the preferred service. Contains migration logic for earlier versions @@ -422,12 +407,11 @@ public class DebridManager: ObservableObject { // Update the UI downloadUrl = downloadLink } else { - throw DebridError.FailedRequest(description: "Could not fetch your file from RealDebrid's cache or API") + throw DebridError.FailedRequest(description: "Could not fetch your file from \(debridSource.id)'s cache or API") } // Fetch one more time to add updated data into the RD cloud cache - // TODO: Add common fetch cloud method - //await fetchRdCloud(bypassTTL: true) + await fetchDebridCloud(bypassTTL: true) } catch { switch error { case DebridError.IsCaching: @@ -440,122 +424,55 @@ public class DebridManager: ObservableObject { } } + // Wrapper to handle cloud fetching public func fetchDebridCloud(bypassTTL: Bool = false) async { - switch selectedDebridType { - case .realDebrid: - await fetchRdCloud(bypassTTL: bypassTTL) - case .allDebrid: - await fetchAdCloud(bypassTTL: bypassTTL) - case .premiumize: - await fetchPmCloud(bypassTTL: bypassTTL) - case .none: + guard let selectedSource = selectedDebridSource else { return } - } - // Refreshes torrents and downloads from a RD user's account - public func fetchRdCloud(bypassTTL: Bool = false) async { - if bypassTTL || Date().timeIntervalSince1970 > realDebridCloudTTL { + if bypassTTL || Date().timeIntervalSince1970 > selectedSource.cloudTTL { do { - realDebridCloudTorrents = try await realDebrid.getUserTorrents() - realDebridCloudDownloads = try await realDebrid.getUserDownloads() + // Populates the inner downloads and torrent arrays + try await selectedSource.getUserDownloads() + try await selectedSource.getUserTorrents() - // 5 minutes - realDebridCloudTTL = Date().timeIntervalSince1970 + 300 - } catch { - await sendDebridError(error, prefix: "RealDebrid cloud fetch error") - } - } - } - - func deleteRdDownload(downloadID: String) async { - do { - try await realDebrid.deleteDownload(downloadId: downloadID) - - // Bypass TTL to get current RD values - await fetchRdCloud(bypassTTL: true) - } catch { - await sendDebridError(error, prefix: "RealDebrid download delete error") - } - } - - func deleteRdTorrent(torrentID: String? = nil, presentError: Bool = true) async { - do { - if let torrentID { - try await realDebrid.deleteTorrent(torrentId: torrentID) - - await fetchRdCloud(bypassTTL: true) - } else { - throw DebridError.FailedRequest(description: "No torrent ID was provided") - } - } catch { - await sendDebridError(error, prefix: "RealDebrid torrent delete error", presentError: presentError) - } - } - - // Refreshes torrents and downloads from a RD user's account - public func fetchAdCloud(bypassTTL: Bool = false) async { - if bypassTTL || Date().timeIntervalSince1970 > allDebridCloudTTL { - do { - allDebridCloudMagnets = try await allDebrid.getUserTorrents() - allDebridCloudLinks = try await allDebrid.getUserDownloads() - - // 5 minutes - allDebridCloudTTL = Date().timeIntervalSince1970 + 300 - } catch { - await sendDebridError(error, prefix: "AlLDebrid cloud fetch error") - } - } - } - - func deleteAdLink(link: String) async { - do { - try await allDebrid.deleteDownload(downloadId: link) - - await fetchAdCloud(bypassTTL: true) - } catch { - await sendDebridError(error, prefix: "AllDebrid link delete error") - } - } - - func deleteAdMagnet(magnetId: String) async { - do { - try await allDebrid.deleteTorrent(torrentId: magnetId) - - await fetchAdCloud(bypassTTL: true) - } catch { - await sendDebridError(error, prefix: "AllDebrid magnet delete error") - } - } - - // Refreshes items and fetches from a PM user account - public func fetchPmCloud(bypassTTL: Bool = false) async { - if bypassTTL || Date().timeIntervalSince1970 > premiumizeCloudTTL { - do { - let userItems = try await premiumize.getUserDownloads() - withAnimation { - premiumizeCloudItems = userItems - } - - // 5 minutes - premiumizeCloudTTL = Date().timeIntervalSince1970 + 300 + // Update the TTL to 5 minutes from now + selectedSource.cloudTTL = Date().timeIntervalSince1970 + 300 } catch { let error = error as NSError if error.code != -999 { - await sendDebridError(error, prefix: "Premiumize cloud fetch error") + await sendDebridError(error, prefix: "\(selectedSource.id) cloud fetch error") } + } } } - public func deletePmItem(id: String) async { - do { - try await premiumize.deleteDownload(downloadId: id) + public func deleteCloudDownload(_ download: DebridCloudDownload) async { + guard let selectedSource = selectedDebridSource else { + return + } - // Bypass TTL to get current RD values - await fetchPmCloud(bypassTTL: true) + do { + try await selectedSource.deleteDownload(downloadId: download.downloadId) + + await fetchDebridCloud(bypassTTL: true) } catch { - await sendDebridError(error, prefix: "Premiumize cloud delete error") + await sendDebridError(error, prefix: "\(selectedSource.id) download delete error") + } + } + + public func deleteCloudTorrent(_ torrent: DebridCloudTorrent) async { + guard let selectedSource = selectedDebridSource else { + return + } + + do { + try await selectedSource.deleteTorrent(torrentId: torrent.torrentId) + + await fetchDebridCloud(bypassTTL: true) + } catch { + await sendDebridError(error, prefix: "\(selectedSource.id) torrent delete error") } } } diff --git a/Ferrite/Views/ComponentViews/Library/Cloud/CloudDownloadView.swift b/Ferrite/Views/ComponentViews/Library/Cloud/CloudDownloadView.swift new file mode 100644 index 0000000..9f2b488 --- /dev/null +++ b/Ferrite/Views/ComponentViews/Library/Cloud/CloudDownloadView.swift @@ -0,0 +1,57 @@ +// +// CloudDownloadView.swift +// Ferrite +// +// Created by Brian Dashore on 6/6/24. +// + +import SwiftUI + +struct CloudDownloadView: View { + @EnvironmentObject var navModel: NavigationViewModel + @EnvironmentObject var debridManager: DebridManager + @EnvironmentObject var pluginManager: PluginManager + + @Store var debridSource: DebridSource + + @Binding var searchText: String + + var body: some View { + DisclosureGroup("Downloads") { + ForEach(debridSource.cloudDownloads.filter { + searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased()) + }, id: \.self) { cloudDownload in + Button(cloudDownload.fileName) { + navModel.resultFromCloud = true + navModel.selectedTitle = cloudDownload.fileName + debridManager.downloadUrl = cloudDownload.link + + PersistenceController.shared.createHistory( + HistoryEntryJson( + name: cloudDownload.fileName, + url: cloudDownload.link, + source: debridSource.id + ), + performSave: true + ) + + pluginManager.runDefaultAction( + urlString: debridManager.downloadUrl, + navModel: navModel + ) + } + .disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.7, animation: .easeOut(duration: 0.2)) + .tint(.primary) + } + .onDelete { offsets in + for index in offsets { + if let cloudDownload = debridSource.cloudDownloads[safe: index] { + Task { + await debridManager.deleteCloudDownload(cloudDownload) + } + } + } + } + } + } +} diff --git a/Ferrite/Views/ComponentViews/Library/Cloud/AllDebridCloudView.swift b/Ferrite/Views/ComponentViews/Library/Cloud/CloudTorrentView.swift similarity index 57% rename from Ferrite/Views/ComponentViews/Library/Cloud/AllDebridCloudView.swift rename to Ferrite/Views/ComponentViews/Library/Cloud/CloudTorrentView.swift index ee72b05..0c86880 100644 --- a/Ferrite/Views/ComponentViews/Library/Cloud/AllDebridCloudView.swift +++ b/Ferrite/Views/ComponentViews/Library/Cloud/CloudTorrentView.swift @@ -1,71 +1,36 @@ // -// AllDebridCloudView.swift +// CloudTorrentView.swift // Ferrite // -// Created by Brian Dashore on 1/5/23. +// Created by Brian Dashore on 6/6/24. // import SwiftUI -struct AllDebridCloudView: View { - @EnvironmentObject var debridManager: DebridManager +struct CloudTorrentView: View { @EnvironmentObject var navModel: NavigationViewModel + @EnvironmentObject var debridManager: DebridManager @EnvironmentObject var pluginManager: PluginManager + @Store var debridSource: DebridSource + @Binding var searchText: String var body: some View { - DisclosureGroup("Links") { - ForEach(debridManager.allDebridCloudLinks.filter { - searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased()) - }, id: \.self) { cloudDownload in - Button(cloudDownload.fileName) { - navModel.resultFromCloud = true - navModel.selectedTitle = cloudDownload.fileName - debridManager.downloadUrl = cloudDownload.link - - PersistenceController.shared.createHistory( - HistoryEntryJson( - name: cloudDownload.fileName, - url: cloudDownload.link, - source: DebridType.allDebrid.toString() - ), - performSave: true - ) - - pluginManager.runDefaultAction( - urlString: debridManager.downloadUrl, - navModel: navModel - ) - } - .disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.7, animation: .easeOut(duration: 0.2)) - .tint(.primary) - } - .onDelete { offsets in - for index in offsets { - if let cloudDownload = debridManager.allDebridCloudLinks[safe: index] { - Task { - await debridManager.deleteAdLink(link: cloudDownload.downloadId) - } - } - } - } - } - - DisclosureGroup("Magnets") { - ForEach(debridManager.allDebridCloudMagnets.filter { + DisclosureGroup("Torrents") { + ForEach(debridSource.cloudTorrents.filter { searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased()) }, id: \.self) { cloudTorrent in Button { - if cloudTorrent.status == "Ready", !cloudTorrent.links.isEmpty { + if cloudTorrent.status == "downloaded", !cloudTorrent.links.isEmpty { navModel.resultFromCloud = true navModel.selectedTitle = cloudTorrent.fileName - + var historyInfo = HistoryEntryJson( name: cloudTorrent.fileName, - source: DebridType.allDebrid.toString() + source: debridSource.id ) - + Task { let magnet = Magnet(hash: cloudTorrent.hash, link: nil) await debridManager.populateDebridIA([magnet]) @@ -74,11 +39,11 @@ struct AllDebridCloudView: View { if cloudTorrent.links.count == 1 { await debridManager.fetchDebridDownload(magnet: magnet) - + if !debridManager.downloadUrl.isEmpty { historyInfo.url = debridManager.downloadUrl PersistenceController.shared.createHistory(historyInfo, performSave: true) - + pluginManager.runDefaultAction( urlString: debridManager.downloadUrl, navModel: navModel @@ -98,11 +63,11 @@ struct AllDebridCloudView: View { .font(.callout) .fixedSize(horizontal: false, vertical: true) .lineLimit(4) - + HStack { Text(cloudTorrent.status.capitalizingFirstLetter()) Spacer() - //DebridLabelView(cloudLinks: cloudTorrent.links) + DebridLabelView(debridSource: debridSource, cloudLinks: cloudTorrent.links) } .font(.caption) } @@ -112,9 +77,9 @@ struct AllDebridCloudView: View { } .onDelete { offsets in for index in offsets { - if let cloudTorrent = debridManager.allDebridCloudMagnets[safe: index] { + if let cloudTorrent = debridSource.cloudTorrents[safe: index] { Task { - await debridManager.deleteAdMagnet(magnetId: cloudTorrent.torrentId) + await debridManager.deleteCloudTorrent(cloudTorrent) } } } diff --git a/Ferrite/Views/ComponentViews/Library/Cloud/PremiumizeCloudView.swift b/Ferrite/Views/ComponentViews/Library/Cloud/PremiumizeCloudView.swift deleted file mode 100644 index e9acb9a..0000000 --- a/Ferrite/Views/ComponentViews/Library/Cloud/PremiumizeCloudView.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// PremiumizeCloudView.swift -// Ferrite -// -// Created by Brian Dashore on 1/2/23. -// - -import SwiftUI - -struct PremiumizeCloudView: View { - @EnvironmentObject var debridManager: DebridManager - @EnvironmentObject var navModel: NavigationViewModel - @EnvironmentObject var pluginManager: PluginManager - - @Binding var searchText: String - - var body: some View { - DisclosureGroup("Items") { - ForEach(debridManager.premiumizeCloudItems.filter { - searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased()) - }, id: \.self) { cloudDownload in - Button(cloudDownload.fileName) { - Task { - navModel.resultFromCloud = true - navModel.selectedTitle = cloudDownload.fileName - - await debridManager.fetchDebridDownload(magnet: nil, cloudInfo: cloudDownload.downloadId) - - if !debridManager.downloadUrl.isEmpty { - PersistenceController.shared.createHistory( - HistoryEntryJson( - name: cloudDownload.fileName, - url: cloudDownload.link, - source: DebridType.premiumize.toString() - ), - performSave: true - ) - - pluginManager.runDefaultAction( - urlString: debridManager.downloadUrl, - navModel: navModel - ) - } - } - } - .disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.7, animation: .easeOut(duration: 0.2)) - .tint(.primary) - } - .onDelete { offsets in - for index in offsets { - if let cloudDownload = debridManager.premiumizeCloudItems[safe: index] { - Task { - await debridManager.deletePmItem(id: cloudDownload.downloadId) - } - } - } - } - } - } -} diff --git a/Ferrite/Views/ComponentViews/Library/Cloud/RealDebridCloudView.swift b/Ferrite/Views/ComponentViews/Library/Cloud/RealDebridCloudView.swift deleted file mode 100644 index b05e764..0000000 --- a/Ferrite/Views/ComponentViews/Library/Cloud/RealDebridCloudView.swift +++ /dev/null @@ -1,126 +0,0 @@ -// -// RealDebridCloudView.swift -// Ferrite -// -// Created by Brian Dashore on 12/31/22. -// - -import SwiftUI - -struct RealDebridCloudView: View { - @EnvironmentObject var navModel: NavigationViewModel - @EnvironmentObject var debridManager: DebridManager - @EnvironmentObject var pluginManager: PluginManager - - @Binding var searchText: String - - var body: some View { - Group { - DisclosureGroup("Downloads") { - ForEach(debridManager.realDebrid.cloudDownloads.filter { - searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased()) - }, id: \.self) { cloudDownload in - Button(cloudDownload.fileName) { - navModel.resultFromCloud = true - navModel.selectedTitle = cloudDownload.fileName - debridManager.downloadUrl = cloudDownload.link - - PersistenceController.shared.createHistory( - HistoryEntryJson( - name: cloudDownload.fileName, - url: cloudDownload.link, - source: DebridType.realDebrid.toString() - ), - performSave: true - ) - - pluginManager.runDefaultAction( - urlString: debridManager.downloadUrl, - navModel: navModel - ) - } - .disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.7, animation: .easeOut(duration: 0.2)) - .tint(.primary) - } - .onDelete { offsets in - for index in offsets { - if let cloudDownload = debridManager.realDebridCloudDownloads[safe: index] { - Task { - await debridManager.deleteRdDownload(downloadID: cloudDownload.downloadId) - } - } - } - } - } - - DisclosureGroup("Torrents") { - ForEach(debridManager.realDebrid.cloudTorrents.filter { - searchText.isEmpty ? true : $0.fileName.lowercased().contains(searchText.lowercased()) - }, id: \.self) { cloudTorrent in - Button { - if cloudTorrent.status == "downloaded", !cloudTorrent.links.isEmpty { - navModel.resultFromCloud = true - navModel.selectedTitle = cloudTorrent.fileName - - var historyInfo = HistoryEntryJson( - name: cloudTorrent.fileName, - source: DebridType.realDebrid.toString() - ) - - Task { - let magnet = Magnet(hash: cloudTorrent.hash, link: nil) - await debridManager.populateDebridIA([magnet]) - if debridManager.selectDebridResult(magnet: magnet) { - // Is this a batch? - - if cloudTorrent.links.count == 1 { - await debridManager.fetchDebridDownload(magnet: magnet) - - if !debridManager.downloadUrl.isEmpty { - historyInfo.url = debridManager.downloadUrl - PersistenceController.shared.createHistory(historyInfo, performSave: true) - - pluginManager.runDefaultAction( - urlString: debridManager.downloadUrl, - navModel: navModel - ) - } - } else { - navModel.selectedMagnet = magnet - navModel.selectedHistoryInfo = historyInfo - navModel.currentChoiceSheet = .batch - } - } - } - } - } label: { - VStack(alignment: .leading, spacing: 10) { - Text(cloudTorrent.fileName) - .font(.callout) - .fixedSize(horizontal: false, vertical: true) - .lineLimit(4) - - HStack { - Text(cloudTorrent.status.capitalizingFirstLetter()) - Spacer() - //DebridLabelView(cloudLinks: cloudTorrent.links) - } - .font(.caption) - } - } - .disabledAppearance(navModel.currentChoiceSheet != nil, dimmedOpacity: 0.7, animation: .easeOut(duration: 0.2)) - .tint(.primary) - } - .onDelete { offsets in - for index in offsets { - if let cloudTorrent = debridManager.realDebridCloudTorrents[safe: index] { - Task { - await debridManager.deleteRdTorrent(torrentID: cloudTorrent.torrentId) - } - } - } - } - } - } - } -} diff --git a/Ferrite/Views/ComponentViews/Library/DebridCloudView.swift b/Ferrite/Views/ComponentViews/Library/DebridCloudView.swift index b9e271f..a52120a 100644 --- a/Ferrite/Views/ComponentViews/Library/DebridCloudView.swift +++ b/Ferrite/Views/ComponentViews/Library/DebridCloudView.swift @@ -10,19 +10,18 @@ import SwiftUI struct DebridCloudView: View { @EnvironmentObject var debridManager: DebridManager + @Store var debridSource: DebridSource + @Binding var searchText: String var body: some View { List { - switch debridManager.selectedDebridType { - case .realDebrid: - RealDebridCloudView(searchText: $searchText) - case .premiumize: - PremiumizeCloudView(searchText: $searchText) - case .allDebrid: - AllDebridCloudView(searchText: $searchText) - case .none: - EmptyView() + if !debridSource.cloudDownloads.isEmpty { + CloudDownloadView(debridSource: debridSource, searchText: $searchText) + } + + if !debridSource.cloudTorrents.isEmpty { + CloudTorrentView(debridSource: debridSource, searchText: $searchText) } } .listStyle(.plain) diff --git a/Ferrite/Views/LibraryView.swift b/Ferrite/Views/LibraryView.swift index ac1260f..347bc04 100644 --- a/Ferrite/Views/LibraryView.swift +++ b/Ferrite/Views/LibraryView.swift @@ -38,7 +38,13 @@ struct LibraryView: View { case .history: HistoryView(allHistoryEntries: allHistoryEntries, searchText: $searchText) case .debridCloud: - DebridCloudView(searchText: $searchText) + if let selectedDebridSource = debridManager.selectedDebridSource { + DebridCloudView(debridSource: selectedDebridSource, searchText: $searchText) + } else { + // Placeholder view that takes up the entire parent view + Color.clear + .frame(maxWidth: .infinity) + } } } .overlay {