mirror of
https://github.com/cranci1/Sora.git
synced 2026-04-21 08:32:00 +00:00
please trakt please 🙏
This commit is contained in:
parent
ffeddb37e6
commit
51dcae1a54
5 changed files with 138 additions and 91 deletions
|
|
@ -25,29 +25,36 @@ class TraktMutation {
|
||||||
guard status == errSecSuccess,
|
guard status == errSecSuccess,
|
||||||
let tokenData = item as? Data,
|
let tokenData = item as? Data,
|
||||||
let token = String(data: tokenData, encoding: .utf8) else {
|
let token = String(data: tokenData, encoding: .utf8) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
func markAsWatched(type: String, tmdbID: Int, episodeNumber: Int? = nil, seasonNumber: Int? = nil, completion: @escaping (Result<Void, Error>) -> Void) {
|
func markAsWatched(type: String, tmdbID: Int, episodeNumber: Int? = nil, seasonNumber: Int? = nil, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
if let sendTraktUpdates = UserDefaults.standard.object(forKey: "sendTraktUpdates") as? Bool,
|
let sendTraktUpdates = UserDefaults.standard.object(forKey: "sendTraktUpdates") as? Bool ?? true
|
||||||
sendTraktUpdates == false {
|
if !sendTraktUpdates {
|
||||||
|
Logger.shared.log("Trakt updates disabled by user preference", type: "Debug")
|
||||||
|
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Trakt updates disabled by user"])))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.shared.log("Attempting to mark \(type) as watched - TMDB ID: \(tmdbID), Episode: \(episodeNumber ?? 0), Season: \(seasonNumber ?? 0)", type: "Debug")
|
||||||
|
|
||||||
guard let userToken = getTokenFromKeychain() else {
|
guard let userToken = getTokenFromKeychain() else {
|
||||||
|
Logger.shared.log("Trakt access token not found in keychain", type: "Error")
|
||||||
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Access token not found"])))
|
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Access token not found"])))
|
||||||
Logger.shared.log("Trakt Access token not found", type: "Error")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.shared.log("Found Trakt access token, proceeding with API call", type: "Debug")
|
||||||
|
|
||||||
let endpoint = "/sync/history"
|
let endpoint = "/sync/history"
|
||||||
let watchedAt = ISO8601DateFormatter().string(from: Date())
|
let watchedAt = ISO8601DateFormatter().string(from: Date())
|
||||||
let body: [String: Any]
|
let body: [String: Any]
|
||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
case "movie":
|
case "movie":
|
||||||
|
Logger.shared.log("Preparing movie watch request for TMDB ID: \(tmdbID)", type: "Debug")
|
||||||
body = [
|
body = [
|
||||||
"movies": [
|
"movies": [
|
||||||
[
|
[
|
||||||
|
|
@ -59,10 +66,13 @@ class TraktMutation {
|
||||||
|
|
||||||
case "episode":
|
case "episode":
|
||||||
guard let episode = episodeNumber, let season = seasonNumber else {
|
guard let episode = episodeNumber, let season = seasonNumber else {
|
||||||
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Missing episode or season number"])))
|
let errorMsg = "Missing episode (\(episodeNumber ?? -1)) or season (\(seasonNumber ?? -1)) number"
|
||||||
|
Logger.shared.log(errorMsg, type: "Error")
|
||||||
|
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: errorMsg])))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.shared.log("Preparing episode watch request - TMDB ID: \(tmdbID), Season: \(season), Episode: \(episode)", type: "Debug")
|
||||||
body = [
|
body = [
|
||||||
"shows": [
|
"shows": [
|
||||||
[
|
[
|
||||||
|
|
@ -83,6 +93,7 @@ class TraktMutation {
|
||||||
]
|
]
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Logger.shared.log("Invalid content type: \(type)", type: "Error")
|
||||||
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid content type"])))
|
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid content type"])))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -95,36 +106,54 @@ class TraktMutation {
|
||||||
request.setValue(TraktToken.clientID, forHTTPHeaderField: "trakt-api-key")
|
request.setValue(TraktToken.clientID, forHTTPHeaderField: "trakt-api-key")
|
||||||
|
|
||||||
do {
|
do {
|
||||||
request.httpBody = try JSONSerialization.data(withJSONObject: body, options: [.prettyPrinted])
|
let jsonData = try JSONSerialization.data(withJSONObject: body, options: [.prettyPrinted])
|
||||||
|
request.httpBody = jsonData
|
||||||
|
|
||||||
|
if let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||||
|
Logger.shared.log("Trakt API Request Body: \(jsonString)", type: "Debug")
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
Logger.shared.log("Failed to serialize request body: \(error.localizedDescription)", type: "Error")
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.shared.log("Sending Trakt API request to: \(request.url?.absoluteString ?? "unknown")", type: "Debug")
|
||||||
|
|
||||||
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
|
Logger.shared.log("Trakt API network error: \(error.localizedDescription)", type: "Error")
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let httpResponse = response as? HTTPURLResponse else {
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
|
Logger.shared.log("Trakt API: No HTTP response received", type: "Error")
|
||||||
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "No HTTP response"])))
|
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "No HTTP response"])))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.shared.log("Trakt API Response Status: \(httpResponse.statusCode)", type: "Debug")
|
||||||
|
|
||||||
|
if let data = data, let responseString = String(data: data, encoding: .utf8) {
|
||||||
|
Logger.shared.log("Trakt API Response Body: \(responseString)", type: "Debug")
|
||||||
|
}
|
||||||
|
|
||||||
if (200...299).contains(httpResponse.statusCode) {
|
if (200...299).contains(httpResponse.statusCode) {
|
||||||
if let data = data, let responseString = String(data: data, encoding: .utf8) {
|
Logger.shared.log("Successfully updated watch status on Trakt for \(type)", type: "General")
|
||||||
Logger.shared.log("Trakt API Response: \(responseString)", type: "Debug")
|
|
||||||
}
|
|
||||||
Logger.shared.log("Successfully updated watch status on Trakt", type: "Debug")
|
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
} else {
|
} else {
|
||||||
var errorMessage = "Unexpected status code: \(httpResponse.statusCode)"
|
var errorMessage = "HTTP \(httpResponse.statusCode)"
|
||||||
if let data = data,
|
if let data = data,
|
||||||
let errorJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
let errorJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
||||||
let error = errorJson["error"] as? String {
|
if let error = errorJson["error"] as? String {
|
||||||
errorMessage = error
|
errorMessage = "\(errorMessage): \(error)"
|
||||||
|
}
|
||||||
|
if let errorDescription = errorJson["error_description"] as? String {
|
||||||
|
errorMessage = "\(errorMessage) - \(errorDescription)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Logger.shared.log("Trakt API Error: \(errorMessage)", type: "Error")
|
||||||
completion(.failure(NSError(domain: "", code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: errorMessage])))
|
completion(.failure(NSError(domain: "", code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: errorMessage])))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1647,19 +1647,26 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
||||||
self.tryAniListUpdate()
|
self.tryAniListUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let tmdbId = self.tmdbID {
|
if let tmdbId = self.tmdbID, tmdbId > 0 {
|
||||||
|
Logger.shared.log("Attempting Trakt update - TMDB ID: \(tmdbId), isMovie: \(self.isMovie), episode: \(self.episodeNumber), season: \(self.seasonNumber)", type: "Debug")
|
||||||
|
|
||||||
let traktMutation = TraktMutation()
|
let traktMutation = TraktMutation()
|
||||||
|
|
||||||
if self.isMovie {
|
if self.isMovie {
|
||||||
traktMutation.markAsWatched(type: "movie", tmdbID: tmdbId) { result in
|
traktMutation.markAsWatched(type: "movie", tmdbID: tmdbId) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
Logger.shared.log("Successfully updated Trakt progress for movie", type: "General")
|
Logger.shared.log("Successfully updated Trakt progress for movie (TMDB: \(tmdbId))", type: "General")
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
Logger.shared.log("Failed to update Trakt progress: \(error.localizedDescription)", type: "Error")
|
Logger.shared.log("Failed to update Trakt progress for movie: \(error.localizedDescription)", type: "Error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
guard self.episodeNumber > 0 && self.seasonNumber > 0 else {
|
||||||
|
Logger.shared.log("Invalid episode (\(self.episodeNumber)) or season (\(self.seasonNumber)) number for Trakt update", type: "Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
traktMutation.markAsWatched(
|
traktMutation.markAsWatched(
|
||||||
type: "episode",
|
type: "episode",
|
||||||
tmdbID: tmdbId,
|
tmdbID: tmdbId,
|
||||||
|
|
@ -1668,12 +1675,14 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
||||||
) { result in
|
) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
Logger.shared.log("Successfully updated Trakt progress for episode \(self.episodeNumber)", type: "General")
|
Logger.shared.log("Successfully updated Trakt progress for episode \(self.episodeNumber) (TMDB: \(tmdbId))", type: "General")
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
Logger.shared.log("Failed to update Trakt progress: \(error.localizedDescription)", type: "Error")
|
Logger.shared.log("Failed to update Trakt progress for episode: \(error.localizedDescription)", type: "Error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Logger.shared.log("Skipping Trakt update - TMDB ID not set or invalid: \(self.tmdbID ?? -1)", type: "Warning")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1831,6 +1840,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
||||||
|
|
||||||
@objc func seekForward() {
|
@objc func seekForward() {
|
||||||
let skipValue = UserDefaults.standard.double(forKey: "skipIncrement")
|
let skipValue = UserDefaults.standard.double(forKey: "skipIncrement")
|
||||||
|
|
||||||
let finalSkip = skipValue > 0 ? skipValue : 10
|
let finalSkip = skipValue > 0 ? skipValue : 10
|
||||||
currentTimeVal = min(currentTimeVal + finalSkip, duration)
|
currentTimeVal = min(currentTimeVal + finalSkip, duration)
|
||||||
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600)) { [weak self] finished in
|
player.seek(to: CMTime(seconds: currentTimeVal, preferredTimescale: 600)) { [weak self] finished in
|
||||||
|
|
|
||||||
|
|
@ -215,19 +215,26 @@ class VideoPlayerViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let tmdbId = self.tmdbID {
|
if let tmdbId = self.tmdbID, tmdbId > 0 {
|
||||||
|
Logger.shared.log("Attempting Trakt update - TMDB ID: \(tmdbId), isMovie: \(self.isMovie), episode: \(self.episodeNumber), season: \(self.seasonNumber)", type: "Debug")
|
||||||
|
|
||||||
let traktMutation = TraktMutation()
|
let traktMutation = TraktMutation()
|
||||||
|
|
||||||
if self.isMovie {
|
if self.isMovie {
|
||||||
traktMutation.markAsWatched(type: "movie", tmdbID: tmdbId) { result in
|
traktMutation.markAsWatched(type: "movie", tmdbID: tmdbId) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
Logger.shared.log("Updated Trakt progress for movie", type: "General")
|
Logger.shared.log("Updated Trakt progress for movie (TMDB: \(tmdbId))", type: "General")
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
Logger.shared.log("Could not update Trakt progress: \(error.localizedDescription)", type: "Error")
|
Logger.shared.log("Could not update Trakt progress for movie: \(error.localizedDescription)", type: "Error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
guard self.episodeNumber > 0 && self.seasonNumber > 0 else {
|
||||||
|
Logger.shared.log("Invalid episode (\(self.episodeNumber)) or season (\(self.seasonNumber)) number for Trakt update", type: "Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
traktMutation.markAsWatched(
|
traktMutation.markAsWatched(
|
||||||
type: "episode",
|
type: "episode",
|
||||||
tmdbID: tmdbId,
|
tmdbID: tmdbId,
|
||||||
|
|
@ -236,12 +243,14 @@ class VideoPlayerViewController: UIViewController {
|
||||||
) { result in
|
) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
Logger.shared.log("Updated Trakt progress for Episode \(self.episodeNumber)", type: "General")
|
Logger.shared.log("Updated Trakt progress for Episode \(self.episodeNumber) (TMDB: \(tmdbId))", type: "General")
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
Logger.shared.log("Could not update Trakt progress: \(error.localizedDescription)", type: "Error")
|
Logger.shared.log("Could not update Trakt progress for episode: \(error.localizedDescription)", type: "Error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Logger.shared.log("Skipping Trakt update - TMDB ID not set or invalid: \(self.tmdbID ?? -1)", type: "Warning")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -804,12 +804,12 @@ struct MediaInfoView: View {
|
||||||
let total = UserDefaults.standard.double(forKey: totalTimeKey)
|
let total = UserDefaults.standard.double(forKey: totalTimeKey)
|
||||||
let progress = total > 0 ? last/total : 0
|
let progress = total > 0 ? last/total : 0
|
||||||
let watchedEp = ep.number
|
let watchedEp = ep.number
|
||||||
|
|
||||||
if progress <= 0.9 {
|
if progress <= 0.9 {
|
||||||
UserDefaults.standard.set(99999999.0, forKey: lastPlayedKey)
|
UserDefaults.standard.set(99999999.0, forKey: lastPlayedKey)
|
||||||
UserDefaults.standard.set(99999999.0, forKey: totalTimeKey)
|
UserDefaults.standard.set(99999999.0, forKey: totalTimeKey)
|
||||||
DropManager.shared.showDrop(title: "Marked as Watched", subtitle: "", duration: 1.0, icon: UIImage(systemName: "checkmark.circle.fill"))
|
DropManager.shared.showDrop(title: "Marked as Watched", subtitle: "", duration: 1.0, icon: UIImage(systemName: "checkmark.circle.fill"))
|
||||||
|
|
||||||
if let listID = itemID, listID > 0 {
|
if let listID = itemID, listID > 0 {
|
||||||
AniListMutation().updateAnimeProgress(animeId: listID, episodeNumber: watchedEp, status: "CURRENT") { result in
|
AniListMutation().updateAnimeProgress(animeId: listID, episodeNumber: watchedEp, status: "CURRENT") { result in
|
||||||
switch result {
|
switch result {
|
||||||
|
|
@ -824,7 +824,7 @@ struct MediaInfoView: View {
|
||||||
UserDefaults.standard.set(0.0, forKey: lastPlayedKey)
|
UserDefaults.standard.set(0.0, forKey: lastPlayedKey)
|
||||||
UserDefaults.standard.set(0.0, forKey: totalTimeKey)
|
UserDefaults.standard.set(0.0, forKey: totalTimeKey)
|
||||||
DropManager.shared.showDrop(title: "Progress Reset", subtitle: "", duration: 1.0, icon: UIImage(systemName: "arrow.counterclockwise"))
|
DropManager.shared.showDrop(title: "Progress Reset", subtitle: "", duration: 1.0, icon: UIImage(systemName: "arrow.counterclockwise"))
|
||||||
|
|
||||||
if let listID = itemID, listID > 0 {
|
if let listID = itemID, listID > 0 {
|
||||||
AniListMutation().updateAnimeProgress(animeId: listID, episodeNumber: 0, status: "CURRENT") { _ in }
|
AniListMutation().updateAnimeProgress(animeId: listID, episodeNumber: 0, status: "CURRENT") { _ in }
|
||||||
}
|
}
|
||||||
|
|
@ -1204,7 +1204,6 @@ struct MediaInfoView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func fetchAniListIDForSync() {
|
private func fetchAniListIDForSync() {
|
||||||
let cleaned = cleanTitle(title)
|
let cleaned = cleanTitle(title)
|
||||||
|
|
@ -1225,76 +1224,73 @@ struct MediaInfoView: View {
|
||||||
func fetchMetadataIDIfNeeded() {
|
func fetchMetadataIDIfNeeded() {
|
||||||
let order = metadataProvidersOrder
|
let order = metadataProvidersOrder
|
||||||
let cleanedTitle = cleanTitle(title)
|
let cleanedTitle = cleanTitle(title)
|
||||||
|
|
||||||
itemID = nil
|
itemID = nil
|
||||||
tmdbID = nil
|
tmdbID = nil
|
||||||
activeProvider = nil
|
activeProvider = nil
|
||||||
isError = false
|
isError = false
|
||||||
|
|
||||||
func fetchAniList(completion: @escaping (Bool) -> Void) {
|
var aniListCompleted = false
|
||||||
fetchItemID(byTitle: cleanedTitle) { result in
|
var tmdbCompleted = false
|
||||||
|
var aniListSuccess = false
|
||||||
|
var tmdbSuccess = false
|
||||||
|
|
||||||
|
func checkCompletion() {
|
||||||
|
guard aniListCompleted && tmdbCompleted else { return }
|
||||||
|
|
||||||
|
let primaryProvider = order.first ?? "AniList"
|
||||||
|
|
||||||
|
if primaryProvider == "AniList" && aniListSuccess {
|
||||||
|
activeProvider = "AniList"
|
||||||
|
UserDefaults.standard.set("AniList", forKey: "metadataProviders")
|
||||||
|
} else if primaryProvider == "TMDB" && tmdbSuccess {
|
||||||
|
activeProvider = "TMDB"
|
||||||
|
UserDefaults.standard.set("TMDB", forKey: "metadataProviders")
|
||||||
|
} else if aniListSuccess {
|
||||||
|
activeProvider = "AniList"
|
||||||
|
UserDefaults.standard.set("AniList", forKey: "metadataProviders")
|
||||||
|
} else if tmdbSuccess {
|
||||||
|
activeProvider = "TMDB"
|
||||||
|
UserDefaults.standard.set("TMDB", forKey: "metadataProviders")
|
||||||
|
} else {
|
||||||
|
isError = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchItemID(byTitle: cleanedTitle) { result in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
aniListCompleted = true
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let id):
|
case .success(let id):
|
||||||
DispatchQueue.main.async {
|
self.itemID = id
|
||||||
self.itemID = id
|
aniListSuccess = true
|
||||||
self.activeProvider = "AniList"
|
Logger.shared.log("Successfully fetched AniList ID: \(id)", type: "Debug")
|
||||||
UserDefaults.standard.set("AniList", forKey: "metadataProviders")
|
|
||||||
|
|
||||||
tmdbFetcher.fetchBestMatchID(for: cleanedTitle) { tmdbId, tmdbType in
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
guard let tmdbId = tmdbId, let tmdbType = tmdbType else {
|
|
||||||
completion(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.tmdbID = tmdbId
|
|
||||||
self.tmdbType = tmdbType
|
|
||||||
self.fetchTMDBPosterImageAndSet()
|
|
||||||
completion(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
Logger.shared.log("Failed to fetch AniList ID for tracking: \(error)", type: "Error")
|
Logger.shared.log("Failed to fetch AniList ID: \(error)", type: "Debug")
|
||||||
completion(false)
|
|
||||||
}
|
}
|
||||||
|
checkCompletion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryProviders(_ index: Int) {
|
tmdbFetcher.fetchBestMatchID(for: cleanedTitle) { id, type in
|
||||||
guard index < order.count else {
|
DispatchQueue.main.async {
|
||||||
isError = true
|
tmdbCompleted = true
|
||||||
return
|
if let id = id, let type = type {
|
||||||
}
|
self.tmdbID = id
|
||||||
|
self.tmdbType = type
|
||||||
let provider = order[index]
|
tmdbSuccess = true
|
||||||
switch provider {
|
Logger.shared.log("Successfully fetched TMDB ID: \(id) (type: \(type.rawValue))", type: "Debug")
|
||||||
case "AniList":
|
|
||||||
fetchAniList { success in
|
if self.activeProvider != "TMDB" {
|
||||||
if !success {
|
self.fetchTMDBPosterImageAndSet()
|
||||||
tryProviders(index + 1)
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Logger.shared.log("Failed to fetch TMDB ID", type: "Debug")
|
||||||
}
|
}
|
||||||
case "TMDB":
|
checkCompletion()
|
||||||
tmdbFetcher.fetchBestMatchID(for: cleanedTitle) { id, type in
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if let id = id, let type = type {
|
|
||||||
self.tmdbID = id
|
|
||||||
self.tmdbType = type
|
|
||||||
self.activeProvider = "TMDB"
|
|
||||||
UserDefaults.standard.set("TMDB", forKey: "metadataProviders")
|
|
||||||
self.fetchTMDBPosterImageAndSet()
|
|
||||||
} else {
|
|
||||||
tryProviders(index + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
tryProviders(index + 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tryProviders(0)
|
|
||||||
fetchAniListIDForSync()
|
fetchAniListIDForSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1560,6 +1556,8 @@ struct MediaInfoView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentDefaultPlayer(url: String, fullURL: String, subtitles: String?, headers: [String:String]?) {
|
private func presentDefaultPlayer(url: String, fullURL: String, subtitles: String?, headers: [String:String]?) {
|
||||||
|
let isMovie = tmdbType == .movie
|
||||||
|
|
||||||
let videoPlayerViewController = VideoPlayerViewController(module: module)
|
let videoPlayerViewController = VideoPlayerViewController(module: module)
|
||||||
videoPlayerViewController.headers = headers
|
videoPlayerViewController.headers = headers
|
||||||
videoPlayerViewController.streamUrl = url
|
videoPlayerViewController.streamUrl = url
|
||||||
|
|
@ -1570,6 +1568,9 @@ struct MediaInfoView: View {
|
||||||
videoPlayerViewController.mediaTitle = title
|
videoPlayerViewController.mediaTitle = title
|
||||||
videoPlayerViewController.subtitles = subtitles ?? ""
|
videoPlayerViewController.subtitles = subtitles ?? ""
|
||||||
videoPlayerViewController.aniListID = itemID ?? 0
|
videoPlayerViewController.aniListID = itemID ?? 0
|
||||||
|
videoPlayerViewController.tmdbID = tmdbID
|
||||||
|
videoPlayerViewController.isMovie = isMovie
|
||||||
|
videoPlayerViewController.seasonNumber = selectedSeason + 1
|
||||||
videoPlayerViewController.modalPresentationStyle = .fullScreen
|
videoPlayerViewController.modalPresentationStyle = .fullScreen
|
||||||
|
|
||||||
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||||
|
|
@ -1589,6 +1590,7 @@ struct MediaInfoView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
guard self.activeFetchID == fetchID else { return }
|
guard self.activeFetchID == fetchID else { return }
|
||||||
|
let isMovie = tmdbType == .movie
|
||||||
|
|
||||||
let customMediaPlayer = CustomMediaPlayerViewController(
|
let customMediaPlayer = CustomMediaPlayerViewController(
|
||||||
module: module,
|
module: module,
|
||||||
|
|
@ -1604,6 +1606,8 @@ struct MediaInfoView: View {
|
||||||
headers: headers ?? nil
|
headers: headers ?? nil
|
||||||
)
|
)
|
||||||
customMediaPlayer.seasonNumber = selectedSeason + 1
|
customMediaPlayer.seasonNumber = selectedSeason + 1
|
||||||
|
customMediaPlayer.tmdbID = tmdbID
|
||||||
|
customMediaPlayer.isMovie = isMovie
|
||||||
customMediaPlayer.modalPresentationStyle = .fullScreen
|
customMediaPlayer.modalPresentationStyle = .fullScreen
|
||||||
Logger.shared.log("Opening custom media player with url: \(url)")
|
Logger.shared.log("Opening custom media player with url: \(url)")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,18 +24,13 @@ struct SplashScreenView: View {
|
||||||
.cornerRadius(24)
|
.cornerRadius(24)
|
||||||
.scaleEffect(isAnimating ? 1.2 : 1.0)
|
.scaleEffect(isAnimating ? 1.2 : 1.0)
|
||||||
.opacity(isAnimating ? 1.0 : 0.0)
|
.opacity(isAnimating ? 1.0 : 0.0)
|
||||||
|
|
||||||
Text("Sora")
|
|
||||||
.font(.largeTitle)
|
|
||||||
.fontWeight(.bold)
|
|
||||||
.opacity(isAnimating ? 1.0 : 0.0)
|
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
withAnimation(.easeIn(duration: 0.5)) {
|
withAnimation(.easeIn(duration: 0.5)) {
|
||||||
isAnimating = true
|
isAnimating = true
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
||||||
withAnimation(.easeOut(duration: 0.5)) {
|
withAnimation(.easeOut(duration: 0.5)) {
|
||||||
showMainApp = true
|
showMainApp = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue