This commit is contained in:
2026-02-27 02:32:19 +01:00
parent 86b1752e91
commit aa5ba0f79e
3 changed files with 150 additions and 122 deletions

View File

@@ -192,6 +192,7 @@
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -245,6 +246,7 @@
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;

View File

@@ -2,12 +2,11 @@ import UIKit
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? var window: UIWindow?
func application( func application(
_ application: UIApplication, _: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool { ) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds) window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = ViewController() window?.rootViewController = ViewController()

View File

@@ -1,8 +1,8 @@
//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
//FIXME: Update comicCollectionView when switching between landscape and portrait mode // FIXME: Update comicCollectionView when switching between landscape and portrait mode
import Foundation import Foundation
import UIKit import UIKit
@@ -103,8 +103,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var imageView = UIImageView() var imageView = UIImageView()
var mode = PageTurnMode.leftToRight var mode = PageTurnMode.leftToRight
var metadata: Metadata! var metadata: Metadata!
var currentPage: Int! = nil var currentPage: Int!
var progress = ProgressIndices.init(v: 0, c: 0, i: 0) var progress = ProgressIndices(v: 0, c: 0, i: 0)
var currentPath: URL! var currentPath: URL!
var changedOrientation = false var changedOrientation = false
@@ -136,7 +136,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var comics: [Comic] = [] var comics: [Comic] = []
@IBOutlet var comicCollectionView: UICollectionView! @IBOutlet var comicCollectionView: UICollectionView!
let imageLoader = ImageLoader.init() let imageLoader = ImageLoader()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@@ -198,7 +198,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
comicCollectionView.delegate = self comicCollectionView.delegate = self
comicCollectionView.backgroundColor = .white comicCollectionView.backgroundColor = .white
comicCollectionView.register( comicCollectionView.register(
ComicImageCell.self, forCellWithReuseIdentifier: "ComicImageCell") ComicImageCell.self, forCellWithReuseIdentifier: "ComicImageCell"
)
homeView.addSubview(comicCollectionView) homeView.addSubview(comicCollectionView)
} }
@@ -232,13 +233,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
metadata = try JSONDecoder().decode( metadata = try JSONDecoder().decode(
Metadata.self, Metadata.self,
from: from:
Data( Data(
try String( String(
contentsOfFile: dir.appendingPathComponent( contentsOfFile: dir.appendingPathComponent(
"metadata.json" "metadata.json"
) )
.path .path
).utf8) ).utf8)
) )
loadLocalState() loadLocalState()
comics.append( comics.append(
@@ -304,11 +305,11 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
return return
} }
var newMetadata = Metadata.init( var newMetadata = Metadata(
title: "", title: "",
original_language: "", original_language: "",
last_volume: MetaValue.init(main: 0, bonus: nil), last_volume: MetaValue(main: 0, bonus: nil),
last_chapter: MetaValue.init(main: 0, bonus: nil), last_chapter: MetaValue(main: 0, bonus: nil),
chapter_count: 0, chapter_count: 0,
publication_demographic: "", publication_demographic: "",
status: "", status: "",
@@ -351,19 +352,23 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
newMetadata.chapter_count += 1 newMetadata.chapter_count += 1
assert(volume > currentVolume) assert(volume > currentVolume)
newMetadata.volumes.append( newMetadata.volumes.append(
VolumeMetadata.init( VolumeMetadata(
volume: MetaValue.init(main: volume, bonus: nil), name: nil, volume: MetaValue(main: volume, bonus: nil), name: nil,
chapters: [ chapters: [
ChapterMetadata.init( ChapterMetadata(
chapter: MetaValue.init( chapter: MetaValue(
main: chapter.0, bonus: chapter.1), main: chapter.0, bonus: chapter.1
),
name: "", name: "",
images: [ images: [
ImageMetadata.init( ImageMetadata(
doublePage: doublePage, fileName: fileName, doublePage: doublePage, fileName: fileName,
firstPage: page) firstPage: page
]) ),
])) ]
),
]
))
} else if chapter != currentChapter { } else if chapter != currentChapter {
newMetadata.chapter_count += 1 newMetadata.chapter_count += 1
if chapter.0 == currentChapter.0 { if chapter.0 == currentChapter.0 {
@@ -372,37 +377,43 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
assert(chapter.0 == currentChapter.0 + 1) assert(chapter.0 == currentChapter.0 + 1)
} }
newMetadata.volumes[newMetadata.volumes.count - 1].chapters.append( newMetadata.volumes[newMetadata.volumes.count - 1].chapters.append(
ChapterMetadata.init( ChapterMetadata(
chapter: MetaValue.init(main: chapter.0, bonus: chapter.1), chapter: MetaValue(main: chapter.0, bonus: chapter.1),
name: "", name: "",
images: [ images: [
ImageMetadata.init( ImageMetadata(
doublePage: doublePage, fileName: fileName, doublePage: doublePage, fileName: fileName,
firstPage: page) firstPage: page
])) ),
]
))
} else { } else {
newMetadata.volumes[newMetadata.volumes.count - 1].chapters[ newMetadata.volumes[newMetadata.volumes.count - 1].chapters[
newMetadata.volumes[newMetadata.volumes.count - 1].chapters.count - 1 newMetadata.volumes[newMetadata.volumes.count - 1].chapters.count - 1
].images.append( ].images.append(
ImageMetadata.init( ImageMetadata(
doublePage: doublePage, fileName: fileName, firstPage: page) doublePage: doublePage, fileName: fileName, firstPage: page
)
) )
} }
} else { } else {
newMetadata.chapter_count += 1 newMetadata.chapter_count += 1
newMetadata.volumes.append( newMetadata.volumes.append(
VolumeMetadata.init( VolumeMetadata(
volume: MetaValue.init(main: volume, bonus: nil), name: nil, volume: MetaValue(main: volume, bonus: nil), name: nil,
chapters: [ chapters: [
ChapterMetadata.init( ChapterMetadata(
chapter: MetaValue.init(main: chapter.0, bonus: chapter.1), chapter: MetaValue(main: chapter.0, bonus: chapter.1),
name: "", name: "",
images: [ images: [
ImageMetadata.init( ImageMetadata(
doublePage: doublePage, fileName: fileName, doublePage: doublePage, fileName: fileName,
firstPage: page) firstPage: page
]) ),
])) ]
),
]
))
} }
currentVolume = volume currentVolume = volume
currentChapter = chapter currentChapter = chapter
@@ -434,20 +445,23 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
if screenSize.width > screenSize.height { if screenSize.width > screenSize.height {
scrollOffset.y *= (screenSize.height / screenSize.width) scrollOffset.y *= (screenSize.height / screenSize.width)
} }
var newProgress: ReadProgress = var newProgress =
ReadProgress.leftToRight( ReadProgress.leftToRight(
volumeIndex: progress.v, chapterIndex: progress.c, volumeIndex: progress.v, chapterIndex: progress.c,
imageIndex: progress.i) imageIndex: progress.i
)
switch mode { switch mode {
case .leftToRight: case .leftToRight:
newProgress = ReadProgress.leftToRight( newProgress = ReadProgress.leftToRight(
volumeIndex: progress.v, chapterIndex: progress.c, volumeIndex: progress.v, chapterIndex: progress.c,
imageIndex: progress.i) imageIndex: progress.i
case .rightToLeft: newProgress = ReadProgress.rightToLeft( )
volumeIndex: progress.v, chapterIndex: progress.c, case .rightToLeft: newProgress = ReadProgress.rightToLeft(
imageIndex: progress.i) volumeIndex: progress.v, chapterIndex: progress.c,
case .scroll: newProgress = ReadProgress.scroll(scrollOffset) imageIndex: progress.i
)
case .scroll: newProgress = ReadProgress.scroll(scrollOffset)
} }
queue.async { queue.async {
do { do {
@@ -465,23 +479,23 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
func loadLocalState() { func loadLocalState() {
do { do {
let json = Data( let json = try Data(
try String( String(
contentsOfFile: currentPath.appendingPathComponent("state.json").path contentsOfFile: currentPath.appendingPathComponent("state.json").path
).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 volumeIndex, let chapterIndex, let imageIndex): case let .leftToRight(volumeIndex, chapterIndex, imageIndex):
progress.v = volumeIndex progress.v = volumeIndex
progress.c = chapterIndex progress.c = chapterIndex
progress.i = imageIndex progress.i = imageIndex
mode = .leftToRight mode = .leftToRight
case .rightToLeft(let volumeIndex, let chapterIndex, let imageIndex): case let .rightToLeft(volumeIndex, chapterIndex, imageIndex):
progress.v = volumeIndex progress.v = volumeIndex
progress.c = chapterIndex progress.c = chapterIndex
progress.i = imageIndex progress.i = imageIndex
mode = .rightToLeft mode = .rightToLeft
case .scroll(let point): case let .scroll(point):
if scrollPos == nil { if scrollPos == nil {
scrollPos = point scrollPos = point
let screenSize = UIScreen.main.bounds.size let screenSize = UIScreen.main.bounds.size
@@ -491,13 +505,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
} }
if let indexPath = scrollingCollectionView.indexPathForItem(at: scrollOffset) { if let indexPath = scrollingCollectionView.indexPathForItem(at: scrollOffset) {
var theProgress = ProgressIndices(v: 0, c: 0, i: 0) var theProgress = ProgressIndices(v: 0, c: 0, i: 0)
for _ in 0...indexPath.item { for _ in 0 ... indexPath.item {
theProgress = getProgressIndicesFromTurn( theProgress = getProgressIndicesFromTurn(
turn: .next, progress: theProgress) turn: .next, progress: theProgress
)
} }
progress = theProgress progress = theProgress
} }
} }
mode = .scroll mode = .scroll
} }
@@ -521,11 +535,12 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
setupTapZones() setupTapZones()
} }
func scrollViewDidScroll(_ scrollView: UIScrollView) { func scrollViewDidScroll(_: UIScrollView) {
if scrollingCollectionView.isHidden { return } if scrollingCollectionView.isHidden { return }
let centerPoint = CGPoint( let centerPoint = CGPoint(
x: scrollingCollectionView.bounds.midX + scrollingCollectionView.contentOffset.x, x: scrollingCollectionView.bounds.midX + scrollingCollectionView.contentOffset.x,
y: scrollingCollectionView.bounds.midY + scrollingCollectionView.contentOffset.y) y: scrollingCollectionView.bounds.midY + scrollingCollectionView.contentOffset.y
)
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]
@@ -544,7 +559,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
{ {
return return
} }
if !hasSetContentOffset && scrollPos != nil { if !hasSetContentOffset, scrollPos != nil {
let screenSize = UIScreen.main.bounds.size let screenSize = UIScreen.main.bounds.size
var offset = scrollPos! var offset = scrollPos!
if screenSize.width > screenSize.height { if screenSize.width > screenSize.height {
@@ -597,17 +612,17 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var count = 0 var count = 0
if let enumerator = fileManager.enumerator( if let enumerator = fileManager.enumerator(
at: currentPath, includingPropertiesForKeys: [.isDirectoryKey], at: currentPath, includingPropertiesForKeys: [.isDirectoryKey],
options: [.skipsHiddenFiles]) options: [.skipsHiddenFiles]
{ ) {
for case let dir as URL in enumerator { for case let dir as URL in enumerator {
do { do {
if let enumerator = fileManager.enumerator( if let enumerator = fileManager.enumerator(
at: dir, includingPropertiesForKeys: [.isRegularFileKey], at: dir, includingPropertiesForKeys: [.isRegularFileKey],
options: [.skipsHiddenFiles]) options: [.skipsHiddenFiles]
{ ) {
for case let file as URL in enumerator { for case let file as URL in enumerator {
let resourceValues = try file.resourceValues(forKeys: [ let resourceValues = try file.resourceValues(forKeys: [
.isRegularFileKey .isRegularFileKey,
]) ])
if resourceValues.isRegularFile == true { if resourceValues.isRegularFile == true {
count += 1 count += 1
@@ -628,14 +643,16 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
layout.minimumInteritemSpacing = 0 layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0 layout.minimumLineSpacing = 0
scrollingCollectionView = UICollectionView( scrollingCollectionView = UICollectionView(
frame: view.bounds, collectionViewLayout: layout) frame: view.bounds, collectionViewLayout: layout
)
scrollingCollectionView.translatesAutoresizingMaskIntoConstraints = false scrollingCollectionView.translatesAutoresizingMaskIntoConstraints = false
scrollingCollectionView.dataSource = self scrollingCollectionView.dataSource = self
scrollingCollectionView.delegate = self scrollingCollectionView.delegate = self
scrollingCollectionView.backgroundColor = .white scrollingCollectionView.backgroundColor = .white
scrollingCollectionView.isHidden = true scrollingCollectionView.isHidden = true
scrollingCollectionView.register( scrollingCollectionView.register(
ScrollingImageCell.self, forCellWithReuseIdentifier: "ScrollingImageCell") ScrollingImageCell.self, forCellWithReuseIdentifier: "ScrollingImageCell"
)
readerView.addSubview(scrollingCollectionView) readerView.addSubview(scrollingCollectionView)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
@@ -949,8 +966,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
} }
func gestureRecognizer( func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer, _: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer
) -> Bool { ) -> Bool {
return true return true
} }
@@ -965,13 +982,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
} }
} }
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { func scrollViewDidEndDecelerating(_: UIScrollView) {
if scrollingCollectionView.isHidden { return } if scrollingCollectionView.isHidden { return }
updateInfo() updateInfo()
saveLocalState() saveLocalState()
} }
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { func scrollViewDidEndDragging(_: UIScrollView, willDecelerate decelerate: Bool) {
if scrollingCollectionView.isHidden { return } if scrollingCollectionView.isHidden { return }
if !decelerate { if !decelerate {
updateInfo() updateInfo()
@@ -1044,8 +1061,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
let scaling = UIView.ContentMode.scaleAspectFit let scaling = UIView.ContentMode.scaleAspectFit
var newProgress = progress var newProgress = progress
newProgress = getProgressIndicesFromTurn(turn: turn, progress: newProgress) newProgress = getProgressIndicesFromTurn(turn: turn, progress: newProgress)
if newProgress.v == progress.v && newProgress.c == progress.c && newProgress.i == progress.i if newProgress.v == progress.v, newProgress.c == progress.c, newProgress.i == progress.i {
{
return return
} }
progress = newProgress progress = newProgress
@@ -1058,7 +1074,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
return return
} }
for _ in 0...preloadCount { for _ in 0 ... preloadCount {
newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress) newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
if let path = getImagePath(progress: newProgress) { if let path = getImagePath(progress: newProgress) {
imageLoader.preloadImage(at: path, scaling: scaling) imageLoader.preloadImage(at: path, scaling: scaling)
@@ -1106,7 +1122,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
metadata.volumes[progress.v].chapters[lastChapterIndex].images.count - 1 metadata.volumes[progress.v].chapters[lastChapterIndex].images.count - 1
let lastImage = metadata.volumes[progress.v].chapters[lastChapterIndex].images[ let lastImage = metadata.volumes[progress.v].chapters[lastChapterIndex].images[
lastImageIndex] lastImageIndex
]
var lastPageString = "" var lastPageString = ""
if lastImage.doublePage { if lastImage.doublePage {
lastPageString = String(lastImage.firstPage + 1) lastPageString = String(lastImage.firstPage + 1)
@@ -1150,37 +1167,39 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
switch turn { switch turn {
case .next: case .next:
if metadata.volumes[v].chapters[c].images.count > i + 1 { if metadata.volumes[v].chapters[c].images.count > i + 1 {
return ProgressIndices.init(v: v, c: c, i: i + 1) return ProgressIndices(v: v, c: c, i: i + 1)
} }
if metadata.volumes[v].chapters.count > c + 1 { if metadata.volumes[v].chapters.count > c + 1 {
return ProgressIndices.init(v: v, c: c + 1, i: 0) return ProgressIndices(v: v, c: c + 1, i: 0)
} }
if metadata.volumes.count > v + 1 { if metadata.volumes.count > v + 1 {
return ProgressIndices.init(v: v + 1, c: 0, i: 0) return ProgressIndices(v: v + 1, c: 0, i: 0)
} }
case .previous: case .previous:
if i > 0 { if i > 0 {
return ProgressIndices.init(v: v, c: c, i: i - 1) return ProgressIndices(v: v, c: c, i: i - 1)
} }
if c > 0 { if c > 0 {
return ProgressIndices.init( return ProgressIndices(
v: v, c: c - 1, i: metadata.volumes[v].chapters[c - 1].images.count - 1) v: v, c: c - 1, i: metadata.volumes[v].chapters[c - 1].images.count - 1
)
} }
if v > 0 { if v > 0 {
return ProgressIndices.init( return ProgressIndices(
v: v - 1, c: metadata.volumes[v - 1].chapters.count - 1, v: v - 1, c: metadata.volumes[v - 1].chapters.count - 1,
i: metadata.volumes[v - 1].chapters[ i: metadata.volumes[v - 1].chapters[
metadata.volumes[v - 1].chapters.count - 1 metadata.volumes[v - 1].chapters.count - 1
].images.count - 1) ].images.count - 1
)
} }
} }
return ProgressIndices.init(v: v, c: c, i: i) return ProgressIndices(v: v, c: c, i: i)
} }
func getMetadata(path: URL) -> Metadata? { func getMetadata(path: URL) -> Metadata? {
do { do {
let json = Data( let json = try Data(
try String(contentsOfFile: path.appendingPathComponent("metadata.json").path) String(contentsOfFile: path.appendingPathComponent("metadata.json").path)
.utf8) .utf8)
let metadata = try JSONDecoder().decode(Metadata.self, from: json) let metadata = try JSONDecoder().decode(Metadata.self, from: json)
return metadata return metadata
@@ -1193,14 +1212,14 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
return nil return nil
} }
func setImages(path: URL) { func setImages(path _: URL) {
let scaling: UIView.ContentMode! let scaling: UIView.ContentMode!
if mode == .scroll { if mode == .scroll {
scaling = UIView.ContentMode.scaleAspectFill scaling = UIView.ContentMode.scaleAspectFill
} else { scaling = UIView.ContentMode.scaleAspectFit } } else { scaling = UIView.ContentMode.scaleAspectFit }
imageLoader.loadImage( imageLoader.loadImage(
at: at:
getImagePath(progress: progress), getImagePath(progress: progress),
scaling: scaling scaling: scaling
) { [weak self] image in ) { [weak self] image in
self?.imageView.image = image self?.imageView.image = image
@@ -1208,7 +1227,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
} }
var newProgress = progress var newProgress = progress
for _ in 0...preloadCount { for _ in 0 ... preloadCount {
newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress) newProgress = getProgressIndicesFromTurn(turn: .next, progress: newProgress)
imageLoader.preloadImage(at: getImagePath(progress: newProgress), scaling: scaling) imageLoader.preloadImage(at: getImagePath(progress: newProgress), scaling: scaling)
} }
@@ -1245,8 +1264,8 @@ func getGlobalState() -> GlobalState {
let fileManager = FileManager.default let fileManager = FileManager.default
if let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first { if let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first {
do { do {
let json = Data( let json = try Data(
try String( String(
contentsOfFile: documentsURL.appendingPathComponent("state.json").path contentsOfFile: documentsURL.appendingPathComponent("state.json").path
).utf8) ).utf8)
return try JSONDecoder().decode(GlobalState.self, from: json) return try JSONDecoder().decode(GlobalState.self, from: json)
@@ -1268,9 +1287,8 @@ func getDocumentsURL() -> URL? {
} }
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView( func collectionView(
_ collectionView: UICollectionView, numberOfItemsInSection section: Int _ collectionView: UICollectionView, numberOfItemsInSection _: Int
) )
-> Int -> Int
{ {
@@ -1287,7 +1305,8 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
if collectionView == comicCollectionView { if collectionView == comicCollectionView {
let cell = let cell =
collectionView.dequeueReusableCell( collectionView.dequeueReusableCell(
withReuseIdentifier: "ComicImageCell", for: indexPath) withReuseIdentifier: "ComicImageCell", for: indexPath
)
as! ComicImageCell as! ComicImageCell
cell.imageView.image = comics[indexPath.item].cover cell.imageView.image = comics[indexPath.item].cover
return cell return cell
@@ -1295,7 +1314,8 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
// 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
)
as! ScrollingImageCell as! ScrollingImageCell
if metadata == nil { if metadata == nil {
return cell return cell
@@ -1303,20 +1323,21 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
// TODO: Fix scrolling again // TODO: Fix scrolling again
return cell return cell
} else { } else {
assert(false) assertionFailure()
} }
// Xcode profiling sucks: // Xcode profiling sucks:
return return
collectionView.dequeueReusableCell( collectionView.dequeueReusableCell(
withReuseIdentifier: "ScrollingImageCell", for: indexPath) withReuseIdentifier: "ScrollingImageCell", for: indexPath
)
as! ScrollingImageCell as! ScrollingImageCell
} }
func collectionView( func collectionView(
_ collectionView: UICollectionView, _ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout, layout _: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath sizeForItemAt _: IndexPath
) -> CGSize { ) -> CGSize {
if collectionView == comicCollectionView { if collectionView == comicCollectionView {
let spacing: CGFloat = 8 let spacing: CGFloat = 8
@@ -1331,7 +1352,7 @@ extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFl
// TODO: Fix scrolling again // TODO: Fix scrolling again
return CGSize() return CGSize()
} else { } else {
assert(false) assertionFailure()
} }
// Xcode profiling sucks: // Xcode profiling sucks:
return CGSize() return CGSize()
@@ -1367,7 +1388,8 @@ class ScrollingImageCell: UICollectionViewCell {
]) ])
} }
required init?(coder: NSCoder) { @available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
} }
@@ -1390,7 +1412,8 @@ class ComicImageCell: UICollectionViewCell {
]) ])
} }
required init?(coder: NSCoder) { @available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
} }
@@ -1403,7 +1426,7 @@ enum Rotation {
class ImageLoader { class ImageLoader {
private let cache = NSCache<NSString, UIImage>() private let cache = NSCache<NSString, UIImage>()
private let horCache = NSCache<NSString, UIImage>() private let horCache = NSCache<NSString, UIImage>()
private var loadingTasks: [String: [((UIImage?) -> Void)]] = [:] private var loadingTasks: [String: [(UIImage?) -> Void]] = [:]
var size: [String: CGSize] = [:] var size: [String: CGSize] = [:]
init() { init() {
@@ -1421,9 +1444,9 @@ class ImageLoader {
) { ) {
let screenSize = UIScreen.main.bounds.size let screenSize = UIScreen.main.bounds.size
let rotation: Rotation! let rotation: Rotation!
if screenSize.width > screenSize.height { if screenSize.width > screenSize.height {
rotation = Rotation.horizontal rotation = Rotation.horizontal
} else { rotation = Rotation.vertical } } else { rotation = Rotation.vertical }
if rotation == .vertical { if rotation == .vertical {
if let cached = cache.object(forKey: path.path as NSString) { if let cached = cache.object(forKey: path.path as NSString) {
@@ -1455,9 +1478,11 @@ class ImageLoader {
if completion == nil || rotation == .vertical { if completion == nil || rotation == .vertical {
let vertical = CGSize( let vertical = CGSize(
width: min(screenSize.width, screenSize.height), width: min(screenSize.width, screenSize.height),
height: max(screenSize.height, screenSize.width)) height: max(screenSize.height, screenSize.width)
)
let vScaledSize = aspectSize( let vScaledSize = aspectSize(
for: image.size, in: vertical, scaling: scaling) for: image.size, in: vertical, scaling: scaling
)
let vScaleImage = resizeImage(image, to: vScaledSize) let vScaleImage = resizeImage(image, to: vScaledSize)
guard let cost = imageByteSize(vScaleImage) else { return } guard let cost = imageByteSize(vScaleImage) else { return }
self.cache.setObject(vScaleImage, forKey: path.path as NSString, cost: cost) self.cache.setObject(vScaleImage, forKey: path.path as NSString, cost: cost)
@@ -1469,9 +1494,11 @@ class ImageLoader {
if completion == nil || rotation == .horizontal { if completion == nil || rotation == .horizontal {
let horizontal = CGSize( let horizontal = CGSize(
width: max(screenSize.width, screenSize.height), width: max(screenSize.width, screenSize.height),
height: min(screenSize.height, screenSize.width)) height: min(screenSize.height, screenSize.width)
)
let hScaledSize = aspectSize( let hScaledSize = aspectSize(
for: image.size, in: horizontal, scaling: scaling) for: image.size, in: horizontal, scaling: scaling
)
let hScaleImage = resizeImage(image, to: hScaledSize) let hScaleImage = resizeImage(image, to: hScaledSize)
guard let cost = imageByteSize(hScaleImage) else { return } guard let cost = imageByteSize(hScaleImage) else { return }
self.horCache.setObject(hScaleImage, forKey: path.path as NSString, cost: cost) self.horCache.setObject(hScaleImage, forKey: path.path as NSString, cost: cost)