thank god man thank god
Some checks are pending
Build and Release IPA / Build IPA (push) Waiting to run

This commit is contained in:
cranci1 2025-01-08 17:07:31 +01:00
parent 3ebf986424
commit ac66da899c
3 changed files with 107 additions and 18 deletions

View file

@ -70,9 +70,9 @@ class JSController: ObservableObject {
}.resume()
}
func fetchDetails(url: String, completion: @escaping ([MediaItem]) -> Void) {
func fetchDetails(url: String, completion: @escaping ([MediaItem], [EpisodeLink]) -> Void) {
guard let url = URL(string: url) else {
completion([])
completion([], [])
return
}
@ -81,31 +81,43 @@ class JSController: ObservableObject {
if let error = error {
print("Network error: \(error)")
DispatchQueue.main.async { completion([]) }
DispatchQueue.main.async { completion([], []) }
return
}
guard let data = data, let html = String(data: data, encoding: .utf8) else {
print("Failed to decode HTML")
DispatchQueue.main.async { completion([]) }
DispatchQueue.main.async { completion([], []) }
return
}
var resultItems: [MediaItem] = []
var episodeLinks: [EpisodeLink] = []
if let parseFunction = self.context.objectForKeyedSubscript("extractDetails"),
let results = parseFunction.call(withArguments: [html]).toArray() as? [[String: String]] {
let resultItems = results.map { item in
resultItems = results.map { item in
MediaItem(
description: item["description"] ?? "",
aliases: item["aliases"] ?? "",
airdate: item["airdate"] ?? ""
)
}
DispatchQueue.main.async {
completion(resultItems)
}
} else {
print("Failed to parse results")
DispatchQueue.main.async { completion([]) }
}
if let fetchEpisodesFunction = self.context.objectForKeyedSubscript("extractEpisodes"),
let episodesResult = fetchEpisodesFunction.call(withArguments: [html]).toArray() as? [[String: String]] {
for episodeData in episodesResult {
if let num = episodeData["number"], let link = episodeData["href"], let number = Int(num) {
episodeLinks.append(EpisodeLink(number: number, href: link))
}
}
}
DispatchQueue.main.async {
completion(resultItems, episodeLinks)
}
}.resume()
}

View file

@ -8,10 +8,15 @@
import SwiftUI
import Kingfisher
struct EpisodeLink: Identifiable {
let id = UUID()
let number: Int
let href: String
}
struct EpisodeCell: View {
let episode: String
let episodeID: Int
let imageUrl: String
let progress: Double
let itemID: Int

View file

@ -24,9 +24,8 @@ struct MediaInfoView: View {
@State var aliases: String = ""
@State var synopsis: String = ""
@State var airdate: String = ""
@State var genres: [String] = []
@State var episodes: [String] = []
@State var episodeLinks: [EpisodeLink] = []
@State var itemID: Int?
@State var isLoading: Bool = true
@State var showFullSynopsis: Bool = false
@ -132,32 +131,57 @@ struct MediaInfoView: View {
.frame(width: 20, height: 27)
}
}
if !episodeLinks.isEmpty {
VStack(alignment: .leading, spacing: 10) {
Text("Episodes")
.font(.system(size: 18))
.fontWeight(.bold)
ForEach(episodeLinks.indices, id: \.self) { i in
let ep = episodeLinks[i]
let lastPlayedTime = UserDefaults.standard.double(forKey: "lastPlayedTime_\(ep.href)")
let totalTime = UserDefaults.standard.double(forKey: "totalTime_\(ep.href)")
let progress = totalTime > 0 ? lastPlayedTime / totalTime : 0
EpisodeCell(episode: ep.href, episodeID: ep.number - 1, progress: progress, itemID: itemID ?? 0)
}
}
}
}
.padding()
.navigationBarTitleDisplayMode(.inline)
.navigationBarTitle(title)
.navigationBarTitle("")
.navigationViewStyle(StackNavigationViewStyle())
}
}
}
.onAppear {
getDetails()
fetchDetails()
fetchItemID(byTitle: title) { result in
switch result {
case .success(let id):
itemID = id
case .failure(let error):
print("Failed to fetch Item ID: \(error)")
}
}
}
}
func getDetails() {
func fetchDetails() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
Task {
do {
let jsContent = try moduleManager.getModuleContent(module)
jsController.loadScript(jsContent)
jsController.fetchDetails(url: href) { items in
jsController.fetchDetails(url: href) { items, episodes in
if let item = items.first {
print("Fetched item: \(item)")
self.synopsis = item.description
self.aliases = item.aliases
self.airdate = item.airdate
}
self.episodeLinks = episodes
self.isLoading = false
}
} catch {
@ -167,4 +191,52 @@ struct MediaInfoView: View {
}
}
}
private func fetchItemID(byTitle title: String, completion: @escaping (Result<Int, Error>) -> Void) {
let query = """
query {
Media(search: "\(title)", type: ANIME) {
id
}
}
"""
guard let url = URL(string: "https://graphql.anilist.co") else {
completion(.failure(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])))
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let parameters: [String: Any] = ["query": query]
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
URLSession.custom.dataTask(with: request) { data, _, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else {
completion(.failure(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "No data received"])))
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let data = json["data"] as? [String: Any],
let media = data["Media"] as? [String: Any],
let id = media["id"] as? Int {
completion(.success(id))
} else {
let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])
completion(.failure(error))
}
} catch {
completion(.failure(error))
}
}.resume()
}
}