feat: alerts

This commit was merged in pull request #21.
This commit is contained in:
2026-07-17 02:30:56 +02:00
parent 36157b53f9
commit 77872ed1ea
+144 -24
View File
@@ -59,6 +59,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var scrollPos: CGPoint!
var hasSetContentOffset = false
var pendingAlert: UIAlertController?
var imageView = UIImageView()
var mode = PageTurnMode.leftToRight
var metadataList: [URL: Metadata] = [:]
@@ -105,6 +107,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
setup()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let alert = pendingAlert {
present(alert, animated: false, completion: nil)
}
}
func setup() {
do {
if try fileManager.contentsOfDirectory(atPath: documentsURL.path).isEmpty {
@@ -140,8 +149,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
setupHomeView()
if let name = globalState.comicName {
readComic(name: name)
} else {
print("no comic?")
}
}
@@ -163,14 +170,21 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
}
func loadComics() {
let alert = UIAlertController(title: "Failed to load comics.", message: "This is an alert.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
do {
var directories: [URL] = []
let contents = try fileManager.contentsOfDirectory(
guard let contents = try? fileManager.contentsOfDirectory(
at: documentsURL,
includingPropertiesForKeys: [.isDirectoryKey],
options: [.skipsHiddenFiles]
)
else {
alert.message = String(format: "Failed to read contents of directory: \(documentsURL)")
pendingAlert = alert
return
}
directories = contents.filter { url in
var isDirectory: ObjCBool = false
@@ -181,33 +195,63 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
for dir in directories {
if !fileManager.fileExists(atPath: dir.appendingPathComponent(metadataFilename).path) {
getMetadataFromFilename(path: dir)
if pendingAlert != nil {
return
}
}
currentPath = dir
let data = try! Data(contentsOf: dir.appendingPathComponent(metadataFilename))
guard let data = try? Data(contentsOf: dir.appendingPathComponent(metadataFilename))
else {
alert.message = String(format: "Failed to read contents of metadata: \(dir.appendingPathComponent(metadataFilename))")
pendingAlert = alert
return
}
var byteBuffer = ByteBuffer(data: data)
metadata = try! getCheckedRoot(byteBuffer: &byteBuffer)
metadata = try? getCheckedRoot(byteBuffer: &byteBuffer)
if metadata == nil {
alert.message = String(format: "Failed to read contents of metadata flatbuffer file: \(dir.appendingPathComponent(metadataFilename))")
pendingAlert = alert
return
}
metadataList[dir] = metadata
loadLocalState()
let volCovP = ProgressIndices(v: progress.v, c: 0, i: 0)
let archivePath = getArchiveURL(volCovP.v)
let archive = try! Archive(url: archivePath, accessMode: .read)
let archive = try Archive(url: archivePath, accessMode: .read)
let filename = metadata.volumes[volCovP.v].chapters[volCovP.c].images[volCovP.i].filename!
let targetEntry = archive[filename]!
guard let targetEntry = archive[filename] else {
alert.message = String(format: "Archive entry does not exist: \(filename)")
pendingAlert = alert
return
}
var extractedData = Data()
_ = try archive.extract(targetEntry) { data in
extractedData.append(data)
do {
_ = try archive.extract(targetEntry) { data in
extractedData.append(data)
}
} catch {
alert.message = String(format: "Failed to extract data from entry: \(targetEntry.path)")
pendingAlert = alert
return
}
guard let coverImage = UIImage(data: extractedData) else {
alert.message = String(format: "Cover image is nil: \(filename)")
pendingAlert = alert
return
}
comics.append(
Comic(
cover: UIImage(data: extractedData)!,
cover: coverImage,
metadata: metadata,
path: dir
)
)
}
} catch {
pendingAlert = alert
alert.message = String(format: "Generic failure.")
print("Failed to read directories")
}
}
@@ -263,9 +307,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
func getMetadataFromFilename(path: URL) {
// Beautiful, is it not?
let patterns: [(NSRegularExpression, NSRegularExpression, Int, Int, Int)] = [
(try! NSRegularExpression(pattern: #"c([0-9]+(?:x[0-9]+)?) \(v([0-9]+)\) - p([0-9]+(?:-p?[0-9]+)?)"#), try! NSRegularExpression(pattern: #"^(.*) - c([0-9]+(?:x[0-9]+)?) \(v([0-9]+)\) - p([0-9]+(?:-p?[0-9]+)?)"#), 3, 1, 2),
(try! NSRegularExpression(pattern: "v([0-9]+) p([0-9]+(?:-[0-9]+)?) - c([0-9]+(?:x[0-9]+)?)"), try! NSRegularExpression(pattern: "^(.*) - v([0-9]+) p([0-9]+(?:-[0-9]+)?) - c([0-9]+(?:x[0-9]+)?)"), 2, 3, 1),
let patterns: [(NSRegularExpression?, NSRegularExpression?, Int, Int, Int)] = [
(try? NSRegularExpression(pattern: #"c([0-9]+(?:x[0-9]+)?) \(v([0-9]+)\) - p([0-9]+(?:-p?[0-9]+)?)"#), try? NSRegularExpression(pattern: #"^(.*) - c([0-9]+(?:x[0-9]+)?) \(v([0-9]+)\) - p([0-9]+(?:-p?[0-9]+)?)"#), 3, 1, 2),
(try? NSRegularExpression(pattern: "v([0-9]+) p([0-9]+(?:-[0-9]+)?) - c([0-9]+(?:x[0-9]+)?)"), try? NSRegularExpression(pattern: "^(.*) - v([0-9]+) p([0-9]+(?:-[0-9]+)?) - c([0-9]+(?:x[0-9]+)?)"), 2, 3, 1),
]
var pattern: NSRegularExpression! = nil
var titlePattern: NSRegularExpression! = nil
@@ -293,6 +337,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
var titleValue: String = ""
let alert = UIAlertController(title: "Failed to get metadata from filename.", message: "This is an alert.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
let volumeDir = path.appendingPathComponent("volumes")
var isDir: ObjCBool = false
@@ -300,25 +347,42 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
print("Subdirectory volumes not found in \"\(path)\", returning")
return
}
let volumeURLs = try! fileManager.contentsOfDirectory(
let volumeURLs = try? fileManager.contentsOfDirectory(
at: volumeDir,
includingPropertiesForKeys: [.isRegularFileKey],
options: [.skipsHiddenFiles]
).filter { $0.pathExtension == "cbz" }
.sorted { $0.lastPathComponent < $1.lastPathComponent }
if volumeURLs == nil {
alert.message = String(format: "failed to read dir: \(volumeDir)")
pendingAlert = alert
return
}
if volumeURLs.isEmpty {
if volumeURLs!.isEmpty {
print("found no volumes in volume dir: \(volumeDir)")
return
}
var filenames: [(String, String)] = []
for volumeURL in volumeURLs {
for volumeURL in volumeURLs! {
do {
let volumeArchive = try Archive(url: volumeURL, accessMode: .read)
volumeArchive.map { URL(string: $0.path)!.lastPathComponent }.sorted().forEach{ filenames.append((volumeURL.lastPathComponent, $0)) }
var volumeArchiveFiles: [String] = []
for entry in volumeArchive {
// guard let url = URL(string: entry.path) else {
// alert.message = String(format: "failed to create URL from string: \(entry.path)")
// pendingAlert = alert
// return
// }
volumeArchiveFiles.append(entry.path)
}
for filename in volumeArchiveFiles.sorted() {
filenames.append((volumeURL.lastPathComponent, filename))
}
} catch {
print("Failed to read archive \(volumeURL)")
alert.message = String(format: "failed to read archive: \(volumeURL)")
pendingAlert = alert
continue
}
}
@@ -330,6 +394,16 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
do {
for (currentPattern, currentTitlePattern, currentPageRegexPosition, currentChapterRegexPosition, currentVolumeRegexPosition) in patterns {
guard let currentPattern = currentPattern else {
alert.message = String(format: "failed to get currentPattern")
pendingAlert = alert
continue
}
guard let currentTitlePattern = currentTitlePattern else {
alert.message = String(format: "failed to get currentTitlePattern")
pendingAlert = alert
continue
}
let filename = filenames[0].1
let range = NSRange(filename.startIndex..., in: filename)
if let match = currentTitlePattern.firstMatch(in: filename, range: range) {
@@ -390,25 +464,51 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
if let match = regex.firstMatch(in: filename, range: range) {
let chapterStr = (filename as NSString).substring(with: match.range(at: chapterRegexPosition))
let chapterParts = chapterStr.split(separator: "x", maxSplits: 1)
if chapterParts.count < 1 {
alert.message = String(format: "Did not find chapter number in filename: \(filename)")
pendingAlert = alert
return
}
guard let nChapter0 = UInt32(chapterParts[0]) else {
alert.message = String(format: "Failed to convert chapter number to an int: \(filename)")
pendingAlert = alert
return
}
let chapter: (UInt32, UInt32?) = (
UInt32(chapterParts[0])!, chapterParts.count > 1 ? UInt32(chapterParts[1])! : nil
nChapter0, chapterParts.count > 1 ? UInt32(chapterParts[1]) : nil
)
let volume: UInt32 = UInt32((filename as NSString).substring(with: match.range(at: volumeRegexPosition)))!
guard let volume: UInt32 = UInt32((filename as NSString).substring(with: match.range(at: volumeRegexPosition))) else {
alert.message = String(format: "failed to get match for volume in filename: \(filename)")
pendingAlert = alert
return
}
let pageStr = (filename as NSString).substring(with: match.range(at: pageRegexPosition))
let pageParts = pageStr.split(separator: "-", maxSplits: 1)
guard let nPage = UInt32(pageParts[0]) else {
alert.message = String(format: "failed to read archive: \(filename)")
pendingAlert = alert
return
}
let (page, doublePage) = (
UInt32(pageParts[0])!, pageParts.count > 1
nPage, pageParts.count > 1
)
let archive = try Archive(url: volumeDir.appendingPathComponent(volumeURL), accessMode: .read)
let entry = archive[filename]!
guard let entry = archive[filename] else {
alert.message = String(format: "failed to read archive: \(filename)")
pendingAlert = alert
return
}
var size = ImageDimensions(width: 0, height: 0)
do {
size = try imageDimensions(of: entry, in: archive)
} catch {
print("Failed to get image dimensions of filename: \(filename)")
alert.message = String(format: "Failed to get image dimensions of filename: \(filename)")
pendingAlert = alert
return
}
let m_filename = builder.create(string: filename)
@@ -452,8 +552,23 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
currentChapters = []
} else if chapter != currentChapter {
if chapter.0 == currentChapter.0 {
if chapter.1 == nil {
alert.message = String(format: "chapter.1 is nil")
pendingAlert = alert
return
}
if chapter.1! != currentChapter.1 ?? 1 {
alert.message = String(format: "chapter != currentChapter")
pendingAlert = alert
return
}
assert(chapter.1! == currentChapter.1 ?? 1)
} else {
if chapter.0 != currentChapter.0 + 1 {
alert.message = String(format: "chapter.0 != currentChapter.0 + 1")
pendingAlert = alert
return
}
assert(chapter.0 == currentChapter.0 + 1)
}
@@ -547,7 +662,12 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
)
builder.finish(offset: metadata)
try! builder.data.write(to: path.appendingPathComponent(metadataFilename))
do {
try builder.data.write(to: path.appendingPathComponent(metadataFilename))
} catch {
alert.message = String(format: "Failed to write metadata file at: \(metadataFilename)")
pendingAlert = alert
}
}
func saveLocalState() {