Debrid: Refactor IA and download functions
Use the common protocol to handle these. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
4e6cfee608
commit
13988b3c6c
6 changed files with 126 additions and 189 deletions
|
|
@ -19,9 +19,10 @@ public class AllDebrid: PollingDebridSource, ObservableObject {
|
||||||
getToken() != nil
|
getToken() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public var IAValues: [DebridIA] = []
|
@Published public var IAValues: [DebridIA] = []
|
||||||
public var cloudDownloads: [DebridCloudDownload] = []
|
@Published public var cloudDownloads: [DebridCloudDownload] = []
|
||||||
public var cloudTorrents: [DebridCloudTorrent] = []
|
@Published public var cloudTorrents: [DebridCloudTorrent] = []
|
||||||
|
public var cloudTTL: Double = 0.0
|
||||||
|
|
||||||
let baseApiUrl = "https://api.alldebrid.com/v4"
|
let baseApiUrl = "https://api.alldebrid.com/v4"
|
||||||
let appName = "Ferrite"
|
let appName = "Ferrite"
|
||||||
|
|
@ -163,7 +164,26 @@ public class AllDebrid: PollingDebridSource, ObservableObject {
|
||||||
// MARK: - Instant availability
|
// MARK: - Instant availability
|
||||||
|
|
||||||
public func instantAvailability(magnets: [Magnet]) async throws {
|
public func instantAvailability(magnets: [Magnet]) async throws {
|
||||||
let queryItems = magnets.map { URLQueryItem(name: "magnets[]", value: $0.hash) }
|
let now = Date().timeIntervalSince1970
|
||||||
|
|
||||||
|
let sendMagnets = magnets.filter { magnet in
|
||||||
|
if let IAIndex = IAValues.firstIndex(where: { $0.magnet.hash == magnet.hash }) {
|
||||||
|
if now > IAValues[IAIndex].expiryTimeStamp {
|
||||||
|
IAValues.remove(at: IAIndex)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sendMagnets.isEmpty {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let queryItems = sendMagnets.map { URLQueryItem(name: "magnets[]", value: $0.hash) }
|
||||||
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/instant", queryItems: queryItems))
|
var request = URLRequest(url: try buildRequestURL(urlString: "\(baseApiUrl)/magnet/instant", queryItems: queryItems))
|
||||||
|
|
||||||
let data = try await performRequest(request: &request, requestName: #function)
|
let data = try await performRequest(request: &request, requestName: #function)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ public class Premiumize: OAuthDebridSource, ObservableObject {
|
||||||
@Published public var IAValues: [DebridIA] = []
|
@Published public var IAValues: [DebridIA] = []
|
||||||
@Published public var cloudDownloads: [DebridCloudDownload] = []
|
@Published public var cloudDownloads: [DebridCloudDownload] = []
|
||||||
@Published public var cloudTorrents: [DebridCloudTorrent] = []
|
@Published public var cloudTorrents: [DebridCloudTorrent] = []
|
||||||
|
public var cloudTTL: Double = 0.0
|
||||||
|
|
||||||
let baseAuthUrl = "https://www.premiumize.me/authorize"
|
let baseAuthUrl = "https://www.premiumize.me/authorize"
|
||||||
let baseApiUrl = "https://www.premiumize.me/api"
|
let baseApiUrl = "https://www.premiumize.me/api"
|
||||||
|
|
@ -127,16 +128,31 @@ public class Premiumize: OAuthDebridSource, ObservableObject {
|
||||||
// MARK: - Instant availability
|
// MARK: - Instant availability
|
||||||
|
|
||||||
public func instantAvailability(magnets: [Magnet]) async throws {
|
public func instantAvailability(magnets: [Magnet]) async throws {
|
||||||
// Only strip magnets that don't have an associated link for PM
|
let now = Date().timeIntervalSince1970
|
||||||
let strippedMagnets: [Magnet] = magnets.compactMap {
|
|
||||||
if let magnetLink = $0.link {
|
// Remove magnets that don't have an associated link for PM along with existing TTL logic
|
||||||
return Magnet(hash: $0.hash, link: magnetLink)
|
let sendMagnets = magnets.filter { magnet in
|
||||||
|
if magnet.link == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if let IAIndex = IAValues.firstIndex(where: { $0.magnet.hash == magnet.hash }) {
|
||||||
|
if now > IAValues[IAIndex].expiryTimeStamp {
|
||||||
|
IAValues.remove(at: IAIndex)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let availableMagnets = try await divideCacheRequests(magnets: strippedMagnets)
|
if sendMagnets.isEmpty {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let availableMagnets = try await divideCacheRequests(magnets: sendMagnets)
|
||||||
|
|
||||||
// Split DDL requests into chunks of 10
|
// Split DDL requests into chunks of 10
|
||||||
for chunk in availableMagnets.chunked(into: 10) {
|
for chunk in availableMagnets.chunked(into: 10) {
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,10 @@ public class RealDebrid: PollingDebridSource, ObservableObject {
|
||||||
FerriteKeychain.shared.get("RealDebrid.AccessToken") != nil
|
FerriteKeychain.shared.get("RealDebrid.AccessToken") != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published public var IAValues: [DebridIA] = [] {
|
@Published public var IAValues: [DebridIA] = []
|
||||||
willSet {
|
|
||||||
self.objectWillChange.send()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Published public var cloudDownloads: [DebridCloudDownload] = []
|
@Published public var cloudDownloads: [DebridCloudDownload] = []
|
||||||
@Published public var cloudTorrents: [DebridCloudTorrent] = []
|
@Published public var cloudTorrents: [DebridCloudTorrent] = []
|
||||||
var cloudTTL: Double = 0.0
|
public var cloudTTL: Double = 0.0
|
||||||
|
|
||||||
let baseAuthUrl = "https://api.real-debrid.com/oauth/v2"
|
let baseAuthUrl = "https://api.real-debrid.com/oauth/v2"
|
||||||
let baseApiUrl = "https://api.real-debrid.com/rest/1.0"
|
let baseApiUrl = "https://api.real-debrid.com/rest/1.0"
|
||||||
|
|
@ -237,7 +233,26 @@ public class RealDebrid: PollingDebridSource, ObservableObject {
|
||||||
|
|
||||||
// Checks if the magnet is streamable on RD
|
// Checks if the magnet is streamable on RD
|
||||||
public func instantAvailability(magnets: [Magnet]) async throws {
|
public func instantAvailability(magnets: [Magnet]) async throws {
|
||||||
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/instantAvailability/\(magnets.compactMap(\.hash).joined(separator: "/"))")!)
|
let now = Date().timeIntervalSince1970
|
||||||
|
|
||||||
|
let sendMagnets = magnets.filter { magnet in
|
||||||
|
if let IAIndex = IAValues.firstIndex(where: { $0.magnet.hash == magnet.hash }) {
|
||||||
|
if now > IAValues[IAIndex].expiryTimeStamp {
|
||||||
|
IAValues.remove(at: IAIndex)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sendMagnets.isEmpty {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/instantAvailability/\(sendMagnets.compactMap(\.hash).joined(separator: "/"))")!)
|
||||||
|
|
||||||
let data = try await performRequest(request: &request, requestName: #function)
|
let data = try await performRequest(request: &request, requestName: #function)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public protocol DebridSource: AnyObservableObject {
|
||||||
// Cloud variables
|
// Cloud variables
|
||||||
var cloudDownloads: [DebridCloudDownload] { get set }
|
var cloudDownloads: [DebridCloudDownload] { get set }
|
||||||
var cloudTorrents: [DebridCloudTorrent] { get set }
|
var cloudTorrents: [DebridCloudTorrent] { get set }
|
||||||
|
var cloudTTL: Double { get set }
|
||||||
|
|
||||||
// User downloads functions
|
// User downloads functions
|
||||||
func getUserDownloads() async throws -> [DebridCloudDownload]
|
func getUserDownloads() async throws -> [DebridCloudDownload]
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,8 @@ public class DebridManager: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published var selectedDebridSource: DebridSource?
|
@Published var selectedDebridSource: DebridSource?
|
||||||
|
var selectedDebridItem: DebridIA?
|
||||||
/*
|
var selectedDebridFile: DebridIAFile?
|
||||||
func debridSourceFromName(_ name: String? = nil) -> DebridSource? {
|
|
||||||
debridSources.first { $0.id.name == name ?? selectedDebridId?.name }
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Service agnostic variables
|
// Service agnostic variables
|
||||||
@Published var enabledDebrids: Set<DebridType> = [] {
|
@Published var enabledDebrids: Set<DebridType> = [] {
|
||||||
|
|
@ -184,78 +180,22 @@ public class DebridManager: ObservableObject {
|
||||||
|
|
||||||
// Clears all selected files and items
|
// Clears all selected files and items
|
||||||
public func clearSelectedDebridItems() {
|
public func clearSelectedDebridItems() {
|
||||||
switch selectedDebridType {
|
selectedDebridItem = nil
|
||||||
case .realDebrid:
|
selectedDebridFile = nil
|
||||||
selectedRealDebridFile = nil
|
|
||||||
selectedRealDebridItem = nil
|
|
||||||
case .allDebrid:
|
|
||||||
selectedAllDebridFile = nil
|
|
||||||
selectedAllDebridItem = nil
|
|
||||||
case .premiumize:
|
|
||||||
selectedPremiumizeFile = nil
|
|
||||||
selectedPremiumizeItem = nil
|
|
||||||
case .none:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common function to populate hashes for debrid services
|
// Common function to populate hashes for debrid services
|
||||||
public func populateDebridIA(_ resultMagnets: [Magnet]) async {
|
public func populateDebridIA(_ resultMagnets: [Magnet]) async {
|
||||||
let now = Date()
|
for debridSource in debridSources {
|
||||||
|
if !debridSource.isLoggedIn {
|
||||||
// If a hash isn't found in the IA, update it
|
continue
|
||||||
// If the hash is expired, remove it and update it
|
|
||||||
let sendMagnets = resultMagnets.filter { magnet in
|
|
||||||
if let IAIndex = realDebrid.IAValues.firstIndex(where: { $0.magnet.hash == magnet.hash }), enabledDebrids.contains(.realDebrid) {
|
|
||||||
if now.timeIntervalSince1970 > realDebrid.IAValues[IAIndex].expiryTimeStamp {
|
|
||||||
realDebrid.IAValues.remove(at: IAIndex)
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else if let IAIndex = allDebrid.IAValues.firstIndex(where: { $0.magnet.hash == magnet.hash }), enabledDebrids.contains(.allDebrid) {
|
|
||||||
if now.timeIntervalSince1970 > allDebrid.IAValues[IAIndex].expiryTimeStamp {
|
|
||||||
allDebrid.IAValues.remove(at: IAIndex)
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else if let IAIndex = premiumize.IAValues.firstIndex(where: { $0.magnet.hash == magnet.hash }), enabledDebrids.contains(.premiumize) {
|
|
||||||
if now.timeIntervalSince1970 > premiumize.IAValues[IAIndex].expiryTimeStamp {
|
|
||||||
premiumize.IAValues.remove(at: IAIndex)
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't exit the function if the API fetch errors
|
|
||||||
if !sendMagnets.isEmpty {
|
|
||||||
if enabledDebrids.contains(.realDebrid) {
|
|
||||||
do {
|
|
||||||
try await realDebrid.instantAvailability(magnets: sendMagnets)
|
|
||||||
} catch {
|
|
||||||
await sendDebridError(error, prefix: "RealDebrid IA fetch error")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if enabledDebrids.contains(.allDebrid) {
|
// Don't exit the function if the API fetch errors
|
||||||
do {
|
do {
|
||||||
try await allDebrid.instantAvailability(magnets: sendMagnets)
|
try await debridSource.instantAvailability(magnets: resultMagnets)
|
||||||
} catch {
|
} catch {
|
||||||
await sendDebridError(error, prefix: "AllDebrid IA fetch error")
|
await sendDebridError(error, prefix: "\(debridSource.id) IA fetch error")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if enabledDebrids.contains(.premiumize) {
|
|
||||||
do {
|
|
||||||
try await premiumize.instantAvailability(magnets: sendMagnets)
|
|
||||||
} catch {
|
|
||||||
await sendDebridError(error, prefix: "Premiumize IA fetch error")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -281,32 +221,15 @@ public class DebridManager: ObservableObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch selectedDebridSource?.id {
|
guard let selectedSource = selectedDebridSource else {
|
||||||
case .some("RealDebrid"):
|
return false
|
||||||
if let realDebridItem = realDebrid.IAValues.first(where: { magnetHash == $0.magnet.hash }) {
|
}
|
||||||
selectedRealDebridItem = realDebridItem
|
|
||||||
return true
|
if let IAItem = selectedSource.IAValues.first(where: { magnetHash == $0.magnet.hash }) {
|
||||||
} else {
|
selectedDebridItem = IAItem
|
||||||
logManager?.error("DebridManager: Could not find the associated RealDebrid entry for magnet hash \(magnetHash)")
|
return true
|
||||||
return false
|
} else {
|
||||||
}
|
logManager?.error("DebridManager: Could not find the associated \(selectedSource.id) entry for magnet hash \(magnetHash)")
|
||||||
case .some("AllDebrid"):
|
|
||||||
if let allDebridItem = allDebrid.IAValues.first(where: { magnetHash == $0.magnet.hash }) {
|
|
||||||
selectedAllDebridItem = allDebridItem
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
logManager?.error("DebridManager: Could not find the associated AllDebrid entry for magnet hash \(magnetHash)")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case .some("Premiumize"):
|
|
||||||
if let premiumizeItem = premiumize.IAValues.first(where: { magnetHash == $0.magnet.hash }) {
|
|
||||||
selectedPremiumizeItem = premiumizeItem
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
logManager?.error("DebridManager: Could not find the associated Premiumize entry for magnet hash \(magnetHash)")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -535,23 +458,19 @@ public class DebridManager: ObservableObject {
|
||||||
self.currentDebridTask = nil
|
self.currentDebridTask = nil
|
||||||
})
|
})
|
||||||
|
|
||||||
switch selectedDebridType {
|
guard let debridSource = selectedDebridSource else {
|
||||||
case .realDebrid:
|
return
|
||||||
await fetchRdDownload(magnet: magnet, cloudInfo: cloudInfo)
|
|
||||||
case .allDebrid:
|
|
||||||
await fetchAdDownload(magnet: magnet, cloudInfo: cloudInfo)
|
|
||||||
case .premiumize:
|
|
||||||
await fetchPmDownload(magnet: magnet, cloudInfo: cloudInfo)
|
|
||||||
case .none:
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func fetchRdDownload(magnet: Magnet?, cloudInfo: String?) async {
|
|
||||||
do {
|
do {
|
||||||
|
if let cloudInfo {
|
||||||
|
downloadUrl = try await debridSource.checkUserDownloads(link: cloudInfo) ?? ""
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if let magnet {
|
if let magnet {
|
||||||
let downloadLink = try await realDebrid.getDownloadLink(
|
let downloadLink = try await debridSource.getDownloadLink(
|
||||||
magnet: magnet, ia: selectedRealDebridItem, iaFile: selectedRealDebridFile
|
magnet: magnet, ia: selectedDebridItem, iaFile: selectedDebridFile
|
||||||
)
|
)
|
||||||
|
|
||||||
// Update the UI
|
// Update the UI
|
||||||
|
|
@ -560,6 +479,28 @@ public class DebridManager: ObservableObject {
|
||||||
throw RealDebrid.RDError.FailedRequest(description: "Could not fetch your file from RealDebrid's cache or API")
|
throw RealDebrid.RDError.FailedRequest(description: "Could not fetch your file from RealDebrid'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)
|
||||||
|
} catch {
|
||||||
|
// TODO: Fix error types and unify errors
|
||||||
|
print("Error \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchRdDownload(magnet: Magnet?, cloudInfo: String?) async {
|
||||||
|
do {
|
||||||
|
guard let magnet else {
|
||||||
|
throw RealDebrid.RDError.FailedRequest(description: "Could not fetch your file from RealDebrid's cache or API")
|
||||||
|
}
|
||||||
|
|
||||||
|
let downloadLink = try await realDebrid.getDownloadLink(
|
||||||
|
magnet: magnet, ia: selectedRealDebridItem, iaFile: selectedRealDebridFile
|
||||||
|
)
|
||||||
|
|
||||||
|
// Update the UI
|
||||||
|
downloadUrl = downloadLink
|
||||||
|
|
||||||
// Fetch one more time to add updated data into the RD cloud cache
|
// Fetch one more time to add updated data into the RD cloud cache
|
||||||
await fetchRdCloud(bypassTTL: true)
|
await fetchRdCloud(bypassTTL: true)
|
||||||
} catch {
|
} catch {
|
||||||
|
|
@ -631,21 +572,6 @@ public class DebridManager: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkRdUserDownloads(userTorrentLink: String) async -> String? {
|
|
||||||
do {
|
|
||||||
let existingLinks = realDebridCloudDownloads.first { $0.link == userTorrentLink }
|
|
||||||
if let existingLink = existingLinks?.fileName {
|
|
||||||
return existingLink
|
|
||||||
} else {
|
|
||||||
return try await realDebrid.unrestrictLink(debridDownloadLink: userTorrentLink)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
await sendDebridError(error, prefix: "RealDebrid download check error")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchAdDownload(magnet: Magnet?, cloudInfo: String?) async {
|
func fetchAdDownload(magnet: Magnet?, cloudInfo: String?) async {
|
||||||
do {
|
do {
|
||||||
if let magnet {
|
if let magnet {
|
||||||
|
|
@ -666,22 +592,6 @@ public class DebridManager: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkAdUserLinks(lockedLink: String) async -> String? {
|
|
||||||
do {
|
|
||||||
let existingLinks = allDebridCloudLinks.first { $0.link == lockedLink }
|
|
||||||
if let existingLink = existingLinks?.link {
|
|
||||||
return existingLink
|
|
||||||
} else {
|
|
||||||
try await allDebrid.saveLink(link: lockedLink)
|
|
||||||
return try await allDebrid.unlockLink(lockedLink: lockedLink)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
await sendDebridError(error, prefix: "AllDebrid download check error")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refreshes torrents and downloads from a RD user's account
|
// Refreshes torrents and downloads from a RD user's account
|
||||||
public func fetchAdCloud(bypassTTL: Bool = false) async {
|
public func fetchAdCloud(bypassTTL: Bool = false) async {
|
||||||
if bypassTTL || Date().timeIntervalSince1970 > allDebridCloudTTL {
|
if bypassTTL || Date().timeIntervalSince1970 > allDebridCloudTTL {
|
||||||
|
|
|
||||||
|
|
@ -23,39 +23,14 @@ struct BatchChoiceView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavView {
|
NavView {
|
||||||
List {
|
List {
|
||||||
switch debridManager.selectedDebridSource?.id {
|
ForEach(debridManager.selectedDebridItem?.files ?? [], id: \.self) { file in
|
||||||
case .some("RealDebrid"):
|
if file.name.lowercased().contains(searchText.lowercased()) || searchText.isEmpty {
|
||||||
ForEach(debridManager.selectedRealDebridItem?.files ?? [], id: \.self) { file in
|
Button(file.name) {
|
||||||
if file.name.lowercased().contains(searchText.lowercased()) || searchText.isEmpty {
|
debridManager.selectedDebridFile = file
|
||||||
Button(file.name) {
|
|
||||||
debridManager.selectedRealDebridFile = file
|
|
||||||
|
|
||||||
queueCommonDownload(fileName: file.name)
|
queueCommonDownload(fileName: file.name)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .some("AllDebrid"):
|
|
||||||
ForEach(debridManager.selectedAllDebridItem?.files ?? [], id: \.self) { file in
|
|
||||||
if file.name.lowercased().contains(searchText.lowercased()) || searchText.isEmpty {
|
|
||||||
Button(file.name) {
|
|
||||||
debridManager.selectedAllDebridFile = file
|
|
||||||
|
|
||||||
queueCommonDownload(fileName: file.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case .some("Premiumize"):
|
|
||||||
ForEach(debridManager.selectedPremiumizeItem?.files ?? [], id: \.self) { file in
|
|
||||||
if file.name.lowercased().contains(searchText.lowercased()) || searchText.isEmpty {
|
|
||||||
Button(file.name) {
|
|
||||||
debridManager.selectedPremiumizeFile = file
|
|
||||||
|
|
||||||
queueCommonDownload(fileName: file.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
EmptyView()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tint(.primary)
|
.tint(.primary)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue