refactor: Change structure of metadata

This commit is contained in:
2026-01-03 16:32:50 +01:00
parent 06c6539e26
commit 3eacdaf7da
+317 -242
View File
@@ -1,13 +1,10 @@
//TODO: Support for bonus chapters
//TODO: Anilist support? //TODO: Anilist support?
//TODO: Properly avoid swallowing of input from UICollectionView used for scrolling //TODO: Properly avoid swallowing of input from UICollectionView used for scrolling
//TODO: Convert between state for normal and scrolling page turn //TODO: Convert between state for normal and scrolling page turn
//TODO: Support reading with scrolling and landscape mode //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 //FIXME: Update comicCollectionView when switching between landscape and portrait mode
import Foundation
import UIKit import UIKit
let preloadCount = 2 let preloadCount = 2
@@ -20,11 +17,17 @@ enum PageTurn {
} }
enum ReadProgress: Codable { enum ReadProgress: Codable {
case leftToRight(chapter: Int, page: Int) case leftToRight(volumeIndex: Int, chapterIndex: Int, imageIndex: Int)
case rightToLeft(chapter: Int, page: Int) case rightToLeft(volumeIndex: Int, chapterIndex: Int, imageIndex: Int)
case scroll(CGPoint) case scroll(CGPoint)
} }
struct ProgressIndices {
var v: Int
var c: Int
var i: Int
}
enum PageTurnMode: Codable { enum PageTurnMode: Codable {
case leftToRight case leftToRight
case rightToLeft case rightToLeft
@@ -46,11 +49,12 @@ struct LocalState: Codable {
var backgroundColor: String = "black" var backgroundColor: String = "black"
} }
struct Metadata: Decodable { struct Metadata: Codable {
var title: String var title: String
var original_language: String var original_language: String
var last_volume: Float var last_volume: MetaValue
var last_chapter: Float var last_chapter: MetaValue
var chapter_count: Int
var publication_demographic: String var publication_demographic: String
var status: String var status: String
var year: Int? var year: Int?
@@ -58,14 +62,30 @@ struct Metadata: Decodable {
var state: String var state: String
var created_at: String var created_at: String
var updated_at: String var updated_at: String
var volumes: [VolumeMetadata]
}
struct VolumeMetadata: Codable {
var volume: MetaValue
var name: String?
var chapters: [ChapterMetadata] var chapters: [ChapterMetadata]
} }
struct ChapterMetadata: Decodable { struct ChapterMetadata: Codable {
var chapter: Float var chapter: MetaValue
var volume: Float var name: String?
var title: String? var images: [ImageMetadata]
var pages: Int }
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 { class ViewController: UIViewController, UIGestureRecognizerDelegate {
@@ -84,7 +104,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var mode = PageTurnMode.leftToRight var mode = PageTurnMode.leftToRight
var metadata: Metadata! var metadata: Metadata!
var currentPage: Int! = nil var currentPage: Int! = nil
var currentChapterIndex: Int! = nil var progress = ProgressIndices.init(v: 0, c: 0, i: 0)
var currentPath: URL! var currentPath: URL!
var changedOrientation = false var changedOrientation = false
@@ -161,6 +181,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
setupHomeView() setupHomeView()
if let name = globalState.comicName { if let name = globalState.comicName {
readComic(name: name) readComic(name: name)
} else {
print("no comic?")
} }
} }
@@ -197,6 +219,14 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
}.sorted { $0.path < $1.path } }.sorted { $0.path < $1.path }
for dir in directories { for dir in directories {
if !fileManager.fileExists(
atPath: dir.appendingPathComponent(
"metadata.json"
).path)
{
getMetadataFromFileName(path: dir)
}
comics.append( comics.append(
Comic( Comic(
cover: 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() { func saveLocalState() {
let color = readerView.backgroundColor ?? .black let color = readerView.backgroundColor ?? .black
let screenSize = UIScreen.main.bounds.size let screenSize = UIScreen.main.bounds.size
@@ -262,9 +429,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
let progress: ReadProgress = let progress: ReadProgress =
switch mode { switch mode {
case .leftToRight: case .leftToRight:
ReadProgress.leftToRight(chapter: currentChapterIndex, page: currentPage) ReadProgress.leftToRight(
volumeIndex: progress.v, chapterIndex: progress.c,
imageIndex: progress.i)
case .rightToLeft: case .rightToLeft:
ReadProgress.rightToLeft(chapter: currentChapterIndex, page: currentPage) ReadProgress.rightToLeft(
volumeIndex: progress.v, chapterIndex: progress.c,
imageIndex: progress.i)
case .scroll: ReadProgress.scroll(scrollOffset) case .scroll: ReadProgress.scroll(scrollOffset)
} }
queue.async { queue.async {
@@ -289,13 +460,15 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
).utf8) ).utf8)
let local = try JSONDecoder().decode(LocalState.self, from: json) let local = try JSONDecoder().decode(LocalState.self, from: json)
switch local.progress { switch local.progress {
case .leftToRight(let chapter, let page): case .leftToRight(let volumeIndex, let chapterIndex, let imageIndex):
currentChapterIndex = chapter progress.v = volumeIndex
currentPage = page progress.c = chapterIndex
progress.i = imageIndex
mode = .leftToRight mode = .leftToRight
case .rightToLeft(let chapter, let page): case .rightToLeft(let volumeIndex, let chapterIndex, let imageIndex):
currentChapterIndex = chapter progress.v = volumeIndex
currentPage = page progress.c = chapterIndex
progress.i = imageIndex
mode = .rightToLeft mode = .rightToLeft
case .scroll(let point): case .scroll(let point):
if scrollPos == nil { if scrollPos == nil {
@@ -306,17 +479,22 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
scrollOffset.y *= (screenSize.width / screenSize.height) scrollOffset.y *= (screenSize.width / screenSize.height)
} }
if let indexPath = scrollingCollectionView.indexPathForItem(at: scrollOffset) { if let indexPath = scrollingCollectionView.indexPathForItem(at: scrollOffset) {
let (chapter, page) = chapterAndPages[indexPath.item] var theProgress = ProgressIndices(v: 0, c: 0, i: 0)
currentChapterIndex = chapter for _ in 0...indexPath.item {
currentPage = page theProgress = getProgressIndicesFromTurn(
turn: .next, progress: theProgress)
}
progress = theProgress
} }
} }
mode = .scroll mode = .scroll
} }
readerView.backgroundColor = convertStringToColor(str: local.backgroundColor) readerView.backgroundColor = convertStringToColor(str: local.backgroundColor)
} catch let decodingError as DecodingError {
print(decodingError.errorDescription!)
} catch { } 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) { if let indexPath = scrollingCollectionView.indexPathForItem(at: centerPoint) {
let (chapter, page) = chapterAndPages[indexPath.item] let (chapter, page) = chapterAndPages[indexPath.item]
currentChapterIndex = chapter progress.c = chapter
currentPage = page progress.i = page
} }
if scrollingCollectionView.isHidden == false { if scrollingCollectionView.isHidden == false {
saveLocalState() saveLocalState()
@@ -378,6 +556,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
setNeedsStatusBarAppearanceUpdate() setNeedsStatusBarAppearanceUpdate()
if let path = getPathFromComicName(name: name) { if let path = getPathFromComicName(name: name) {
currentPath = path currentPath = path
metadata = getMetadata(path: path)! metadata = getMetadata(path: path)!
globalState.comicName = metadata.title globalState.comicName = metadata.title
@@ -387,10 +566,12 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
scrollingCollectionView.isHidden = true scrollingCollectionView.isHidden = true
leftView.isHidden = false leftView.isHidden = false
rightView.isHidden = false rightView.isHidden = false
setImages(path: path, metadata: metadata) setImages(path: path)
} else { } else {
setupScrolling() setupScrolling()
} }
} else {
print("path not found")
} }
} }
@@ -398,40 +579,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
leftView.isHidden = true leftView.isHidden = true
rightView.isHidden = true rightView.isHidden = true
scrollingCollectionView.isHidden = false scrollingCollectionView.isHidden = false
pagesAvailable = countFiles() // TODO: Fix scrolling again
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()
}
} }
func countFiles() -> Int { func countFiles() -> Int {
@@ -752,11 +900,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
setupScrolling() setupScrolling()
} else { } else {
imageLoader.loadImage( imageLoader.loadImage(
at: getImagePath( at: getImagePath(progress: progress),
chapter: metadata.chapters[currentChapterIndex].chapter,
volume: metadata.chapters[currentChapterIndex].volume,
page: currentPage,
path: currentPath),
scaling: .scaleAspectFit scaling: .scaleAspectFit
) { [weak self] image in ) { [weak self] image in
self?.imageView.image = image self?.imageView.image = image
@@ -887,15 +1031,14 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
func changeImage(turn: PageTurn) { func changeImage(turn: PageTurn) {
let scaling = UIView.ContentMode.scaleAspectFit let scaling = UIView.ContentMode.scaleAspectFit
var (chapter, page) = getChapterAndPageFromTurn( var newProgress = progress
chapter: currentChapterIndex, page: currentPage, turn: turn) newProgress = getProgressIndicesFromTurn(turn: turn, progress: newProgress)
if (chapter, page) == (currentChapterIndex, currentPage) { return } if newProgress.v == progress.v && newProgress.c == progress.c && newProgress.i == progress.i
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)
{ {
return
}
progress = newProgress
if let path = getImagePath(progress: progress) {
imageLoader.loadImage(at: path, scaling: scaling) { [weak self] image in imageLoader.loadImage(at: path, scaling: scaling) { [weak self] image in
self?.imageView.image = image self?.imageView.image = image
self?.updateInfo() self?.updateInfo()
@@ -905,13 +1048,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
} }
for _ in 0...preloadCount { for _ in 0...preloadCount {
(chapter, page) = getChapterAndPageFromTurn( newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
chapter: chapter, page: page, turn: .next) if let path = getImagePath(progress: newProgress) {
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) imageLoader.preloadImage(at: path, scaling: scaling)
} else { } else {
print("could not preload image") print("could not preload image")
@@ -921,35 +1059,64 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
saveLocalState() saveLocalState()
} }
func metaValueToString(m: MetaValue) -> String {
if let bonus = m.bonus {
String(m.main) + "." + String(bonus)
} else {
String(m.main)
}
}
func updateInfo() { func updateInfo() {
if metadata == nil { return } if metadata == nil { return }
if currentChapterIndex == nil || currentPage == nil { return }
var text = "\(metadata.title)\n" var text = "\(metadata.title)\n"
if let chapterTitle = metadata.chapters[currentChapterIndex].title { if let chapterTitle = metadata.volumes[progress.v].chapters[progress.c].name {
text += text +=
"\(chapterTitle)\n" "\(chapterTitle)\n"
} }
let chapterValue = metadata.chapters[currentChapterIndex].chapter let chapterValue = metadata.volumes[progress.v].chapters[progress.c].chapter
let chapterString = let chapterString = metaValueToString(m: chapterValue)
chapterValue.truncatingRemainder(dividingBy: 1) == 0
? String(Int(chapterValue)) let lastChapterValue = metadata.last_chapter
: String(chapterValue) 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 += text +=
""" """
Volume \(Int(metadata.chapters[currentChapterIndex].volume)) of \(Int(metadata.last_volume)) Volume \(volumeString) of \(lastVolumeString)
Chapter \(chapterString) of \(Int(metadata.last_chapter)) Chapter \(chapterString) of \(lastChapterString)
Page \(currentPage!) of \(metadata.chapters[currentChapterIndex].pages) Page \(pageString) of \(lastPageString)
""" """
if let size = imageLoader.size[ if let size = imageLoader.size[getImagePath(progress: progress).path] {
getImagePath(
chapter: metadata.chapters[currentChapterIndex].chapter,
volume: metadata.chapters[currentChapterIndex].volume,
page: currentPage,
path: currentPath
).path]
{
text += "\nImage size: \(Int(size.width))x\(Int(size.height))" text += "\nImage size: \(Int(size.width))x\(Int(size.height))"
} }
info.text = text info.text = text
@@ -968,43 +1135,47 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
} }
} }
func getImagePath(chapter: Float, volume: Float, page: Int, path: URL) -> URL! { func getImagePath(progress: ProgressIndices) -> URL! {
let modernPath = path.appendingPathComponent(String(format: "volume_%04d", Int(volume))) let (v, c, i) = (progress.v, progress.c, progress.i)
.appendingPathComponent( let modernPath = currentPath.appendingPathComponent("images").appendingPathComponent(
String(format: "chapter_\(formatNumber(chapter))_page_%04d.png", page)) metadata.volumes[v].chapters[c].images[i].fileName)
print("trying to get path \(modernPath)") // print("trying to get path \(modernPath)")
// if fileManager.fileExists(atPath: modernPath.path) { // if fileManager.fileExists(atPath: modernPath.path) {
return modernPath return modernPath
// } // }
// return nil // 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 { switch turn {
case .next: case .next:
if metadata.chapters.count >= chapter + 1 { if metadata.volumes[v].chapters[c].images.count > i + 1 {
if page + 1 > metadata.chapters[chapter].pages { return ProgressIndices.init(v: v, c: c, i: i + 1)
return (chapter + 1, 1) }
} else { if metadata.volumes[v].chapters.count > c + 1 {
return (chapter, page + 1) return ProgressIndices.init(v: v, c: c + 1, i: 0)
} }
} else { if metadata.volumes.count > v + 1 {
return (chapter, min(metadata.chapters[chapter].pages, page + 1)) return ProgressIndices.init(v: v + 1, c: 0, i: 0)
} }
case .previous: case .previous:
if page < 2 { if i > 0 {
if chapter > 0 { return ProgressIndices.init(v: v, c: c, i: i - 1)
return ( }
chapter - 1, if c > 0 {
metadata.chapters[chapter - 1].pages return ProgressIndices.init(
) v: v, c: c - 1, i: metadata.volumes[v].chapters[c - 1].images.count - 1)
} else { }
return (chapter, page) if v > 0 {
} return ProgressIndices.init(
} else { v: v - 1, c: metadata.volumes[v - 1].chapters.count - 1,
return (chapter, max(1, page - 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? { func getMetadata(path: URL) -> Metadata? {
@@ -1015,81 +1186,32 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
let metadata = try JSONDecoder().decode(Metadata.self, from: json) let metadata = try JSONDecoder().decode(Metadata.self, from: json)
return metadata return metadata
} catch let decodingError as DecodingError {
print(decodingError.errorDescription!)
} catch { } catch {
print("Error reading stuff") print("Unexpected error: \(error)")
} }
return nil return nil
} }
func setImages(path: URL, metadata: Metadata) { func setImages(path: URL) {
let scaling: UIView.ContentMode = let scaling: UIView.ContentMode =
if mode == .scroll { if mode == .scroll {
.scaleAspectFill .scaleAspectFill
} else { .scaleAspectFit } } else { .scaleAspectFit }
var directories: [URL] = [] imageLoader.loadImage(
if currentPage != nil && currentChapterIndex != nil { at:
var vol = metadata.chapters[currentChapterIndex].volume getImagePath(progress: progress),
imageLoader.loadImage( scaling: scaling
at: getImagePath( ) { [weak self] image in
chapter: metadata.chapters[currentChapterIndex].chapter, volume: vol, self?.imageView.image = image
page: currentPage, path: currentPath self?.updateInfo()
),
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
} }
do { var newProgress = progress
let contents = try fileManager.contentsOfDirectory( for _ in 0...preloadCount {
at: path, newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
includingPropertiesForKeys: [.isRegularFileKey], imageLoader.preloadImage(at: getImagePath(progress: newProgress), scaling: scaling)
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")
} }
} }
@@ -1108,11 +1230,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
super.viewWillTransition(to: size, with: coordinator) super.viewWillTransition(to: size, with: coordinator)
if mode != .scroll { if mode != .scroll {
imageLoader.loadImage( imageLoader.loadImage(
at: getImagePath( at: getImagePath(progress: progress),
chapter: metadata.chapters[currentChapterIndex].chapter,
volume: metadata.chapters[currentChapterIndex].volume,
page: currentPage,
path: currentPath),
scaling: .scaleAspectFit scaling: .scaleAspectFit
) { image in ) { image in
self.imageView.image = image self.imageView.image = image
@@ -1175,7 +1293,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
cell.imageView.image = comics[indexPath.item].cover cell.imageView.image = comics[indexPath.item].cover
return cell return cell
} else if collectionView == scrollingCollectionView { } else if collectionView == scrollingCollectionView {
let scaling = UIView.ContentMode.scaleAspectFill // let scaling = UIView.ContentMode.scaleAspectFill
let cell = let cell =
collectionView.dequeueReusableCell( collectionView.dequeueReusableCell(
withReuseIdentifier: "ScrollingImageCell", for: indexPath) withReuseIdentifier: "ScrollingImageCell", for: indexPath)
@@ -1183,29 +1301,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
if metadata == nil { if metadata == nil {
return cell return cell
} }
var (chapterIndex, page) = chapterAndPages[indexPath.item] // TODO: Fix scrolling again
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
}
}
}
return cell return cell
} else { } else {
assert(false) assert(false)
@@ -1233,28 +1329,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
if metadata == nil { if metadata == nil {
return CGSize() return CGSize()
} }
if sizeList[indexPath.item] != CGSize(width: 0, height: 0) { // TODO: Fix scrolling again
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
)
}
return CGSize() return CGSize()
} else { } else {
assert(false) assert(false)