RealDebrid, Github: Reorganize models
Prep for more debrid services Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
a1cd62d3b9
commit
06d4f8e84e
7 changed files with 230 additions and 217 deletions
8
Ferrite/API/AllDebridWrapper.swift
Normal file
8
Ferrite/API/AllDebridWrapper.swift
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// AllDebridWrapper.swift
|
||||
// Ferrite
|
||||
//
|
||||
// Created by Brian Dashore on 11/25/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
|
@ -8,21 +8,21 @@
|
|||
import Foundation
|
||||
|
||||
public class Github {
|
||||
public func fetchLatestRelease() async throws -> GithubRelease? {
|
||||
public func fetchLatestRelease() async throws -> Release? {
|
||||
let url = URL(string: "https://api.github.com/repos/bdashore3/Ferrite/releases/latest")!
|
||||
|
||||
let (data, _) = try await URLSession.shared.data(from: url)
|
||||
|
||||
let rawResponse = try JSONDecoder().decode(GithubRelease.self, from: data)
|
||||
let rawResponse = try JSONDecoder().decode(Release.self, from: data)
|
||||
return rawResponse
|
||||
}
|
||||
|
||||
public func fetchReleases() async throws -> [GithubRelease]? {
|
||||
public func fetchReleases() async throws -> [Release]? {
|
||||
let url = URL(string: "https://api.github.com/repos/bdashore3/Ferrite/releases")!
|
||||
|
||||
let (data, _) = try await URLSession.shared.data(from: url)
|
||||
|
||||
let rawResponse = try JSONDecoder().decode([GithubRelease].self, from: data)
|
||||
let rawResponse = try JSONDecoder().decode([Release].self, from: data)
|
||||
return rawResponse
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,17 +8,6 @@
|
|||
import Foundation
|
||||
import KeychainSwift
|
||||
|
||||
public enum RealDebridError: Error {
|
||||
case InvalidUrl
|
||||
case InvalidPostBody
|
||||
case InvalidResponse
|
||||
case InvalidToken
|
||||
case EmptyData
|
||||
case EmptyTorrents
|
||||
case FailedRequest(description: String)
|
||||
case AuthQuery(description: String)
|
||||
}
|
||||
|
||||
public class RealDebrid {
|
||||
let jsonDecoder = JSONDecoder()
|
||||
let keychain = KeychainSwift()
|
||||
|
|
@ -38,7 +27,7 @@ public class RealDebrid {
|
|||
]
|
||||
|
||||
guard let url = urlComponents.url else {
|
||||
throw RealDebridError.InvalidUrl
|
||||
throw RDError.InvalidUrl
|
||||
}
|
||||
|
||||
let request = URLRequest(url: url)
|
||||
|
|
@ -49,7 +38,7 @@ public class RealDebrid {
|
|||
return rawResponse
|
||||
} catch {
|
||||
print("Couldn't get the new client creds!")
|
||||
throw RealDebridError.AuthQuery(description: error.localizedDescription)
|
||||
throw RDError.AuthQuery(description: error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +51,7 @@ public class RealDebrid {
|
|||
]
|
||||
|
||||
guard let url = urlComponents.url else {
|
||||
throw RealDebridError.InvalidUrl
|
||||
throw RDError.InvalidUrl
|
||||
}
|
||||
|
||||
let request = URLRequest(url: url)
|
||||
|
|
@ -73,7 +62,7 @@ public class RealDebrid {
|
|||
|
||||
while count < 20 {
|
||||
if Task.isCancelled {
|
||||
throw RealDebridError.AuthQuery(description: "Token request cancelled.")
|
||||
throw RDError.AuthQuery(description: "Token request cancelled.")
|
||||
}
|
||||
|
||||
let (data, _) = try await URLSession.shared.data(for: request)
|
||||
|
|
@ -95,7 +84,7 @@ public class RealDebrid {
|
|||
}
|
||||
}
|
||||
|
||||
throw RealDebridError.AuthQuery(description: "Could not fetch the client ID and secret in time. Try logging in again.")
|
||||
throw RDError.AuthQuery(description: "Could not fetch the client ID and secret in time. Try logging in again.")
|
||||
}
|
||||
|
||||
if case let .failure(error) = await authTask?.result {
|
||||
|
|
@ -106,11 +95,11 @@ public class RealDebrid {
|
|||
// Fetch all tokens for the user and store in keychain
|
||||
public func getTokens(deviceCode: String) async throws {
|
||||
guard let clientId = UserDefaults.standard.string(forKey: "RealDebrid.ClientId") else {
|
||||
throw RealDebridError.EmptyData
|
||||
throw RDError.EmptyData
|
||||
}
|
||||
|
||||
guard let clientSecret = keychain.get("RealDebrid.ClientSecret") else {
|
||||
throw RealDebridError.EmptyData
|
||||
throw RDError.EmptyData
|
||||
}
|
||||
|
||||
var request = URLRequest(url: URL(string: "\(baseAuthUrl)/token")!)
|
||||
|
|
@ -174,7 +163,7 @@ public class RealDebrid {
|
|||
// Wrapper request function which matches the responses and returns data
|
||||
@discardableResult public func performRequest(request: inout URLRequest, requestName: String) async throws -> Data {
|
||||
guard let token = await fetchToken() else {
|
||||
throw RealDebridError.InvalidToken
|
||||
throw RDError.InvalidToken
|
||||
}
|
||||
|
||||
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||
|
|
@ -182,23 +171,23 @@ public class RealDebrid {
|
|||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
|
||||
guard let response = response as? HTTPURLResponse else {
|
||||
throw RealDebridError.FailedRequest(description: "No HTTP response given")
|
||||
throw RDError.FailedRequest(description: "No HTTP response given")
|
||||
}
|
||||
|
||||
if response.statusCode >= 200, response.statusCode <= 299 {
|
||||
return data
|
||||
} else if response.statusCode == 401 {
|
||||
try await deleteTokens()
|
||||
throw RealDebridError.FailedRequest(description: "The request \(requestName) failed because you were unauthorized. Please relogin to RealDebrid in Settings.")
|
||||
throw RDError.FailedRequest(description: "The request \(requestName) failed because you were unauthorized. Please relogin to RealDebrid in Settings.")
|
||||
} else {
|
||||
throw RealDebridError.FailedRequest(description: "The request \(requestName) failed with status code \(response.statusCode).")
|
||||
throw RDError.FailedRequest(description: "The request \(requestName) failed with status code \(response.statusCode).")
|
||||
}
|
||||
}
|
||||
|
||||
// Checks if the magnet is streamable on RD
|
||||
// Currently does not work for batch links
|
||||
public func instantAvailability(magnetHashes: [String]) async throws -> [RealDebridIA] {
|
||||
var availableHashes: [RealDebridIA] = []
|
||||
public func instantAvailability(magnetHashes: [String]) async throws -> [RealDebrid.IA] {
|
||||
var availableHashes: [RealDebrid.IA] = []
|
||||
var request = URLRequest(url: URL(string: "\(baseApiUrl)/torrents/instantAvailability/\(magnetHashes.joined(separator: "/"))")!)
|
||||
|
||||
let data = try await performRequest(request: &request, requestName: #function)
|
||||
|
|
@ -219,17 +208,17 @@ public class RealDebrid {
|
|||
if data.rd.count > 1 || data.rd[0].count > 1 {
|
||||
// Batch array
|
||||
let batches = data.rd.map { fileDict in
|
||||
let batchFiles: [RealDebridIABatchFile] = fileDict.map { key, value in
|
||||
let batchFiles: [RealDebrid.IABatchFile] = fileDict.map { key, value in
|
||||
// Force unwrapped ID. Is safe because ID is guaranteed on a successful response
|
||||
RealDebridIABatchFile(id: Int(key)!, fileName: value.filename)
|
||||
RealDebrid.IABatchFile(id: Int(key)!, fileName: value.filename)
|
||||
}.sorted(by: { $0.id < $1.id })
|
||||
|
||||
return RealDebridIABatch(files: batchFiles)
|
||||
return RealDebrid.IABatch(files: batchFiles)
|
||||
}
|
||||
|
||||
// RD files array
|
||||
// Possibly sort this in the future, but not sure how at the moment
|
||||
var files: [RealDebridIAFile] = []
|
||||
var files: [RealDebrid.IAFile] = []
|
||||
|
||||
for index in batches.indices {
|
||||
let batchFiles = batches[index].files
|
||||
|
|
@ -239,7 +228,7 @@ public class RealDebrid {
|
|||
|
||||
if !files.contains(where: { $0.name == batchFile.fileName }) {
|
||||
files.append(
|
||||
RealDebridIAFile(
|
||||
RealDebrid.IAFile(
|
||||
name: batchFile.fileName,
|
||||
batchIndex: index,
|
||||
batchFileIndex: batchFileIndex
|
||||
|
|
@ -251,7 +240,7 @@ public class RealDebrid {
|
|||
|
||||
// TTL: 5 minutes
|
||||
availableHashes.append(
|
||||
RealDebridIA(
|
||||
RealDebrid.IA(
|
||||
hash: hash,
|
||||
expiryTimeStamp: Date().timeIntervalSince1970 + 300,
|
||||
files: files,
|
||||
|
|
@ -260,7 +249,7 @@ public class RealDebrid {
|
|||
)
|
||||
} else {
|
||||
availableHashes.append(
|
||||
RealDebridIA(
|
||||
RealDebrid.IA(
|
||||
hash: hash,
|
||||
expiryTimeStamp: Date().timeIntervalSince1970 + 300
|
||||
)
|
||||
|
|
@ -319,9 +308,9 @@ public class RealDebrid {
|
|||
if let torrentLink = rawResponse.links[safe: selectedIndex ?? -1], rawResponse.status == "downloaded" {
|
||||
return torrentLink
|
||||
} else if rawResponse.status == "downloading" || rawResponse.status == "queued" {
|
||||
throw RealDebridError.EmptyTorrents
|
||||
throw RDError.EmptyTorrents
|
||||
} else {
|
||||
throw RealDebridError.EmptyData
|
||||
throw RDError.EmptyData
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public struct GithubRelease: Codable, Hashable, Sendable {
|
||||
let htmlUrl: String
|
||||
let tagName: String
|
||||
extension Github {
|
||||
public struct Release: Codable, Hashable, Sendable {
|
||||
let htmlUrl: String
|
||||
let tagName: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case htmlUrl = "html_url"
|
||||
case tagName = "tag_name"
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case htmlUrl = "html_url"
|
||||
case tagName = "tag_name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,187 +8,201 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
// MARK: - device code endpoint
|
||||
|
||||
public struct DeviceCodeResponse: Codable, Sendable {
|
||||
let deviceCode, userCode: String
|
||||
let interval, expiresIn: Int
|
||||
let verificationURL, directVerificationURL: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case deviceCode = "device_code"
|
||||
case userCode = "user_code"
|
||||
case interval
|
||||
case expiresIn = "expires_in"
|
||||
case verificationURL = "verification_url"
|
||||
case directVerificationURL = "direct_verification_url"
|
||||
extension RealDebrid {
|
||||
// MARK: - Errors
|
||||
public enum RDError: Error {
|
||||
case InvalidUrl
|
||||
case InvalidPostBody
|
||||
case InvalidResponse
|
||||
case InvalidToken
|
||||
case EmptyData
|
||||
case EmptyTorrents
|
||||
case FailedRequest(description: String)
|
||||
case AuthQuery(description: String)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - device credentials endpoint
|
||||
// MARK: - device code endpoint
|
||||
|
||||
public struct DeviceCredentialsResponse: Codable, Sendable {
|
||||
let clientID, clientSecret: String?
|
||||
public struct DeviceCodeResponse: Codable, Sendable {
|
||||
let deviceCode, userCode: String
|
||||
let interval, expiresIn: Int
|
||||
let verificationURL, directVerificationURL: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case clientID = "client_id"
|
||||
case clientSecret = "client_secret"
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case deviceCode = "device_code"
|
||||
case userCode = "user_code"
|
||||
case interval
|
||||
case expiresIn = "expires_in"
|
||||
case verificationURL = "verification_url"
|
||||
case directVerificationURL = "direct_verification_url"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - token endpoint
|
||||
// MARK: - device credentials endpoint
|
||||
|
||||
public struct TokenResponse: Codable, Sendable {
|
||||
let accessToken: String
|
||||
let expiresIn: Int
|
||||
let refreshToken, tokenType: String
|
||||
public struct DeviceCredentialsResponse: Codable, Sendable {
|
||||
let clientID, clientSecret: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accessToken = "access_token"
|
||||
case expiresIn = "expires_in"
|
||||
case refreshToken = "refresh_token"
|
||||
case tokenType = "token_type"
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case clientID = "client_id"
|
||||
case clientSecret = "client_secret"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - instantAvailability endpoint
|
||||
// MARK: - token endpoint
|
||||
|
||||
// Thanks Skitty!
|
||||
public struct InstantAvailabilityResponse: Codable, Sendable {
|
||||
var data: InstantAvailabilityData?
|
||||
public struct TokenResponse: Codable, Sendable {
|
||||
let accessToken: String
|
||||
let expiresIn: Int
|
||||
let refreshToken, tokenType: String
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accessToken = "access_token"
|
||||
case expiresIn = "expires_in"
|
||||
case refreshToken = "refresh_token"
|
||||
case tokenType = "token_type"
|
||||
}
|
||||
}
|
||||
|
||||
if let data = try? container.decode(InstantAvailabilityData.self) {
|
||||
self.data = data
|
||||
// MARK: - instantAvailability endpoint
|
||||
|
||||
// Thanks Skitty!
|
||||
public struct InstantAvailabilityResponse: Codable, Sendable {
|
||||
var data: InstantAvailabilityData?
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
if let data = try? container.decode(InstantAvailabilityData.self) {
|
||||
self.data = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InstantAvailabilityData: Codable, Sendable {
|
||||
var rd: [[String: InstantAvailabilityInfo]]
|
||||
}
|
||||
|
||||
struct InstantAvailabilityInfo: Codable, Sendable {
|
||||
var filename: String
|
||||
var filesize: Int
|
||||
}
|
||||
|
||||
// MARK: - Instant Availability client side structures
|
||||
|
||||
public struct IA: Codable, Hashable, Sendable {
|
||||
let hash: String
|
||||
let expiryTimeStamp: Double
|
||||
var files: [IAFile] = []
|
||||
var batches: [IABatch] = []
|
||||
}
|
||||
|
||||
public struct IABatch: Codable, Hashable, Sendable {
|
||||
let files: [IABatchFile]
|
||||
}
|
||||
|
||||
public struct IABatchFile: Codable, Hashable, Sendable {
|
||||
let id: Int
|
||||
let fileName: String
|
||||
}
|
||||
|
||||
public struct IAFile: Codable, Hashable, Sendable {
|
||||
let name: String
|
||||
let batchIndex: Int
|
||||
let batchFileIndex: Int
|
||||
}
|
||||
|
||||
public enum IAStatus: Codable, Hashable, Sendable {
|
||||
case full
|
||||
case partial
|
||||
case none
|
||||
}
|
||||
|
||||
// MARK: - addMagnet endpoint
|
||||
|
||||
public struct AddMagnetResponse: Codable, Sendable {
|
||||
let id: String
|
||||
let uri: String
|
||||
}
|
||||
|
||||
// MARK: - torrentInfo endpoint
|
||||
|
||||
struct TorrentInfoResponse: Codable, Sendable {
|
||||
let id, filename, originalFilename, hash: String
|
||||
let bytes, originalBytes: Int
|
||||
let host: String
|
||||
let split, progress: Int
|
||||
let status, added: String
|
||||
let files: [TorrentInfoFile]
|
||||
let links: [String]
|
||||
let ended: String?
|
||||
let speed: Int?
|
||||
let seeders: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, filename
|
||||
case originalFilename = "original_filename"
|
||||
case hash, bytes
|
||||
case originalBytes = "original_bytes"
|
||||
case host, split, progress, status, added, files, links, ended, speed, seeders
|
||||
}
|
||||
}
|
||||
|
||||
struct TorrentInfoFile: Codable, Sendable {
|
||||
let id: Int
|
||||
let path: String
|
||||
let bytes, selected: Int
|
||||
}
|
||||
|
||||
public struct UserTorrentsResponse: Codable, Sendable {
|
||||
let id, filename, hash: String
|
||||
let bytes: Int
|
||||
let host: String
|
||||
let split, progress: Int
|
||||
let status, added: String
|
||||
let links: [String]
|
||||
let speed, seeders: Int?
|
||||
let ended: String?
|
||||
}
|
||||
|
||||
// MARK: - unrestrictLink endpoint
|
||||
|
||||
struct UnrestrictLinkResponse: Codable, Sendable {
|
||||
let id, filename: String
|
||||
let mimeType: String?
|
||||
let filesize: Int
|
||||
let link: String
|
||||
let host: String
|
||||
let hostIcon: String
|
||||
let chunks, crc: Int
|
||||
let download: String
|
||||
let streamable: Int
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, filename, mimeType, filesize, link, host
|
||||
case hostIcon = "host_icon"
|
||||
case chunks, crc, download, streamable
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - User downloads list
|
||||
|
||||
public struct UserDownloadsResponse: Codable, Sendable {
|
||||
let id, filename: String
|
||||
let mimeType: String?
|
||||
let filesize: Int
|
||||
let link: String
|
||||
let host: String
|
||||
let hostIcon: String
|
||||
let chunks: Int
|
||||
let download: String
|
||||
let streamable: Int
|
||||
let generated: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, filename, mimeType, filesize, link, host
|
||||
case hostIcon = "host_icon"
|
||||
case chunks, download, streamable, generated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Instant Availability client side structures
|
||||
|
||||
struct InstantAvailabilityData: Codable, Sendable {
|
||||
var rd: [[String: InstantAvailabilityInfo]]
|
||||
}
|
||||
|
||||
struct InstantAvailabilityInfo: Codable, Sendable {
|
||||
var filename: String
|
||||
var filesize: Int
|
||||
}
|
||||
|
||||
public struct RealDebridIA: Codable, Hashable, Sendable {
|
||||
let hash: String
|
||||
let expiryTimeStamp: Double
|
||||
var files: [RealDebridIAFile] = []
|
||||
var batches: [RealDebridIABatch] = []
|
||||
}
|
||||
|
||||
public struct RealDebridIABatch: Codable, Hashable, Sendable {
|
||||
let files: [RealDebridIABatchFile]
|
||||
}
|
||||
|
||||
public struct RealDebridIABatchFile: Codable, Hashable, Sendable {
|
||||
let id: Int
|
||||
let fileName: String
|
||||
}
|
||||
|
||||
public struct RealDebridIAFile: Codable, Hashable, Sendable {
|
||||
let name: String
|
||||
let batchIndex: Int
|
||||
let batchFileIndex: Int
|
||||
}
|
||||
|
||||
public enum RealDebridIAStatus: Codable, Hashable, Sendable {
|
||||
case full
|
||||
case partial
|
||||
case none
|
||||
}
|
||||
|
||||
// MARK: - addMagnet endpoint
|
||||
|
||||
public struct AddMagnetResponse: Codable, Sendable {
|
||||
let id: String
|
||||
let uri: String
|
||||
}
|
||||
|
||||
// MARK: - torrentInfo endpoint
|
||||
|
||||
struct TorrentInfoResponse: Codable, Sendable {
|
||||
let id, filename, originalFilename, hash: String
|
||||
let bytes, originalBytes: Int
|
||||
let host: String
|
||||
let split, progress: Int
|
||||
let status, added: String
|
||||
let files: [TorrentInfoFile]
|
||||
let links: [String]
|
||||
let ended: String?
|
||||
let speed: Int?
|
||||
let seeders: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, filename
|
||||
case originalFilename = "original_filename"
|
||||
case hash, bytes
|
||||
case originalBytes = "original_bytes"
|
||||
case host, split, progress, status, added, files, links, ended, speed, seeders
|
||||
}
|
||||
}
|
||||
|
||||
struct TorrentInfoFile: Codable, Sendable {
|
||||
let id: Int
|
||||
let path: String
|
||||
let bytes, selected: Int
|
||||
}
|
||||
|
||||
public struct UserTorrentsResponse: Codable, Sendable {
|
||||
let id, filename, hash: String
|
||||
let bytes: Int
|
||||
let host: String
|
||||
let split, progress: Int
|
||||
let status, added: String
|
||||
let links: [String]
|
||||
let speed, seeders: Int?
|
||||
let ended: String?
|
||||
}
|
||||
|
||||
// MARK: - unrestrictLink endpoint
|
||||
|
||||
struct UnrestrictLinkResponse: Codable, Sendable {
|
||||
let id, filename: String
|
||||
let mimeType: String?
|
||||
let filesize: Int
|
||||
let link: String
|
||||
let host: String
|
||||
let hostIcon: String
|
||||
let chunks, crc: Int
|
||||
let download: String
|
||||
let streamable: Int
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, filename, mimeType, filesize, link, host
|
||||
case hostIcon = "host_icon"
|
||||
case chunks, crc, download, streamable
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - User downloads list
|
||||
|
||||
public struct UserDownloadsResponse: Codable, Sendable {
|
||||
let id, filename: String
|
||||
let mimeType: String?
|
||||
let filesize: Int
|
||||
let link: String
|
||||
let host: String
|
||||
let hostIcon: String
|
||||
let chunks: Int
|
||||
let download: String
|
||||
let streamable: Int
|
||||
let generated: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, filename, mimeType, filesize, link, host
|
||||
case hostIcon = "host_icon"
|
||||
case chunks, download, streamable, generated
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ public class DebridManager: ObservableObject {
|
|||
var realDebridAuthUrl: String = ""
|
||||
|
||||
// RealDebrid fetch variables
|
||||
@Published var realDebridIAValues: [RealDebridIA] = []
|
||||
@Published var realDebridIAValues: [RealDebrid.IA] = []
|
||||
var realDebridDownloadUrl: String = ""
|
||||
|
||||
@Published var showDeleteAlert: Bool = false
|
||||
|
||||
// TODO: Switch to an individual item based sheet system to remove these variables
|
||||
var selectedRealDebridItem: RealDebridIA?
|
||||
var selectedRealDebridFile: RealDebridIAFile?
|
||||
var selectedRealDebridItem: RealDebrid.IA?
|
||||
var selectedRealDebridFile: RealDebrid.IAFile?
|
||||
var selectedRealDebridID: String?
|
||||
|
||||
init() {
|
||||
|
|
@ -81,7 +81,7 @@ public class DebridManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
public func matchSearchResult(result: SearchResult?) -> RealDebridIAStatus {
|
||||
public func matchSearchResult(result: SearchResult?) -> RealDebrid.IAStatus {
|
||||
guard let result else {
|
||||
return .none
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ public class DebridManager: ObservableObject {
|
|||
}
|
||||
} catch {
|
||||
switch error {
|
||||
case RealDebridError.EmptyTorrents:
|
||||
case RealDebrid.RDError.EmptyTorrents:
|
||||
showDeleteAlert.toggle()
|
||||
default:
|
||||
let error = error as NSError
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct SettingsAppVersionView: View {
|
|||
@EnvironmentObject var toastModel: ToastViewModel
|
||||
|
||||
@State private var viewTask: Task<Void, Never>?
|
||||
@State private var releases: [GithubRelease] = []
|
||||
@State private var releases: [Github.Release] = []
|
||||
|
||||
@State private var loadedReleases = false
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue