mirror of
https://github.com/Ferrite-iOS/Ferrite.git
synced 2026-04-21 08:52:00 +00:00
Ferrite: Add SwiftFormat
Signed-off-by: kingbri <bdashore3@gmail.com>
This commit is contained in:
parent
e9670ea118
commit
e634906ab4
10 changed files with 123 additions and 39 deletions
1
.swift-version
Normal file
1
.swift-version
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
5.7
|
||||||
77
.swiftformat
Normal file
77
.swiftformat
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
# File exclusion
|
||||||
|
--exclude Ferrite/API/Keychain.swift
|
||||||
|
|
||||||
|
# Formatting options
|
||||||
|
--acronyms ID,URL,UUID
|
||||||
|
--allman false
|
||||||
|
--assetliterals visual-width
|
||||||
|
--beforemarks
|
||||||
|
--binarygrouping none
|
||||||
|
--categorymark "MARK: %c"
|
||||||
|
--classthreshold 0
|
||||||
|
--closingparen balanced
|
||||||
|
--closurevoid remove
|
||||||
|
--commas inline
|
||||||
|
--conflictmarkers reject
|
||||||
|
--decimalgrouping none
|
||||||
|
--elseposition same-line
|
||||||
|
--emptybraces no-space
|
||||||
|
--enumthreshold 0
|
||||||
|
--exponentcase lowercase
|
||||||
|
--exponentgrouping disabled
|
||||||
|
--extensionacl on-extension
|
||||||
|
--extensionlength 0
|
||||||
|
--extensionmark "MARK: - %t + %c"
|
||||||
|
--fractiongrouping disabled
|
||||||
|
--fragment false
|
||||||
|
--funcattributes preserve
|
||||||
|
--groupedextension "MARK: %c"
|
||||||
|
--guardelse auto
|
||||||
|
--header ignore
|
||||||
|
--hexgrouping none
|
||||||
|
--hexliteralcase uppercase
|
||||||
|
--ifdef no-indent
|
||||||
|
--importgrouping alpha
|
||||||
|
--indent 4
|
||||||
|
--indentcase false
|
||||||
|
--indentstrings false
|
||||||
|
--lifecycle
|
||||||
|
--lineaftermarks true
|
||||||
|
--linebreaks lf
|
||||||
|
--markcategories true
|
||||||
|
--markextensions always
|
||||||
|
--marktypes always
|
||||||
|
--maxwidth none
|
||||||
|
--modifierorder
|
||||||
|
--nevertrailing
|
||||||
|
--nospaceoperators
|
||||||
|
--nowrapoperators
|
||||||
|
--octalgrouping none
|
||||||
|
--operatorfunc spaced
|
||||||
|
--organizetypes actor,class,enum,struct
|
||||||
|
--patternlet hoist
|
||||||
|
--ranges spaced
|
||||||
|
--redundanttype infer-locals-only
|
||||||
|
--self remove
|
||||||
|
--selfrequired
|
||||||
|
--semicolons never
|
||||||
|
--shortoptionals always
|
||||||
|
--smarttabs enabled
|
||||||
|
--stripunusedargs closure-only
|
||||||
|
--structthreshold 0
|
||||||
|
--tabwidth unspecified
|
||||||
|
--trailingclosures
|
||||||
|
--trimwhitespace always
|
||||||
|
--typeattributes preserve
|
||||||
|
--typemark "MARK: - %t"
|
||||||
|
--varattributes preserve
|
||||||
|
--voidtype void
|
||||||
|
--wraparguments preserve
|
||||||
|
--wrapcollections before-first
|
||||||
|
--wrapconditions preserve
|
||||||
|
--wrapparameters after-first
|
||||||
|
--wrapreturntype preserve
|
||||||
|
--wrapternary default
|
||||||
|
--wraptypealiases preserve
|
||||||
|
--xcodeindentation disabled
|
||||||
|
--yodaswap always
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
// MARK: - device code endpoint
|
// MARK: - device code endpoint
|
||||||
|
|
||||||
public struct DeviceCodeResponse: Codable {
|
public struct DeviceCodeResponse: Codable {
|
||||||
let deviceCode, userCode: String
|
let deviceCode, userCode: String
|
||||||
let interval, expiresIn: Int
|
let interval, expiresIn: Int
|
||||||
|
|
@ -25,6 +26,7 @@ public struct DeviceCodeResponse: Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - device credentials endpoint
|
// MARK: - device credentials endpoint
|
||||||
|
|
||||||
public struct DeviceCredentialsResponse: Codable {
|
public struct DeviceCredentialsResponse: Codable {
|
||||||
let clientID, clientSecret: String?
|
let clientID, clientSecret: String?
|
||||||
|
|
||||||
|
|
@ -35,6 +37,7 @@ public struct DeviceCredentialsResponse: Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - token endpoint
|
// MARK: - token endpoint
|
||||||
|
|
||||||
public struct TokenResponse: Codable {
|
public struct TokenResponse: Codable {
|
||||||
let accessToken: String
|
let accessToken: String
|
||||||
let expiresIn: Int
|
let expiresIn: Int
|
||||||
|
|
@ -55,7 +58,7 @@ public struct InstantAvailabilityResponse: Codable {
|
||||||
var data: InstantAvailabilityData?
|
var data: InstantAvailabilityData?
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.singleValueContainer()
|
let container = try decoder.singleValueContainer()
|
||||||
|
|
||||||
if let data = try? container.decode(InstantAvailabilityData.self) {
|
if let data = try? container.decode(InstantAvailabilityData.self) {
|
||||||
self.data = data
|
self.data = data
|
||||||
|
|
@ -73,40 +76,43 @@ struct InstantAvailabilityInfo: Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Instant Availability client side structures
|
// MARK: - Instant Availability client side structures
|
||||||
|
|
||||||
public struct RealDebridIA: Codable, Hashable {
|
public struct RealDebridIA: Codable, Hashable {
|
||||||
let hash: String
|
let hash: String
|
||||||
var files: [RealDebridIAFile] = []
|
var files: [RealDebridIAFile] = []
|
||||||
var batches: [RealDebridIABatch] = []
|
var batches: [RealDebridIABatch] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct RealDebridIABatch: Codable, Hashable {
|
public struct RealDebridIABatch: Codable, Hashable {
|
||||||
let files: [RealDebridIABatchFile]
|
let files: [RealDebridIABatchFile]
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct RealDebridIABatchFile: Codable, Hashable {
|
public struct RealDebridIABatchFile: Codable, Hashable {
|
||||||
let id: Int
|
let id: Int
|
||||||
let fileName: String
|
let fileName: String
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct RealDebridIAFile: Codable, Hashable {
|
public struct RealDebridIAFile: Codable, Hashable {
|
||||||
let name: String
|
let name: String
|
||||||
let batchIndex: Int
|
let batchIndex: Int
|
||||||
let batchFileIndex: Int
|
let batchFileIndex: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RealDebridIAStatus: Codable, Hashable {
|
public enum RealDebridIAStatus: Codable, Hashable {
|
||||||
case full
|
case full
|
||||||
case partial
|
case partial
|
||||||
case none
|
case none
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - addMagnet endpoint
|
// MARK: - addMagnet endpoint
|
||||||
|
|
||||||
public struct AddMagnetResponse: Codable {
|
public struct AddMagnetResponse: Codable {
|
||||||
let id: String
|
let id: String
|
||||||
let uri: String
|
let uri: String
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - torrentInfo endpoint
|
// MARK: - torrentInfo endpoint
|
||||||
|
|
||||||
struct TorrentInfoResponse: Codable {
|
struct TorrentInfoResponse: Codable {
|
||||||
let id, filename, originalFilename, hash: String
|
let id, filename, originalFilename, hash: String
|
||||||
let bytes, originalBytes: Int
|
let bytes, originalBytes: Int
|
||||||
|
|
@ -133,6 +139,7 @@ struct TorrentInfoFile: Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - unrestrictLink endpoint
|
// MARK: - unrestrictLink endpoint
|
||||||
|
|
||||||
struct UnrestrictLinkResponse: Codable {
|
struct UnrestrictLinkResponse: Codable {
|
||||||
let id, filename, mimeType: String
|
let id, filename, mimeType: String
|
||||||
let filesize: Int
|
let filesize: Int
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ public enum RealDebridError: Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RealDebrid: ObservableObject {
|
public class RealDebrid: ObservableObject {
|
||||||
var parentManager: DebridManager? = nil
|
var parentManager: DebridManager?
|
||||||
|
|
||||||
let jsonDecoder = JSONDecoder()
|
let jsonDecoder = JSONDecoder()
|
||||||
let keychain = Keychain()
|
let keychain = Keychain()
|
||||||
|
|
@ -60,7 +60,7 @@ public class RealDebrid: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawResponse.directVerificationURL
|
return rawResponse.directVerificationURL
|
||||||
} catch {
|
} catch {
|
||||||
print("Couldn't get the new client creds!")
|
print("Couldn't get the new client creds!")
|
||||||
|
|
@ -108,7 +108,7 @@ public class RealDebrid: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .failure(error) = await authTask?.result {
|
if case let .failure(error) = await authTask?.result {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +137,7 @@ public class RealDebrid: ObservableObject {
|
||||||
]
|
]
|
||||||
|
|
||||||
request.httpBody = bodyComponents.query?.data(using: .utf8)
|
request.httpBody = bodyComponents.query?.data(using: .utf8)
|
||||||
|
|
||||||
let (data, _) = try await URLSession.shared.data(for: request)
|
let (data, _) = try await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
let rawResponse = try jsonDecoder.decode(TokenResponse.self, from: data)
|
let rawResponse = try jsonDecoder.decode(TokenResponse.self, from: data)
|
||||||
|
|
@ -182,7 +182,7 @@ public class RealDebrid: ObservableObject {
|
||||||
if let token = Keychain.shared.get("RealDebrid.AccessToken") {
|
if let token = Keychain.shared.get("RealDebrid.AccessToken") {
|
||||||
var request = URLRequest(url: URL(string: "\(baseApiUrl)/disable_access_token")!)
|
var request = URLRequest(url: URL(string: "\(baseApiUrl)/disable_access_token")!)
|
||||||
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||||||
let _ = try? await URLSession.shared.data(for: request)
|
_ = try? await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
Keychain.shared.delete("RealDebrid.AccessToken")
|
Keychain.shared.delete("RealDebrid.AccessToken")
|
||||||
}
|
}
|
||||||
|
|
@ -240,9 +240,9 @@ public class RealDebrid: ObservableObject {
|
||||||
if data.rd.count > 1 || data.rd[0].count > 1 {
|
if data.rd.count > 1 || data.rd[0].count > 1 {
|
||||||
// Batch array
|
// Batch array
|
||||||
let batches = data.rd.map { fileDict in
|
let batches = data.rd.map { fileDict in
|
||||||
let batchFiles: [RealDebridIABatchFile] = fileDict.map { (key, value) in
|
let batchFiles: [RealDebridIABatchFile] = fileDict.map { key, value in
|
||||||
// Force unwrapped ID. Is safe because ID is guaranteed on a successful response
|
// Force unwrapped ID. Is safe because ID is guaranteed on a successful response
|
||||||
return RealDebridIABatchFile(id: Int(key)!, fileName: value.filename)
|
RealDebridIABatchFile(id: Int(key)!, fileName: value.filename)
|
||||||
}.sorted(by: { $0.id < $1.id })
|
}.sorted(by: { $0.id < $1.id })
|
||||||
|
|
||||||
return RealDebridIABatch(files: batchFiles)
|
return RealDebridIABatch(files: batchFiles)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,6 @@ import Foundation
|
||||||
|
|
||||||
extension Data {
|
extension Data {
|
||||||
func hexEncodedString() -> String {
|
func hexEncodedString() -> String {
|
||||||
return map { String(format: "%02hhx", $0) }.joined()
|
map { String(format: "%02hhx", $0) }.joined()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@ import SwiftUI
|
||||||
|
|
||||||
public class DebridManager: ObservableObject {
|
public class DebridManager: ObservableObject {
|
||||||
// UI Variables
|
// UI Variables
|
||||||
var toastModel: ToastViewModel? = nil
|
var toastModel: ToastViewModel?
|
||||||
@Published var showWebView: Bool = false
|
@Published var showWebView: Bool = false
|
||||||
|
|
||||||
// RealDebrid variables
|
// RealDebrid variables
|
||||||
let realDebrid: RealDebrid = RealDebrid()
|
let realDebrid: RealDebrid = .init()
|
||||||
|
|
||||||
@AppStorage("RealDebrid.Enabled") var realDebridEnabled = false
|
@AppStorage("RealDebrid.Enabled") var realDebridEnabled = false
|
||||||
|
|
||||||
|
|
@ -112,7 +112,7 @@ public class DebridManager: ObservableObject {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileIds = iaBatchFromFile.files.map({ $0.id })
|
fileIds = iaBatchFromFile.files.map(\.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
try await realDebrid.selectFiles(debridID: realDebridId, fileIds: fileIds)
|
try await realDebrid.selectFiles(debridID: realDebridId, fileIds: fileIds)
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Base32
|
import Base32
|
||||||
import SwiftUI
|
|
||||||
import SwiftSoup
|
import SwiftSoup
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
public struct SearchResult: Hashable, Codable {
|
public struct SearchResult: Hashable, Codable {
|
||||||
let title: String
|
let title: String
|
||||||
|
|
@ -30,17 +30,17 @@ class ScrapingViewModel: ObservableObject {
|
||||||
@AppStorage("RealDebrid.Enabled") var realDebridEnabled = false
|
@AppStorage("RealDebrid.Enabled") var realDebridEnabled = false
|
||||||
|
|
||||||
// Link the toast view model for single-directional communication
|
// Link the toast view model for single-directional communication
|
||||||
var toastModel: ToastViewModel? = nil
|
var toastModel: ToastViewModel?
|
||||||
|
|
||||||
// Decopule this in the future
|
// Decopule this in the future
|
||||||
let sources = [
|
let sources = [
|
||||||
//TorrentSource(
|
// TorrentSource(
|
||||||
//name: "Nyaa",
|
// name: "Nyaa",
|
||||||
//url: "https://nyaa.si",
|
// url: "https://nyaa.si",
|
||||||
//rowQuery: ".torrent-list tbody tr",
|
// rowQuery: ".torrent-list tbody tr",
|
||||||
//linkQuery: "td:nth-child(3) > a:nth-child(2))",
|
// linkQuery: "td:nth-child(3) > a:nth-child(2))",
|
||||||
//titleQuery: "td:nth-child(2) > a:last-child"
|
// titleQuery: "td:nth-child(2) > a:last-child"
|
||||||
//),
|
// ),
|
||||||
TorrentSource(
|
TorrentSource(
|
||||||
name: "AnimeTosho",
|
name: "AnimeTosho",
|
||||||
url: "https://animetosho.org/search?q=",
|
url: "https://animetosho.org/search?q=",
|
||||||
|
|
@ -48,7 +48,7 @@ class ScrapingViewModel: ObservableObject {
|
||||||
linkQuery: ".links > a:nth-child(4)",
|
linkQuery: ".links > a:nth-child(4)",
|
||||||
titleQuery: ".link",
|
titleQuery: ".link",
|
||||||
sizeQuery: ".size"
|
sizeQuery: ".size"
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@Published var searchResults: [SearchResult] = []
|
@Published var searchResults: [SearchResult] = []
|
||||||
|
|
@ -91,7 +91,7 @@ class ScrapingViewModel: ObservableObject {
|
||||||
public func scrapeWebsite(source: TorrentSource, html: String) async {
|
public func scrapeWebsite(source: TorrentSource, html: String) async {
|
||||||
var tempResults: [SearchResult] = []
|
var tempResults: [SearchResult] = []
|
||||||
var hashes: [String] = []
|
var hashes: [String] = []
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let document = try SwiftSoup.parse(html)
|
let document = try SwiftSoup.parse(html)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct CardView: View {
|
struct CardView: View {
|
||||||
@Binding var result: SearchResult
|
@Binding var result: SearchResult
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
|
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
// Created by Brian Dashore on 7/20/22.
|
// Created by Brian Dashore on 7/20/22.
|
||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import ActivityView
|
import ActivityView
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
struct MagnetChoiceView: View {
|
struct MagnetChoiceView: View {
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@ struct WebView: UIViewRepresentable {
|
||||||
return webView
|
return webView
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUIView(_ uiView: WKWebView, context: Context) {
|
func updateUIView(_ uiView: WKWebView, context: Context) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WebView_Previews: PreviewProvider {
|
struct WebView_Previews: PreviewProvider {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue