mirror of
https://github.com/cranci1/Sora.git
synced 2026-03-28 13:28:45 +00:00
better 💴 💴💴💴
This commit is contained in:
parent
89c8311809
commit
5fef2f15b8
5 changed files with 85 additions and 30 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue