This commit is contained in:
Francesco 2025-04-07 21:11:08 +02:00
parent f80f18cd1c
commit 14affcdd01
10 changed files with 120 additions and 288 deletions

View file

@ -0,0 +1,100 @@
//
// AniListPushUpdates.swift
// Sulfur
//
// Created by Francesco on 07/04/25.
//
import UIKit
import Security
class AniListMutation {
let apiURL = URL(string: "https://graphql.anilist.co")!
func getTokenFromKeychain() -> String? {
let serviceName = "me.cranci.sora.AniListToken"
let accountName = "AniListAccessToken"
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: accountName,
kSecReturnData as String: kCFBooleanTrue!,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess, let tokenData = item as? Data else {
return nil
}
return String(data: tokenData, encoding: .utf8)
}
func updateAnimeProgress(animeId: Int, episodeNumber: Int, completion: @escaping (Result<Void, Error>) -> Void) {
guard let userToken = getTokenFromKeychain() else {
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Access token not found"])))
return
}
let query = """
mutation ($mediaId: Int, $progress: Int) {
SaveMediaListEntry (mediaId: $mediaId, progress: $progress) {
id
progress
}
}
"""
let variables: [String: Any] = [
"mediaId": animeId,
"progress": episodeNumber
]
let requestBody: [String: Any] = [
"query": query,
"variables": variables
]
guard let jsonData = try? JSONSerialization.data(withJSONObject: requestBody, options: []) else {
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to serialize JSON"])))
return
}
var request = URLRequest(url: apiURL)
request.httpMethod = "POST"
request.setValue("Bearer \(userToken)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
completion(.failure(NSError(domain: "", code: statusCode, userInfo: [NSLocalizedDescriptionKey: "Unexpected response or status code"])))
return
}
if let data = data {
do {
let responseJSON = try JSONSerialization.jsonObject(with: data, options: [])
print("Successfully updated anime progress")
print(responseJSON)
completion(.success(()))
} catch {
completion(.failure(error))
}
} else {
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "No data received"])))
}
}
task.resume()
}
}

View file

@ -1,24 +0,0 @@
//
// AniListItem.swift
// Sora
//
// Created by Francesco on 09/02/25.
//
import Foundation
struct AniListItem: Codable {
let id: Int
let title: AniListTitle
let coverImage: AniListCoverImage
}
struct AniListTitle: Codable {
let romaji: String
let english: String?
let native: String?
}
struct AniListCoverImage: Codable {
let large: String
}

View file

@ -1,57 +0,0 @@
//
// TMDB-Seasonal.swift
// Sulfur
//
// Created by Francesco on 05/03/25.
//
import Foundation
class TMDBSeasonal {
static func fetchTMDBSeasonal(completion: @escaping ([AniListItem]?) -> Void) {
Task {
do {
let url = URL(string: "https://api.themoviedb.org/3/movie/upcoming")!
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
components.queryItems = [
URLQueryItem(name: "language", value: "en-US")
]
var request = URLRequest(url: components.url!)
let token = TMBDRequest.getToken()
request.allHTTPHeaderFields = [
"accept": "application/json",
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
"Authorization": "Bearer \(token)"
]
let (data, _) = try await URLSession.shared.data(for: request)
let response = try JSONDecoder().decode(TMDBResponse.self, from: data)
let anilistItems = response.results.map { item in
AniListItem(
id: item.id,
title: AniListTitle(
romaji: item.displayTitle,
english: item.originalTitle ?? item.originalName ?? item.displayTitle,
native: ""
),
coverImage: AniListCoverImage(
large: item.posterURL
)
)
}
DispatchQueue.main.async {
completion(anilistItems)
}
} catch {
DispatchQueue.main.async {
Logger.shared.log("Error fetching TMDB seasonal: \(error.localizedDescription)")
completion(nil)
}
}
}
}
}

View file

