refactor: Change structure of metadata
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
//TODO: Support for bonus chapters
|
||||
//TODO: Anilist support?
|
||||
//TODO: Properly avoid swallowing of input from UICollectionView used for scrolling
|
||||
//TODO: Convert between state for normal and scrolling page turn
|
||||
//TODO: Support reading with scrolling and landscape mode
|
||||
//TODO: Support Cover being zeroth page.
|
||||
//TODO: Support double pages.
|
||||
//TODO: Do file name parsing.
|
||||
//FIXME: Update comicCollectionView when switching between landscape and portrait mode
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
let preloadCount = 2
|
||||
@@ -20,11 +17,17 @@ enum PageTurn {
|
||||
}
|
||||
|
||||
enum ReadProgress: Codable {
|
||||
case leftToRight(chapter: Int, page: Int)
|
||||
case rightToLeft(chapter: Int, page: Int)
|
||||
case leftToRight(volumeIndex: Int, chapterIndex: Int, imageIndex: Int)
|
||||
case rightToLeft(volumeIndex: Int, chapterIndex: Int, imageIndex: Int)
|
||||
case scroll(CGPoint)
|
||||
}
|
||||
|
||||
struct ProgressIndices {
|
||||
var v: Int
|
||||
var c: Int
|
||||
var i: Int
|
||||
}
|
||||
|
||||
enum PageTurnMode: Codable {
|
||||
case leftToRight
|
||||
case rightToLeft
|
||||
@@ -46,11 +49,12 @@ struct LocalState: Codable {
|
||||
var backgroundColor: String = "black"
|
||||
}
|
||||
|
||||
struct Metadata: Decodable {
|
||||
struct Metadata: Codable {
|
||||
var title: String
|
||||
var original_language: String
|
||||
var last_volume: Float
|
||||
var last_chapter: Float
|
||||
var last_volume: MetaValue
|
||||
var last_chapter: MetaValue
|
||||
var chapter_count: Int
|
||||
var publication_demographic: String
|
||||
var status: String
|
||||
var year: Int?
|
||||
@@ -58,14 +62,30 @@ struct Metadata: Decodable {
|
||||
var state: String
|
||||
var created_at: String
|
||||
var updated_at: String
|
||||
var volumes: [VolumeMetadata]
|
||||
}
|
||||
|
||||
struct VolumeMetadata: Codable {
|
||||
var volume: MetaValue
|
||||
var name: String?
|
||||
var chapters: [ChapterMetadata]
|
||||
}
|
||||
|
||||
struct ChapterMetadata: Decodable {
|
||||
var chapter: Float
|
||||
var volume: Float
|
||||
var title: String?
|
||||
var pages: Int
|
||||
struct ChapterMetadata: Codable {
|
||||
var chapter: MetaValue
|
||||
var name: String?
|
||||
var images: [ImageMetadata]
|
||||
}
|
||||
|
||||
struct ImageMetadata: Codable {
|
||||
var doublePage: Bool
|
||||
var fileName: String
|
||||
var firstPage: Int
|
||||
}
|
||||
|
||||
struct MetaValue: Codable {
|
||||
var main: Int
|
||||
var bonus: Int?
|
||||
}
|
||||
|
||||
class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
@@ -84,7 +104,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
var mode = PageTurnMode.leftToRight
|
||||
var metadata: Metadata!
|
||||
var currentPage: Int! = nil
|
||||
var currentChapterIndex: Int! = nil
|
||||
var progress = ProgressIndices.init(v: 0, c: 0, i: 0)
|
||||
var currentPath: URL!
|
||||
|
||||
var changedOrientation = false
|
||||
@@ -161,6 +181,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
setupHomeView()
|
||||
if let name = globalState.comicName {
|
||||
readComic(name: name)
|
||||
} else {
|
||||
print("no comic?")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +219,14 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
}.sorted { $0.path < $1.path }
|
||||
|
||||
for dir in directories {
|
||||
if !fileManager.fileExists(
|
||||
atPath: dir.appendingPathComponent(
|
||||
"metadata.json"
|
||||
).path)
|
||||
{
|
||||
getMetadataFromFileName(path: dir)
|
||||
}
|
||||
|
||||
comics.append(
|
||||
Comic(
|
||||
cover:
|
||||
@@ -252,6 +282,143 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func getMetadataFromFileName(path: URL) {
|
||||
// Beautiful, is it not?
|
||||
let pattern = "c([0-9]+(?:x[0-9]+)?) \\(v([0-9]+)\\) - p([0-9]+(?:-[0-9]+)?)"
|
||||
|
||||
var currentVolume: Int! = nil
|
||||
var currentChapter: (Int, Int?)!
|
||||
|
||||
let outFileName = "metadata.json"
|
||||
|
||||
if fileManager.fileExists(
|
||||
atPath: path.appendingPathComponent(outFileName).absoluteString)
|
||||
{
|
||||
print("skipped metadata file creation")
|
||||
return
|
||||
}
|
||||
|
||||
var metadata = Metadata.init(
|
||||
title: "",
|
||||
original_language: "",
|
||||
last_volume: MetaValue.init(main: 0, bonus: nil),
|
||||
last_chapter: MetaValue.init(main: 0, bonus: nil),
|
||||
chapter_count: 0,
|
||||
publication_demographic: "",
|
||||
status: "",
|
||||
year: nil,
|
||||
content_rating: "",
|
||||
state: "",
|
||||
created_at: "",
|
||||
updated_at: "",
|
||||
volumes: []
|
||||
)
|
||||
do {
|
||||
let regex = try NSRegularExpression(pattern: pattern)
|
||||
let dir = path.appendingPathComponent("images")
|
||||
|
||||
let fileURLs = try fileManager.contentsOfDirectory(
|
||||
at: dir,
|
||||
includingPropertiesForKeys: [.isRegularFileKey],
|
||||
options: [.skipsHiddenFiles]
|
||||
)
|
||||
let fileNames = fileURLs.map { $0.lastPathComponent }.sorted()
|
||||
for fileName in fileNames {
|
||||
let range = NSRange(fileName.startIndex..., in: fileName)
|
||||
if let match = regex.firstMatch(in: fileName, range: range) {
|
||||
let chapterStr = (fileName as NSString).substring(with: match.range(at: 1))
|
||||
let chapterParts = chapterStr.split(separator: "x", maxSplits: 1)
|
||||
let chapter = (
|
||||
Int(chapterParts[0])!, chapterParts.count > 1 ? Int(chapterParts[1])! : nil
|
||||
)
|
||||
|
||||
let volume = Int((fileName as NSString).substring(with: match.range(at: 2)))!
|
||||
|
||||
let pageStr = (fileName as NSString).substring(with: match.range(at: 3))
|
||||
let pageParts = pageStr.split(separator: "-", maxSplits: 1)
|
||||
let (page, doublePage) = (
|
||||
Int(pageParts[0])!, pageParts.count > 1
|
||||
)
|
||||
|
||||
if currentVolume != nil {
|
||||
if volume != currentVolume {
|
||||
metadata.chapter_count += 1
|
||||
assert(volume > currentVolume)
|
||||
metadata.volumes.append(
|
||||
VolumeMetadata.init(
|
||||
volume: MetaValue.init(main: volume, bonus: nil), name: nil,
|
||||
chapters: [
|
||||
ChapterMetadata.init(
|
||||
chapter: MetaValue.init(
|
||||
main: chapter.0, bonus: chapter.1),
|
||||
name: "",
|
||||
images: [
|
||||
ImageMetadata.init(
|
||||
doublePage: doublePage, fileName: fileName,
|
||||
firstPage: page)
|
||||
])
|
||||
]))
|
||||
} else if chapter != currentChapter {
|
||||
metadata.chapter_count += 1
|
||||
if chapter.0 == currentChapter.0 {
|
||||
assert(chapter.1! == currentChapter.1 ?? 1)
|
||||
} else {
|
||||
assert(chapter.0 == currentChapter.0 + 1)
|
||||
}
|
||||
metadata.volumes[metadata.volumes.count - 1].chapters.append(
|
||||
ChapterMetadata.init(
|
||||
chapter: MetaValue.init(main: chapter.0, bonus: chapter.1),
|
||||
name: "",
|
||||
images: [
|
||||
ImageMetadata.init(
|
||||
doublePage: doublePage, fileName: fileName,
|
||||
firstPage: page)
|
||||
]))
|
||||
} else {
|
||||
metadata.volumes[metadata.volumes.count - 1].chapters[
|
||||
metadata.volumes[metadata.volumes.count - 1].chapters.count - 1
|
||||
].images.append(
|
||||
ImageMetadata.init(
|
||||
doublePage: doublePage, fileName: fileName, firstPage: page)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
metadata.chapter_count += 1
|
||||
metadata.volumes.append(
|
||||
VolumeMetadata.init(
|
||||
volume: MetaValue.init(main: volume, bonus: nil), name: nil,
|
||||
chapters: [
|
||||
ChapterMetadata.init(
|
||||
chapter: MetaValue.init(main: chapter.0, bonus: chapter.1),
|
||||
name: "",
|
||||
images: [
|
||||
ImageMetadata.init(
|
||||
doublePage: doublePage, fileName: fileName,
|
||||
firstPage: page)
|
||||
])
|
||||
]))
|
||||
}
|
||||
currentVolume = volume
|
||||
currentChapter = chapter
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
print("failed reading image file names")
|
||||
}
|
||||
|
||||
do {
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
|
||||
encoder.keyEncodingStrategy = .useDefaultKeys
|
||||
try encoder.encode(
|
||||
metadata
|
||||
).write(
|
||||
to: path.appendingPathComponent(outFileName))
|
||||
} catch {
|
||||
print("failed to save metadata")
|
||||
}
|
||||
}
|
||||
|
||||
func saveLocalState() {
|
||||
let color = readerView.backgroundColor ?? .black
|
||||
let screenSize = UIScreen.main.bounds.size
|
||||
@@ -262,9 +429,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
let progress: ReadProgress =
|
||||
switch mode {
|
||||
case .leftToRight:
|
||||
ReadProgress.leftToRight(chapter: currentChapterIndex, page: currentPage)
|
||||
ReadProgress.leftToRight(
|
||||
volumeIndex: progress.v, chapterIndex: progress.c,
|
||||
imageIndex: progress.i)
|
||||
case .rightToLeft:
|
||||
ReadProgress.rightToLeft(chapter: currentChapterIndex, page: currentPage)
|
||||
ReadProgress.rightToLeft(
|
||||
volumeIndex: progress.v, chapterIndex: progress.c,
|
||||
imageIndex: progress.i)
|
||||
case .scroll: ReadProgress.scroll(scrollOffset)
|
||||
}
|
||||
queue.async {
|
||||
@@ -289,13 +460,15 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
).utf8)
|
||||
let local = try JSONDecoder().decode(LocalState.self, from: json)
|
||||
switch local.progress {
|
||||
case .leftToRight(let chapter, let page):
|
||||
currentChapterIndex = chapter
|
||||
currentPage = page
|
||||
case .leftToRight(let volumeIndex, let chapterIndex, let imageIndex):
|
||||
progress.v = volumeIndex
|
||||
progress.c = chapterIndex
|
||||
progress.i = imageIndex
|
||||
mode = .leftToRight
|
||||
case .rightToLeft(let chapter, let page):
|
||||
currentChapterIndex = chapter
|
||||
currentPage = page
|
||||
case .rightToLeft(let volumeIndex, let chapterIndex, let imageIndex):
|
||||
progress.v = volumeIndex
|
||||
progress.c = chapterIndex
|
||||
progress.i = imageIndex
|
||||
mode = .rightToLeft
|
||||
case .scroll(let point):
|
||||
if scrollPos == nil {
|
||||
@@ -306,17 +479,22 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
scrollOffset.y *= (screenSize.width / screenSize.height)
|
||||
}
|
||||
if let indexPath = scrollingCollectionView.indexPathForItem(at: scrollOffset) {
|
||||
let (chapter, page) = chapterAndPages[indexPath.item]
|
||||
currentChapterIndex = chapter
|
||||
currentPage = page
|
||||
var theProgress = ProgressIndices(v: 0, c: 0, i: 0)
|
||||
for _ in 0...indexPath.item {
|
||||
theProgress = getProgressIndicesFromTurn(
|
||||
turn: .next, progress: theProgress)
|
||||
}
|
||||
progress = theProgress
|
||||
}
|
||||
|
||||
}
|
||||
mode = .scroll
|
||||
}
|
||||
readerView.backgroundColor = convertStringToColor(str: local.backgroundColor)
|
||||
} catch let decodingError as DecodingError {
|
||||
print(decodingError.errorDescription!)
|
||||
} catch {
|
||||
print("failed to load local state")
|
||||
print("Unexpected error: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,8 +518,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
|
||||
if let indexPath = scrollingCollectionView.indexPathForItem(at: centerPoint) {
|
||||
let (chapter, page) = chapterAndPages[indexPath.item]
|
||||
currentChapterIndex = chapter
|
||||
currentPage = page
|
||||
progress.c = chapter
|
||||
progress.i = page
|
||||
}
|
||||
if scrollingCollectionView.isHidden == false {
|
||||
saveLocalState()
|
||||
@@ -378,6 +556,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
if let path = getPathFromComicName(name: name) {
|
||||
currentPath = path
|
||||
|
||||
metadata = getMetadata(path: path)!
|
||||
|
||||
globalState.comicName = metadata.title
|
||||
@@ -387,10 +566,12 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
scrollingCollectionView.isHidden = true
|
||||
leftView.isHidden = false
|
||||
rightView.isHidden = false
|
||||
setImages(path: path, metadata: metadata)
|
||||
setImages(path: path)
|
||||
} else {
|
||||
setupScrolling()
|
||||
}
|
||||
} else {
|
||||
print("path not found")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,40 +579,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
leftView.isHidden = true
|
||||
rightView.isHidden = true
|
||||
scrollingCollectionView.isHidden = false
|
||||
pagesAvailable = countFiles()
|
||||
var index = 0
|
||||
var (chapter, page) = (1, 1)
|
||||
chapterAndPages = Array(repeating: (0, 0), count: pagesAvailable + 1)
|
||||
chapterAndPages[index] = (chapter, page)
|
||||
while index < pagesAvailable {
|
||||
index += 1
|
||||
(chapter, page) = getChapterAndPageFromTurn(
|
||||
chapter: chapter, page: page, turn: .next)
|
||||
chapterAndPages[index] = (chapter, page)
|
||||
}
|
||||
|
||||
sizeList = Array(repeating: CGSize(), count: pagesAvailable)
|
||||
let binPath = currentPath.appendingPathComponent("size.bin")
|
||||
let decoder = PropertyListDecoder()
|
||||
do {
|
||||
let data = try Data(contentsOf: binPath)
|
||||
sizeList = try decoder.decode([CGSize].self, from: data)
|
||||
} catch {
|
||||
print("Failed to read data:", error)
|
||||
}
|
||||
|
||||
scrollingCollectionView.reloadData()
|
||||
DispatchQueue.main.async {
|
||||
let encoder = PropertyListEncoder()
|
||||
encoder.outputFormat = .binary
|
||||
do {
|
||||
let data = try encoder.encode(self.sizeList)
|
||||
try data.write(to: binPath)
|
||||
} catch {
|
||||
print("Encoding or writing failed:", error)
|
||||
}
|
||||
self.updateInfo()
|
||||
}
|
||||
// TODO: Fix scrolling again
|
||||
}
|
||||
|
||||
func countFiles() -> Int {
|
||||
@@ -752,11 +900,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
setupScrolling()
|
||||
} else {
|
||||
imageLoader.loadImage(
|
||||
at: getImagePath(
|
||||
chapter: metadata.chapters[currentChapterIndex].chapter,
|
||||
volume: metadata.chapters[currentChapterIndex].volume,
|
||||
page: currentPage,
|
||||
path: currentPath),
|
||||
at: getImagePath(progress: progress),
|
||||
scaling: .scaleAspectFit
|
||||
) { [weak self] image in
|
||||
self?.imageView.image = image
|
||||
@@ -887,15 +1031,14 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
|
||||
func changeImage(turn: PageTurn) {
|
||||
let scaling = UIView.ContentMode.scaleAspectFit
|
||||
var (chapter, page) = getChapterAndPageFromTurn(
|
||||
chapter: currentChapterIndex, page: currentPage, turn: turn)
|
||||
if (chapter, page) == (currentChapterIndex, currentPage) { return }
|
||||
var vol = metadata.chapters[chapter].volume
|
||||
currentPage = page
|
||||
currentChapterIndex = chapter
|
||||
if let path = getImagePath(
|
||||
chapter: metadata.chapters[chapter].chapter, volume: vol, page: page, path: currentPath)
|
||||
var newProgress = progress
|
||||
newProgress = getProgressIndicesFromTurn(turn: turn, progress: newProgress)
|
||||
if newProgress.v == progress.v && newProgress.c == progress.c && newProgress.i == progress.i
|
||||
{
|
||||
return
|
||||
}
|
||||
progress = newProgress
|
||||
if let path = getImagePath(progress: progress) {
|
||||
imageLoader.loadImage(at: path, scaling: scaling) { [weak self] image in
|
||||
self?.imageView.image = image
|
||||
self?.updateInfo()
|
||||
@@ -905,13 +1048,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
for _ in 0...preloadCount {
|
||||
(chapter, page) = getChapterAndPageFromTurn(
|
||||
chapter: chapter, page: page, turn: .next)
|
||||
vol = metadata.chapters[chapter].volume
|
||||
if let path = getImagePath(
|
||||
chapter: metadata.chapters[chapter].chapter, volume: vol, page: page,
|
||||
path: currentPath)
|
||||
{
|
||||
newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
|
||||
if let path = getImagePath(progress: newProgress) {
|
||||
imageLoader.preloadImage(at: path, scaling: scaling)
|
||||
} else {
|
||||
print("could not preload image")
|
||||
@@ -921,35 +1059,64 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
saveLocalState()
|
||||
}
|
||||
|
||||
func metaValueToString(m: MetaValue) -> String {
|
||||
if let bonus = m.bonus {
|
||||
String(m.main) + "." + String(bonus)
|
||||
} else {
|
||||
String(m.main)
|
||||
}
|
||||
}
|
||||
|
||||
func updateInfo() {
|
||||
if metadata == nil { return }
|
||||
if currentChapterIndex == nil || currentPage == nil { return }
|
||||
|
||||
var text = "\(metadata.title)\n"
|
||||
|
||||
if let chapterTitle = metadata.chapters[currentChapterIndex].title {
|
||||
if let chapterTitle = metadata.volumes[progress.v].chapters[progress.c].name {
|
||||
text +=
|
||||
"\(chapterTitle)\n"
|
||||
}
|
||||
let chapterValue = metadata.chapters[currentChapterIndex].chapter
|
||||
let chapterString =
|
||||
chapterValue.truncatingRemainder(dividingBy: 1) == 0
|
||||
? String(Int(chapterValue))
|
||||
: String(chapterValue)
|
||||
let chapterValue = metadata.volumes[progress.v].chapters[progress.c].chapter
|
||||
let chapterString = metaValueToString(m: chapterValue)
|
||||
|
||||
let lastChapterValue = metadata.last_chapter
|
||||
let lastChapterString = metaValueToString(m: lastChapterValue)
|
||||
|
||||
let volumeValue = metadata.volumes[progress.v].volume
|
||||
let volumeString = metaValueToString(m: volumeValue)
|
||||
|
||||
let lastVolumeValue = metadata.last_volume
|
||||
let lastVolumeString = metaValueToString(m: lastVolumeValue)
|
||||
|
||||
let lastVolumeIndex = metadata.volumes.count - 1
|
||||
let lastChapterIndex = metadata.volumes[lastVolumeIndex].chapters.count - 1
|
||||
let lastImageIndex =
|
||||
metadata.volumes[lastVolumeIndex].chapters[lastChapterIndex].images.count - 1
|
||||
|
||||
let lastImage = metadata.volumes[lastVolumeIndex].chapters[lastChapterIndex].images[
|
||||
lastImageIndex]
|
||||
let lastPageString =
|
||||
if lastImage.doublePage {
|
||||
String(lastImage.firstPage + 1)
|
||||
} else {
|
||||
String(lastImage.firstPage)
|
||||
}
|
||||
|
||||
let currentImage = metadata.volumes[progress.v].chapters[progress.c].images[progress.i]
|
||||
let pageString =
|
||||
if currentImage.doublePage {
|
||||
String(currentImage.firstPage) + "-" + String(currentImage.firstPage + 1)
|
||||
} else {
|
||||
String(currentImage.firstPage)
|
||||
}
|
||||
|
||||
text +=
|
||||
"""
|
||||
Volume \(Int(metadata.chapters[currentChapterIndex].volume)) of \(Int(metadata.last_volume))
|
||||
Chapter \(chapterString) of \(Int(metadata.last_chapter))
|
||||
Page \(currentPage!) of \(metadata.chapters[currentChapterIndex].pages)
|
||||
Volume \(volumeString) of \(lastVolumeString)
|
||||
Chapter \(chapterString) of \(lastChapterString)
|
||||
Page \(pageString) of \(lastPageString)
|
||||
"""
|
||||
if let size = imageLoader.size[
|
||||
getImagePath(
|
||||
chapter: metadata.chapters[currentChapterIndex].chapter,
|
||||
volume: metadata.chapters[currentChapterIndex].volume,
|
||||
page: currentPage,
|
||||
path: currentPath
|
||||
).path]
|
||||
{
|
||||
if let size = imageLoader.size[getImagePath(progress: progress).path] {
|
||||
text += "\nImage size: \(Int(size.width))x\(Int(size.height))"
|
||||
}
|
||||
info.text = text
|
||||
@@ -968,43 +1135,47 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func getImagePath(chapter: Float, volume: Float, page: Int, path: URL) -> URL! {
|
||||
let modernPath = path.appendingPathComponent(String(format: "volume_%04d", Int(volume)))
|
||||
.appendingPathComponent(
|
||||
String(format: "chapter_\(formatNumber(chapter))_page_%04d.png", page))
|
||||
print("trying to get path \(modernPath)")
|
||||
func getImagePath(progress: ProgressIndices) -> URL! {
|
||||
let (v, c, i) = (progress.v, progress.c, progress.i)
|
||||
let modernPath = currentPath.appendingPathComponent("images").appendingPathComponent(
|
||||
metadata.volumes[v].chapters[c].images[i].fileName)
|
||||
// print("trying to get path \(modernPath)")
|
||||
// if fileManager.fileExists(atPath: modernPath.path) {
|
||||
return modernPath
|
||||
// }
|
||||
// return nil
|
||||
}
|
||||
|
||||
func getChapterAndPageFromTurn(chapter: Int, page: Int, turn: PageTurn) -> (Int, Int) {
|
||||
func getProgressIndicesFromTurn(turn: PageTurn, progress: ProgressIndices) -> ProgressIndices {
|
||||
let (v, c, i) = (progress.v, progress.c, progress.i)
|
||||
switch turn {
|
||||
case .next:
|
||||
if metadata.chapters.count >= chapter + 1 {
|
||||
if page + 1 > metadata.chapters[chapter].pages {
|
||||
return (chapter + 1, 1)
|
||||
} else {
|
||||
return (chapter, page + 1)
|
||||
}
|
||||
} else {
|
||||
return (chapter, min(metadata.chapters[chapter].pages, page + 1))
|
||||
if metadata.volumes[v].chapters[c].images.count > i + 1 {
|
||||
return ProgressIndices.init(v: v, c: c, i: i + 1)
|
||||
}
|
||||
if metadata.volumes[v].chapters.count > c + 1 {
|
||||
return ProgressIndices.init(v: v, c: c + 1, i: 0)
|
||||
}
|
||||
if metadata.volumes.count > v + 1 {
|
||||
return ProgressIndices.init(v: v + 1, c: 0, i: 0)
|
||||
}
|
||||
case .previous:
|
||||
if page < 2 {
|
||||
if chapter > 0 {
|
||||
return (
|
||||
chapter - 1,
|
||||
metadata.chapters[chapter - 1].pages
|
||||
)
|
||||
} else {
|
||||
return (chapter, page)
|
||||
}
|
||||
} else {
|
||||
return (chapter, max(1, page - 1))
|
||||
if i > 0 {
|
||||
return ProgressIndices.init(v: v, c: c, i: i - 1)
|
||||
}
|
||||
if c > 0 {
|
||||
return ProgressIndices.init(
|
||||
v: v, c: c - 1, i: metadata.volumes[v].chapters[c - 1].images.count - 1)
|
||||
}
|
||||
if v > 0 {
|
||||
return ProgressIndices.init(
|
||||
v: v - 1, c: metadata.volumes[v - 1].chapters.count - 1,
|
||||
i: metadata.volumes[v - 1].chapters[
|
||||
metadata.volumes[v - 1].chapters.count - 1
|
||||
].images.count - 1)
|
||||
}
|
||||
}
|
||||
return ProgressIndices.init(v: v, c: c, i: i)
|
||||
}
|
||||
|
||||
func getMetadata(path: URL) -> Metadata? {
|
||||
@@ -1015,81 +1186,32 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
let metadata = try JSONDecoder().decode(Metadata.self, from: json)
|
||||
return metadata
|
||||
|
||||
} catch let decodingError as DecodingError {
|
||||
print(decodingError.errorDescription!)
|
||||
} catch {
|
||||
print("Error reading stuff")
|
||||
print("Unexpected error: \(error)")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setImages(path: URL, metadata: Metadata) {
|
||||
func setImages(path: URL) {
|
||||
let scaling: UIView.ContentMode =
|
||||
if mode == .scroll {
|
||||
.scaleAspectFill
|
||||
} else { .scaleAspectFit }
|
||||
var directories: [URL] = []
|
||||
if currentPage != nil && currentChapterIndex != nil {
|
||||
var vol = metadata.chapters[currentChapterIndex].volume
|
||||
imageLoader.loadImage(
|
||||
at: getImagePath(
|
||||
chapter: metadata.chapters[currentChapterIndex].chapter, volume: vol,
|
||||
page: currentPage, path: currentPath
|
||||
),
|
||||
scaling: scaling
|
||||
) { [weak self] image in
|
||||
self?.imageView.image = image
|
||||
self?.updateInfo()
|
||||
}
|
||||
|
||||
var (chapter, page) = getChapterAndPageFromTurn(
|
||||
chapter: currentChapterIndex, page: currentPage, turn: .next)
|
||||
for _ in 0...preloadCount {
|
||||
vol = metadata.chapters[chapter].volume
|
||||
if let path = getImagePath(
|
||||
chapter: metadata.chapters[chapter].chapter, volume: vol, page: page,
|
||||
path: currentPath)
|
||||
{
|
||||
imageLoader.preloadImage(at: path, scaling: scaling)
|
||||
} else {
|
||||
print("could not preload image")
|
||||
}
|
||||
(chapter, page) = getChapterAndPageFromTurn(
|
||||
chapter: chapter, page: page, turn: .next)
|
||||
}
|
||||
|
||||
return
|
||||
imageLoader.loadImage(
|
||||
at:
|
||||
getImagePath(progress: progress),
|
||||
scaling: scaling
|
||||
) { [weak self] image in
|
||||
self?.imageView.image = image
|
||||
self?.updateInfo()
|
||||
}
|
||||
|
||||
do {
|
||||
let contents = try fileManager.contentsOfDirectory(
|
||||
at: path,
|
||||
includingPropertiesForKeys: [.isRegularFileKey],
|
||||
options: [.skipsHiddenFiles]
|
||||
)
|
||||
|
||||
directories = contents.filter { url in
|
||||
var isDirectory: ObjCBool = false
|
||||
return fileManager.fileExists(atPath: url.path, isDirectory: &isDirectory)
|
||||
&& isDirectory.boolValue
|
||||
}.sorted { $0.path < $1.path }
|
||||
let dir: URL = directories[0]
|
||||
let ps: [String] = try fileManager.contentsOfDirectory(atPath: dir.path).sorted()
|
||||
let current = dir.appendingPathComponent(ps[0])
|
||||
imageView.image = UIImage(contentsOfFile: current.path)
|
||||
|
||||
let path_meta = current.lastPathComponent.components(separatedBy: "_")
|
||||
assert(path_meta[0] == "chapter")
|
||||
currentChapterIndex = Int(path_meta[1])! - 1
|
||||
if path_meta[2] == "page" {
|
||||
currentPage = Int(path_meta[3].components(separatedBy: ".")[0])
|
||||
if currentPage == nil {
|
||||
print("unable to set currentPage")
|
||||
assert(false)
|
||||
}
|
||||
}
|
||||
saveLocalState()
|
||||
updateInfo()
|
||||
} catch {
|
||||
print("failed to set images")
|
||||
var newProgress = progress
|
||||
for _ in 0...preloadCount {
|
||||
newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
|
||||
imageLoader.preloadImage(at: getImagePath(progress: newProgress), scaling: scaling)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1108,11 +1230,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
if mode != .scroll {
|
||||
imageLoader.loadImage(
|
||||
at: getImagePath(
|
||||
chapter: metadata.chapters[currentChapterIndex].chapter,
|
||||
volume: metadata.chapters[currentChapterIndex].volume,
|
||||
page: currentPage,
|
||||
path: currentPath),
|
||||
at: getImagePath(progress: progress),
|
||||
scaling: .scaleAspectFit
|
||||
) { image in
|
||||
self.imageView.image = image
|
||||
@@ -1175,7 +1293,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
|
||||
cell.imageView.image = comics[indexPath.item].cover
|
||||
return cell
|
||||
} else if collectionView == scrollingCollectionView {
|
||||
let scaling = UIView.ContentMode.scaleAspectFill
|
||||
// let scaling = UIView.ContentMode.scaleAspectFill
|
||||
let cell =
|
||||
collectionView.dequeueReusableCell(
|
||||
withReuseIdentifier: "ScrollingImageCell", for: indexPath)
|
||||
@@ -1183,29 +1301,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
|
||||
if metadata == nil {
|
||||
return cell
|
||||
}
|
||||
var (chapterIndex, page) = chapterAndPages[indexPath.item]
|
||||
if let url = getImagePath(
|
||||
chapter: metadata.chapters[chapterIndex].chapter,
|
||||
volume: metadata.chapters[chapterIndex].volume,
|
||||
page: page, path: currentPath)
|
||||
{
|
||||
imageLoader.loadImage(at: url, scaling: scaling) { image in
|
||||
cell.imageView.image = image
|
||||
}
|
||||
for _ in 0...preloadCount {
|
||||
(chapterIndex, page) = getChapterAndPageFromTurn(
|
||||
chapter: chapterIndex, page: page, turn: .next)
|
||||
if let url = getImagePath(
|
||||
chapter: metadata.chapters[chapterIndex].chapter,
|
||||
volume: metadata.chapters[chapterIndex].volume,
|
||||
page: page, path: currentPath)
|
||||
{
|
||||
imageLoader.preloadImage(at: url, scaling: scaling)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Fix scrolling again
|
||||
return cell
|
||||
} else {
|
||||
assert(false)
|
||||
@@ -1233,28 +1329,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
|
||||
if metadata == nil {
|
||||
return CGSize()
|
||||
}
|
||||
if sizeList[indexPath.item] != CGSize(width: 0, height: 0) {
|
||||
return CGSize(
|
||||
width: readerView.bounds.width,
|
||||
height: sizeList[indexPath.item].height * readerView.bounds.width
|
||||
/ sizeList[indexPath.item].width)
|
||||
}
|
||||
let (chapter, page) = chapterAndPages[indexPath.item]
|
||||
if let imagePath = getImagePath(
|
||||
chapter: metadata.chapters[chapter].chapter,
|
||||
volume: metadata.chapters[chapter].volume,
|
||||
page: page, path: currentPath),
|
||||
let imageSource = CGImageSourceCreateWithURL(imagePath as CFURL, nil),
|
||||
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)
|
||||
as? [CFString: Any],
|
||||
let height = imageProperties[kCGImagePropertyPixelHeight] as? CGFloat,
|
||||
let width = imageProperties[kCGImagePropertyPixelWidth] as? CGFloat
|
||||
{
|
||||
sizeList[indexPath.item] = CGSize(width: width, height: height)
|
||||
return CGSize(
|
||||
width: readerView.bounds.width, height: height * readerView.bounds.width / width
|
||||
)
|
||||
}
|
||||
// TODO: Fix scrolling again
|
||||
return CGSize()
|
||||
} else {
|
||||
assert(false)
|
||||
|
||||
Reference in New Issue
Block a user