feat: AniList tracking

This commit is contained in:
2026-08-03 00:01:28 +02:00
parent 48ea3c40a1
commit 3a0d094070
+82 -3
View File
@@ -47,6 +47,7 @@ struct LocalState: Codable {
var progress: ReadProgress
var backgroundColor: String?
var useDefaultPageTurnMode: Bool
var aniListTracking: Bool
}
struct Settings: Codable {
@@ -80,6 +81,7 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
var currentPath: URL!
var lastLayoutSize: CGSize = .zero
var aniListToken: String? = getAniListToken()
var aniListTracking = false
var leftTap: UITapGestureRecognizer!
var rightTap: UITapGestureRecognizer!
@@ -798,7 +800,8 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
try JSONEncoder().encode(
LocalState(
progress: newProgress, backgroundColor: self.convertColorToString(color),
useDefaultPageTurnMode: self.useDefaultPageTurnMode
useDefaultPageTurnMode: self.useDefaultPageTurnMode,
aniListTracking: self.aniListTracking
)
).write(
to: self.currentPath.appendingPathComponent("state.json")
@@ -820,6 +823,7 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
let json = try Data(String(contentsOfFile: path).utf8)
let local = try JSONDecoder().decode(LocalState.self, from: json)
useDefaultPageTurnMode = local.useDefaultPageTurnMode
aniListTracking = local.aniListTracking
switch local.progress {
case let .leftToRight(volumeIndex, chapterIndex, imageIndex):
progress.v = volumeIndex
@@ -894,6 +898,7 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
for _ in 0 ..< indexPath.item {
newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
}
aniListProgressUpdate(progress: progress, newProgress: newProgress)
progress = newProgress
}
if scrollingCollectionView.isHidden == false {
@@ -1253,6 +1258,25 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
])
}
func aniListProgressUpdate(progress: ProgressIndices, newProgress: ProgressIndices) {
if progress.v > newProgress.v || progress.c > newProgress.c {
if let token = aniListToken, let id = metadata.anilistId {
var cProgress = 0
var vProgress = 0
while progress.v > vProgress {
cProgress += metadata.volumes[vProgress].chapters.count
vProgress += 1
}
cProgress += progress.c + 1
vProgress += 1
AniListClient.mutateProgress(
accessToken: token, mediaId: UInt(id),
progress: UInt(cProgress), progressVolumes: UInt(vProgress), completion: { _ in }
)
}
}
}
func changeImage(turn: PageTurn) {
let scaling = UIView.ContentMode.scaleAspectFit
var newProgress = progress
@@ -1260,6 +1284,7 @@ final class ViewController: UIViewController, UIGestureRecognizerDelegate {
if newProgress.v == progress.v, newProgress.c == progress.c, newProgress.i == progress.i {
return
}
aniListProgressUpdate(progress: progress, newProgress: newProgress)
progress = newProgress
updateInfo()
let path = getImagePath(progress)
@@ -2392,15 +2417,25 @@ extension ViewController {
let items = AniListAction.allCases
return items.map { action in
var children: [ComicOptionItem]?
var title = action.rawValue
switch action {
case .updateStatus: children = aniListUpdateStatusItems(indexPath)
case .fetchMetadata: print("")
case .track: print("")
case .track:
if aniListTracking {
title += " (Enabled)"
} else {
title += " (Disabled)"
}
}
return ComicOptionItem(
title: action.rawValue, children: children,
title: title, children: children,
destructive: false, available: { true },
action: { [weak self] in
if action == .track {
self?.aniListTracking.toggle()
self?.saveLocalState()
}
self?.dismiss(animated: false)
}
)
@@ -2558,6 +2593,18 @@ struct SaveMediaListEntry: Decodable {
let status: MediaListStatus
}
struct SaveMediaListProgressEntryData: Decodable {
// swiftlint:disable identifier_name
let SaveMediaListEntry: SaveMediaListProgressEntry
// swiftlint:enable identifier_name
}
struct SaveMediaListProgressEntry: Decodable {
let id: Int
let progress: Int
let progressVolumes: Int
}
enum MediaListStatus: String, Decodable, CaseIterable {
case current = "CURRENT"
case planning = "PLANNING"
@@ -2579,6 +2626,38 @@ enum AniListClient {
case noData
}
static func mutateProgress(
accessToken: String,
mediaId: UInt,
progress: UInt,
progressVolumes: UInt,
completion: @escaping (Result<SaveMediaListProgressEntry, Error>) -> Void
) {
let mutation = """
mutation (
$mediaId: Int = \(mediaId), $progress: Int = \(progress), $progressVolumes: Int = \(progressVolumes)
) {
SaveMediaListEntry(mediaId: $mediaId, progress: $progress, progressVolumes: $progressVolumes) {
id
progress
progressVolumes
}
}
"""
mutate(
accessToken: accessToken, mutation: mutation
) { (result: Result<AniListResponse<SaveMediaListProgressEntryData>, Error>) in
switch result {
case let .success(m):
let status = m.data.SaveMediaListEntry
completion(.success(status))
case let .failure(error):
completion(.failure(error))
print("Error: \(error)")
}
}
}
static func mutateMediaListStatus(
accessToken: String,
mediaId: UInt,