@ -1,61 +0,0 @@
//
// TMDB-Trending.swift
// Sulfur
//
// Created by Francesco on 05/03/25.
//
import Foundation
class TMBDTrending {
static func fetchTMDBTrending(completion: @escaping ([AniListItem]?) -> Void) {
Task {
do {
let items = try await fetchTrendingItems()
let anilistItems = items.map { item in
AniListItem(
id: item.id,
title: AniListTitle(
romaji: item.displayTitle,
english: item.originalTitle ?? item.originalName ?? item.displayTitle,
native: ""
),
coverImage: AniListCoverImage(
large: item.posterURL
)
)
}
DispatchQueue.main.async {
completion(anilistItems)
}
} catch {
DispatchQueue.main.async {
Logger.shared.log("Error fetching TMDB trending: \(error.localizedDescription)")
completion(nil)
}
}
}
}
private static func fetchTrendingItems() async throws -> [TMDBItem] {
let url = URL(string: "https://api.themoviedb.org/3/trending/all/day")!
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
let queryItems: [URLQueryItem] = [
URLQueryItem(name: "language", value: "en-US")
]
components.queryItems = queryItems
let token = TMBDRequest.getToken()
var request = URLRequest(url: components.url!)
request.allHTTPHeaderFields = [
"accept": "application/json",
"Authorization": "Bearer \(token)"
]
let (data, _) = try await URLSession.shared.data(for: request)
let response = try JSONDecoder().decode(TMDBResponse.self, from: data)
return response.results
}
}

View file

@ -1,61 +0,0 @@
//
// TMDBItem.swift
// Sulfur
//
// Created by Francesco on 05/03/25.
//
import Foundation
struct TMDBItem: Codable {
let id: Int
let mediaType: String?
let title: String?
let originalTitle: String?
let releaseDate: String?
let name: String?
let originalName: String?
let firstAirDate: String?
let posterPath: String?
let backdropPath: String?
let overview: String
let voteAverage: Double?
enum CodingKeys: String, CodingKey {
case id, overview
case mediaType = "media_type"
case title, name
case originalTitle = "original_title"
case originalName = "original_name"
case posterPath = "poster_path"
case backdropPath = "backdrop_path"
case releaseDate = "release_date"
case firstAirDate = "first_air_date"
case voteAverage = "vote_average"
}
var displayTitle: String {
return title ?? name ?? "Unknown Title"
}
var posterURL: String {
if let path = posterPath {
return "https://image.tmdb.org/t/p/w500\(path)"
}
return ""
}
var backdropURL: String {
if let path = backdropPath {
return "https://image.tmdb.org/t/p/original\(path)"
}
return ""
}
var displayDate: String {
return releaseDate ?? firstAirDate ?? ""
}
}

View file

@ -1,33 +0,0 @@
//
// TMDBRequest.swift
// Sulfur
//
// Created by Francesco on 05/03/25.
//
import Foundation
struct TMDBResponse: Codable {
let results: [TMDBItem]
let page: Int
let totalPages: Int
let totalResults: Int
enum CodingKeys: String, CodingKey {
case results, page
case totalPages = "total_pages"
case totalResults = "total_results"
}
}
class TMBDRequest {
private static let Token = "ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKaGRXUWlPaUkzTXpoaU5HVmtaREJoTVRVMlkyTXhNalprWXpSaE5HSTRZV1ZoTkdGallTSXNJbTVpWmlJNk1UYzBNVEUzTXpjd01pNDNPRGN3TURBeUxDSnpkV0lpT2lJMk4yTTRNek5qTm1RM05ERTVZMlJtWkRnMlpUSmtaR1lpTENKelkyOXdaWE1pT2xzaVlYQnBYM0psWVdRaVhTd2lkbVZ5YzJsdmJpSTZNWDAuR2ZlN0YtOENXSlhnT052MzRtZzNqSFhmTDZCeGJqLWhBWWY5ZllpOUNrRQ=="
static func getToken() -> String {
guard let tokenData = Data(base64Encoded: Token),
let token = String(data: tokenData, encoding: .utf8) else {
fatalError("Failed to decode token.")
}
return token
}
}

View file

