better 💴 💴💴💴

This commit is contained in:
Francesco 2025-04-08 20:33:16 +02:00
parent 89c8311809
commit 5fef2f15b8
5 changed files with 85 additions and 30 deletions

View file

@ -17,6 +17,9 @@ class AniListToken {
static let serviceName = "me.cranci.sora.AniListToken"
static let accountName = "AniListAccessToken"
static let authSuccessNotification = Notification.Name("AniListAuthenticationSuccess")
static let authFailureNotification = Notification.Name("AniListAuthenticationFailure")
static func saveTokenToKeychain(token: String) -> Bool {
let tokenData = token.data(using: .utf8)!
@ -43,7 +46,10 @@ class AniListToken {
guard let url = URL(string: tokenEndpoint) else {
Logger.shared.log("Invalid token endpoint URL", type: "Error")
completion(false)
DispatchQueue.main.async {
NotificationCenter.default.post(name: authFailureNotification, object: nil, userInfo: ["error": "Invalid token endpoint URL"])
completion(false)
}
return
}
@ -55,31 +61,43 @@ class AniListToken {
request.httpBody = bodyString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
Logger.shared.log("Error: \(error.localizedDescription)", type: "Error")
completion(false)
return
}
guard let data = data else {
Logger.shared.log("No data received", type: "Error")
completion(false)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
if let accessToken = json["access_token"] as? String {
let success = saveTokenToKeychain(token: accessToken)
completion(success)
} else {
Logger.shared.log("Unexpected response: \(json)", type: "Error")
completion(false)
}
DispatchQueue.main.async {
if let error = error {
Logger.shared.log("Error: \(error.localizedDescription)", type: "Error")
NotificationCenter.default.post(name: authFailureNotification, object: nil, userInfo: ["error": error.localizedDescription])
completion(false)
return
}
guard let data = data else {
Logger.shared.log("No data received", type: "Error")
NotificationCenter.default.post(name: authFailureNotification, object: nil, userInfo: ["error": "No data received"])
completion(false)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
if let accessToken = json["access_token"] as? String {
let success = saveTokenToKeychain(token: accessToken)
if success {
NotificationCenter.default.post(name: authSuccessNotification, object: nil)
} else {
NotificationCenter.default.post(name: authFailureNotification, object: nil, userInfo: ["error": "Failed to save token to keychain"])
}
completion(success)
} else {
let errorMessage = (json["error"] as? String) ?? "Unexpected response"
Logger.shared.log("Authentication error: \(errorMessage)", type: "Error")
NotificationCenter.default.post(name: authFailureNotification, object: nil, userInfo: ["error": errorMessage])
completion(false)
}
}
} catch {
Logger.shared.log("Failed to parse JSON: \(error.localizedDescription)", type: "Error")
NotificationCenter.default.post(name: authFailureNotification, object: nil, userInfo: ["error": "Failed to parse response: \(error.localizedDescription)"])
completion(false)
}
} catch {
Logger.shared.log("Failed to parse JSON: \(error.localizedDescription)", type: "Error")
completion(false)
}
}

View file

@ -34,6 +34,11 @@ class AniListMutation {
}
func updateAnimeProgress(animeId: Int, episodeNumber: Int, completion: @escaping (Result<Void, Error>) -> Void) {
if let sendPushUpdates = UserDefaults.standard.object(forKey: "sendPushUpdates") as? Bool,
sendPushUpdates == false {
return
}
guard let userToken = getTokenFromKeychain() else {
completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Access token not found"])))
return

View file

@ -1640,7 +1640,6 @@ class CustomMediaPlayerViewController: UIViewController {
guard self != nil else { return }
if player.timeControlStatus == .paused,
let reason = player.reasonForWaitingToPlay {
// If we are paused for a stall/minimize stalls reason, forcibly resume:
Logger.shared.log("Paused reason: \(reason)", type: "Error")
if reason == .toMinimizeStalls || reason == .evaluatingBufferingRate {
player.play()

View file

@ -10,6 +10,8 @@ import Security
import Kingfisher
struct SettingsViewTrackers: View {
@AppStorage("sendPushUpdates") private var isSendPushUpdates = true
@State private var status: String = "You are not logged in"
@State private var isLoggedIn: Bool = false
@State private var username: String = ""
@ -18,7 +20,7 @@ struct SettingsViewTrackers: View {
var body: some View {
Form {
Section(header: Text("AniList"), footer: Text("Sora and cranci1 are not affiliated with AniList in any way.")) {
Section(header: Text("AniList"), footer: Text("Sora and cranci1 are not affiliated with AniList in any way.\n\nNote that push updates may not be 100% acurate.")) {
HStack() {
KFImage(URL(string: "https://raw.githubusercontent.com/cranci1/Ryu/2f10226aa087154974a70c1ec78aa83a47daced9/Ryu/Assets.xcassets/Listing/Anilist.imageset/anilist.png"))
.placeholder {
@ -50,6 +52,10 @@ struct SettingsViewTrackers: View {
.multilineTextAlignment(.center)
}
}
if isLoggedIn {
Toggle("Send push updates", isOn: $isSendPushUpdates)
.tint(.accentColor)
}
Button(isLoggedIn ? "Log Out from AniList.co" : "Log In with AniList.co") {
if isLoggedIn {
logout()
@ -63,11 +69,38 @@ struct SettingsViewTrackers: View {
.navigationTitle("Trackers")
.onAppear {
updateStatus()
setupNotificationObservers()
}
.onDisappear {
removeNotificationObservers()
}
}
func setupNotificationObservers() {
NotificationCenter.default.addObserver(forName: AniListToken.authSuccessNotification, object: nil, queue: .main) { _ in
self.status = "Authentication successful!"
self.updateStatus()
}
NotificationCenter.default.addObserver(forName: AniListToken.authFailureNotification, object: nil, queue: .main) { notification in
if let error = notification.userInfo?["error"] as? String {
self.status = "Login failed: \(error)"
} else {
self.status = "Login failed with unknown error"
}
self.isLoggedIn = false
self.isLoading = false
}
}
func removeNotificationObservers() {
NotificationCenter.default.removeObserver(self, name: AniListToken.authSuccessNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: AniListToken.authFailureNotification, object: nil)
}
func login() {
status = "Starting authentication..."
isLoading = true
AniListLogin.authenticate()
}

View file

@ -21,9 +21,9 @@ struct SettingsView: View {
NavigationLink(destination: SettingsViewModule()) {
Text("Modules")
}
//NavigationLink(destination: SettingsViewTrackers()) {
// Text("Trackers")
//}
NavigationLink(destination: SettingsViewTrackers()) {
Text("Trackers")
}
}
Section(header: Text("Info")) {