@ -23,6 +23,7 @@ struct ModuleMetadata: Codable, Hashable {
let softsub: Bool?
let multiStream: Bool?
let multiSubs: Bool?
let type: String?
struct Author: Codable, Hashable {
let name: String

View file

@ -20,6 +20,7 @@ struct EpisodeCell: View {
let episodeID: Int
let progress: Double
let itemID: Int
let module: ScrapingModule
let onTap: (String) -> Void
let onMarkAllPrevious: () -> Void
@ -124,6 +125,11 @@ struct EpisodeCell: View {
}
private func fetchEpisodeDetails() {
guard module.metadata.type == "anime" else {
isLoading = false
return
}
guard let url = URL(string: "https://api.ani.zip/mappings?anilist_id=\(itemID)") else {
isLoading = false
return

View file

@ -288,6 +288,7 @@ struct MediaInfoView: View {
episodeID: ep.number - 1,
progress: progress,
itemID: itemID ?? 0,
module: module,
onTap: { imageUrl in
if !isFetchingEpisode {
selectedEpisodeNumber = ep.number

View file

@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
130217CC2D81C55E0011EFF5 /* DownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130217CB2D81C55E0011EFF5 /* DownloadView.swift */; };
130C6BFA2D53AB1F00DC1432 /* SettingsViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130C6BF92D53AB1F00DC1432 /* SettingsViewData.swift */; };
13103E892D58A39A000F0673 /* AniListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E882D58A39A000F0673 /* AniListItem.swift */; };
13103E8B2D58E028000F0673 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E8A2D58E028000F0673 /* View.swift */; };
13103E8E2D58E04A000F0673 /* SkeletonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13103E8D2D58E04A000F0673 /* SkeletonCell.swift */; };
131845F92D47C62D00CA7A54 /* SettingsViewGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131845F82D47C62D00CA7A54 /* SettingsViewGeneral.swift */; };
@ -21,10 +20,6 @@
132E351D2D959DDB0007800E /* Drops in Frameworks */ = {isa = PBXBuildFile; productRef = 132E351C2D959DDB0007800E /* Drops */; };
132E35202D959E1D0007800E /* FFmpeg-iOS-Lame in Frameworks */ = {isa = PBXBuildFile; productRef = 132E351F2D959E1D0007800E /* FFmpeg-iOS-Lame */; };
132E35232D959E410007800E /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 132E35222D959E410007800E /* Kingfisher */; };
1334FF4D2D786C93007E289F /* TMDB-Seasonal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1334FF4C2D786C93007E289F /* TMDB-Seasonal.swift */; };
1334FF4F2D786C9E007E289F /* TMDB-Trending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1334FF4E2D786C9E007E289F /* TMDB-Trending.swift */; };
1334FF522D7871B7007E289F /* TMDBItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1334FF512D7871B7007E289F /* TMDBItem.swift */; };
1334FF542D787217007E289F /* TMDBRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1334FF532D787217007E289F /* TMDBRequest.swift */; };
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6D2D2BE2500075467E /* SoraApp.swift */; };
133D7C702D2BE2500075467E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6F2D2BE2500075467E /* ContentView.swift */; };
133D7C722D2BE2520075467E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 133D7C712D2BE2520075467E /* Assets.xcassets */; };
@ -46,6 +41,7 @@
1399FAD42D3AB38C00E97C31 /* SettingsViewLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1399FAD32D3AB38C00E97C31 /* SettingsViewLogger.swift */; };
1399FAD62D3AB3DB00E97C31 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1399FAD52D3AB3DB00E97C31 /* Logger.swift */; };
13B77E192DA44F8300126FDF /* MarqueeLabel in Frameworks */ = {isa = PBXBuildFile; productRef = 13B77E182DA44F8300126FDF /* MarqueeLabel */; };
13B77E202DA457AA00126FDF /* AniListPushUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13B77E1F2DA457AA00126FDF /* AniListPushUpdates.swift */; };
13B7F4C12D58FFDD0045714A /* Shimmer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13B7F4C02D58FFDD0045714A /* Shimmer.swift */; };
13C0E5EA2D5F85EA00E7F619 /* ContinueWatchingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C0E5E92D5F85EA00E7F619 /* ContinueWatchingManager.swift */; };
13C0E5EC2D5F85F800E7F619 /* ContinueWatchingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C0E5EB2D5F85F800E7F619 /* ContinueWatchingItem.swift */; };
@ -73,7 +69,6 @@
130217CB2D81C55E0011EFF5 /* DownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadView.swift; sourceTree = "<group>"; };
130C6BF82D53A4C200DC1432 /* Sora.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sora.entitlements; sourceTree = "<group>"; };
130C6BF92D53AB1F00DC1432 /* SettingsViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewData.swift; sourceTree = "<group>"; };
13103E882D58A39A000F0673 /* AniListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AniListItem.swift; sourceTree = "<group>"; };
13103E8A2D58E028000F0673 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
13103E8D2D58E04A000F0673 /* SkeletonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonCell.swift; sourceTree = "<group>"; };
131845F82D47C62D00CA7A54 /* SettingsViewGeneral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewGeneral.swift; sourceTree = "<group>"; };
@ -82,10 +77,6 @@
132AF1202D99951700A0140B /* JSController-Streams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Streams.swift"; sourceTree = "<group>"; };
132AF1222D9995C300A0140B /* JSController-Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Details.swift"; sourceTree = "<group>"; };
132AF1242D9995F900A0140B /* JSController-Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Search.swift"; sourceTree = "<group>"; };
1334FF4C2D786C93007E289F /* TMDB-Seasonal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TMDB-Seasonal.swift"; sourceTree = "<group>"; };
1334FF4E2D786C9E007E289F /* TMDB-Trending.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TMDB-Trending.swift"; sourceTree = "<group>"; };
1334FF512D7871B7007E289F /* TMDBItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TMDBItem.swift; sourceTree = "<group>"; };
1334FF532D787217007E289F /* TMDBRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TMDBRequest.swift; sourceTree = "<group>"; };
133D7C6A2D2BE2500075467E /* Sulfur.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sulfur.app; sourceTree = BUILT_PRODUCTS_DIR; };
133D7C6D2D2BE2500075467E /* SoraApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraApp.swift; sourceTree = "<group>"; };
133D7C6F2D2BE2500075467E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@ -107,6 +98,7 @@
139935652D468C450065CEFF /* ModuleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleManager.swift; sourceTree = "<group>"; };
1399FAD32D3AB38C00E97C31 /* SettingsViewLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewLogger.swift; sourceTree = "<group>"; };
1399FAD52D3AB3DB00E97C31 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
13B77E1F2DA457AA00126FDF /* AniListPushUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AniListPushUpdates.swift; sourceTree = "<group>"; };
13B7F4C02D58FFDD0045714A /* Shimmer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shimmer.swift; sourceTree = "<group>"; };
13C0E5E92D5F85EA00E7F619 /* ContinueWatchingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContinueWatchingManager.swift; sourceTree = "<group>"; };
13C0E5EB2D5F85F800E7F619 /* ContinueWatchingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContinueWatchingItem.swift; sourceTree = "<group>"; };
@ -149,7 +141,6 @@
13103E802D589D6C000F0673 /* Tracking Services */ = {
isa = PBXGroup;
children = (
1334FF4A2D786C6D007E289F /* TMDB */,
13103E812D589D77000F0673 /* AniList */,
);
path = "Tracking Services";
@ -158,20 +149,12 @@
13103E812D589D77000F0673 /* AniList */ = {
isa = PBXGroup;
children = (
13B77E1E2DA4577D00126FDF /* Mutations */,
13DB468A2D900919008CBC03 /* Auth */,
13103E872D58A392000F0673 /* Struct */,
);
path = AniList;
sourceTree = "<group>";
};
13103E872D58A392000F0673 /* Struct */ = {
isa = PBXGroup;
children = (
13103E882D58A39A000F0673 /* AniListItem.swift */,
);
path = Struct;
sourceTree = "<group>";
};
13103E8C2D58E037000F0673 /* SkeletonCells */ = {
isa = PBXGroup;
children = (
@ -189,33 +172,6 @@
path = Analytics;
sourceTree = "<group>";
};
1334FF4A2D786C6D007E289F /* TMDB */ = {
isa = PBXGroup;
children = (
1334FF502D7871A4007E289F /* Struct */,
1334FF4B2D786C81007E289F /* HomePage */,
);
path = TMDB;
sourceTree = "<group>";
};
1334FF4B2D786C81007E289F /* HomePage */ = {
isa = PBXGroup;
children = (
1334FF4C2D786C93007E289F /* TMDB-Seasonal.swift */,
1334FF4E2D786C9E007E289F /* TMDB-Trending.swift */,
);
path = HomePage;
sourceTree = "<group>";
};
1334FF502D7871A4007E289F /* Struct */ = {
isa = PBXGroup;
children = (
1334FF512D7871B7007E289F /* TMDBItem.swift */,
1334FF532D787217007E289F /* TMDBRequest.swift */,
);
path = Struct;
sourceTree = "<group>";
};
133D7C612D2BE2500075467E = {
isa = PBXGroup;
children = (
@ -387,6 +343,14 @@
path = SettingsView;
sourceTree = "<group>";
};
13B77E1E2DA4577D00126FDF /* Mutations */ = {
isa = PBXGroup;
children = (
13B77E1F2DA457AA00126FDF /* AniListPushUpdates.swift */,
);
path = Mutations;
sourceTree = "<group>";
};
13C0E5E82D5F85DD00E7F619 /* ContinueWatching */ = {
isa = PBXGroup;
children = (
@ -541,24 +505,20 @@
139935662D468C450065CEFF /* ModuleManager.swift in Sources */,
133D7C902D2BE2640075467E /* SettingsView.swift in Sources */,
132AF1252D9995F900A0140B /* JSController-Search.swift in Sources */,
1334FF4F2D786C9E007E289F /* TMDB-Trending.swift in Sources */,
13CBEFDA2D5F7D1200D011EE /* String.swift in Sources */,
13DB46902D900A38008CBC03 /* URL.swift in Sources */,
130C6BFA2D53AB1F00DC1432 /* SettingsViewData.swift in Sources */,
1334FF542D787217007E289F /* TMDBRequest.swift in Sources */,
1E9FF1D32D403E49008AC100 /* SettingsViewLoggerFilter.swift in Sources */,
13EA2BD92D32D98400C1EBD7 /* NormalPlayer.swift in Sources */,
133D7C932D2BE2640075467E /* Modules.swift in Sources */,
13DB7CC32D7D99C0004371D3 /* SubtitleSettingsManager.swift in Sources */,
133D7C702D2BE2500075467E /* ContentView.swift in Sources */,
13DB7CEC2D7DED5D004371D3 /* DownloadManager.swift in Sources */,
1334FF522D7871B7007E289F /* TMDBItem.swift in Sources */,
13D99CF72D4E73C300250A86 /* ModuleAdditionSettingsView.swift in Sources */,
13C0E5EC2D5F85F800E7F619 /* ContinueWatchingItem.swift in Sources */,
13CBA0882D60F19C00EFE70A /* VTTSubtitlesLoader.swift in Sources */,
13EA2BD62D32D97400C1EBD7 /* Double+Extension.swift in Sources */,
133D7C8F2D2BE2640075467E /* MediaInfoView.swift in Sources */,
13103E892D58A39A000F0673 /* AniListItem.swift in Sources */,
132AF1212D99951700A0140B /* JSController-Streams.swift in Sources */,
131845F92D47C62D00CA7A54 /* SettingsViewGeneral.swift in Sources */,
13103E8E2D58E04A000F0673 /* SkeletonCell.swift in Sources */,
@ -577,11 +537,11 @@
133D7C8E2D2BE2640075467E /* LibraryView.swift in Sources */,
133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */,
138AA1B92D2D66FD0021F9DF /* CircularProgressBar.swift in Sources */,
1334FF4D2D786C93007E289F /* TMDB-Seasonal.swift in Sources */,
1E3F5EC82D9F16B7003F310F /* VerticalBrightnessSlider.swift in Sources */,
13DB468D2D90093A008CBC03 /* Anilist-Login.swift in Sources */,
73D164D52D8B5B470011A360 /* JavaScriptCore+Extensions.swift in Sources */,
132AF1232D9995C300A0140B /* JSController-Details.swift in Sources */,
13B77E202DA457AA00126FDF /* AniListPushUpdates.swift in Sources */,
13EA2BD52D32D97400C1EBD7 /* CustomPlayer.swift in Sources */,
1399FAD42D3AB38C00E97C31 /* SettingsViewLogger.swift in Sources */,
13DB46922D900BCE008CBC03 /* SettingsViewTrackers.swift in Sources */,