feat: alerts #21
@@ -59,6 +59,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
var scrollPos: CGPoint!
|
var scrollPos: CGPoint!
|
||||||
var hasSetContentOffset = false
|
var hasSetContentOffset = false
|
||||||
|
|
||||||
|
var pendingAlert: UIAlertController?
|
||||||
|
|
||||||
var imageView = UIImageView()
|
var imageView = UIImageView()
|
||||||
var mode = PageTurnMode.leftToRight
|
var mode = PageTurnMode.leftToRight
|
||||||
var metadataList: [URL: Metadata] = [:]
|
var metadataList: [URL: Metadata] = [:]
|
||||||
@@ -105,6 +107,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
setup()
|
setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
if let alert = pendingAlert {
|
||||||
|
present(alert, animated: false, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setup() {
|
func setup() {
|
||||||
do {
|
do {
|
||||||
if try fileManager.contentsOfDirectory(atPath: documentsURL.path).isEmpty {
|
if try fileManager.contentsOfDirectory(atPath: documentsURL.path).isEmpty {
|
||||||
@@ -140,8 +149,6 @@ 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?")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,14 +170,21 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadComics() {
|
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 {
|
do {
|
||||||
var directories: [URL] = []
|
var directories: [URL] = []
|
||||||
|
|
||||||
let contents = try fileManager.contentsOfDirectory(
|
guard let contents = try? fileManager.contentsOfDirectory(
|
||||||
at: documentsURL,
|
at: documentsURL,
|
||||||
includingPropertiesForKeys: [.isDirectoryKey],
|
includingPropertiesForKeys: [.isDirectoryKey],
|
||||||
options: [.skipsHiddenFiles]
|
options: [.skipsHiddenFiles]
|
||||||
)
|
)
|
||||||
|
else {
|
||||||
|
alert.message = String(format: "Failed to read contents of directory: \(documentsURL)")
|
||||||
|
pendingAlert = alert
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
directories = contents.filter { url in
|
directories = contents.filter { url in
|
||||||
var isDirectory: ObjCBool = false
|
var isDirectory: ObjCBool = false
|
||||||
@@ -181,33 +195,63 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
for dir in directories {
|
for dir in directories {
|
||||||
if !fileManager.fileExists(atPath: dir.appendingPathComponent(metadataFilename).path) {
|
if !fileManager.fileExists(atPath: dir.appendingPathComponent(metadataFilename).path) {
|
||||||
getMetadataFromFilename(path: dir)
|
getMetadataFromFilename(path: dir)
|
||||||
|
if pendingAlert != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPath = dir
|
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)
|
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
|
metadataList[dir] = metadata
|
||||||
loadLocalState()
|
loadLocalState()
|
||||||
let volCovP = ProgressIndices(v: progress.v, c: 0, i: 0)
|
let volCovP = ProgressIndices(v: progress.v, c: 0, i: 0)
|
||||||
let archivePath = getArchiveURL(volCovP.v)
|
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 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()
|
var extractedData = Data()
|
||||||
_ = try archive.extract(targetEntry) { data in
|
do {
|
||||||
extractedData.append(data)
|
_ = 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(
|
comics.append(
|
||||||
Comic(
|
Comic(
|
||||||
cover: UIImage(data: extractedData)!,
|
cover: coverImage,
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
path: dir
|
path: dir
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
pendingAlert = alert
|
||||||
|
alert.message = String(format: "Generic failure.")
|
||||||
print("Failed to read directories")
|
print("Failed to read directories")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,9 +307,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
|
|
||||||
func getMetadataFromFilename(path: URL) {
|
func getMetadataFromFilename(path: URL) {
|
||||||
// Beautiful, is it not?
|
// Beautiful, is it not?
|
||||||
let patterns: [(NSRegularExpression, NSRegularExpression, Int, Int, Int)] = [
|
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: #"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),
|
(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 pattern: NSRegularExpression! = nil
|
||||||
var titlePattern: NSRegularExpression! = nil
|
var titlePattern: NSRegularExpression! = nil
|
||||||
@@ -293,6 +337,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
|
|
||||||
var titleValue: String = ""
|
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")
|
let volumeDir = path.appendingPathComponent("volumes")
|
||||||
|
|
||||||
var isDir: ObjCBool = false
|
var isDir: ObjCBool = false
|
||||||
@@ -300,25 +347,42 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
print("Subdirectory volumes not found in \"\(path)\", returning")
|
print("Subdirectory volumes not found in \"\(path)\", returning")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let volumeURLs = try! fileManager.contentsOfDirectory(
|
let volumeURLs = try? fileManager.contentsOfDirectory(
|
||||||
at: volumeDir,
|
at: volumeDir,
|
||||||
includingPropertiesForKeys: [.isRegularFileKey],
|
includingPropertiesForKeys: [.isRegularFileKey],
|
||||||
options: [.skipsHiddenFiles]
|
options: [.skipsHiddenFiles]
|
||||||
).filter { $0.pathExtension == "cbz" }
|
).filter { $0.pathExtension == "cbz" }
|
||||||
.sorted { $0.lastPathComponent < $1.lastPathComponent }
|
.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)")
|
print("found no volumes in volume dir: \(volumeDir)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var filenames: [(String, String)] = []
|
var filenames: [(String, String)] = []
|
||||||
for volumeURL in volumeURLs {
|
for volumeURL in volumeURLs! {
|
||||||
do {
|
do {
|
||||||
let volumeArchive = try Archive(url: volumeURL, accessMode: .read)
|
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 {
|
} catch {
|
||||||
print("Failed to read archive \(volumeURL)")
|
alert.message = String(format: "failed to read archive: \(volumeURL)")
|
||||||
|
pendingAlert = alert
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,6 +394,16 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
for (currentPattern, currentTitlePattern, currentPageRegexPosition, currentChapterRegexPosition, currentVolumeRegexPosition) in patterns {
|
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 filename = filenames[0].1
|
||||||
let range = NSRange(filename.startIndex..., in: filename)
|
let range = NSRange(filename.startIndex..., in: filename)
|
||||||
if let match = currentTitlePattern.firstMatch(in: filename, range: range) {
|
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) {
|
if let match = regex.firstMatch(in: filename, range: range) {
|
||||||
let chapterStr = (filename as NSString).substring(with: match.range(at: chapterRegexPosition))
|
let chapterStr = (filename as NSString).substring(with: match.range(at: chapterRegexPosition))
|
||||||
let chapterParts = chapterStr.split(separator: "x", maxSplits: 1)
|
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?) = (
|
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 pageStr = (filename as NSString).substring(with: match.range(at: pageRegexPosition))
|
||||||
let pageParts = pageStr.split(separator: "-", maxSplits: 1)
|
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) = (
|
let (page, doublePage) = (
|
||||||
UInt32(pageParts[0])!, pageParts.count > 1
|
nPage, pageParts.count > 1
|
||||||
)
|
)
|
||||||
|
|
||||||
let archive = try Archive(url: volumeDir.appendingPathComponent(volumeURL), accessMode: .read)
|
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)
|
var size = ImageDimensions(width: 0, height: 0)
|
||||||
do {
|
do {
|
||||||
size = try imageDimensions(of: entry, in: archive)
|
size = try imageDimensions(of: entry, in: archive)
|
||||||
} catch {
|
} 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
|
return
|
||||||
}
|
}
|
||||||
let m_filename = builder.create(string: filename)
|
let m_filename = builder.create(string: filename)
|
||||||
@@ -452,8 +552,23 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
currentChapters = []
|
currentChapters = []
|
||||||
} else if chapter != currentChapter {
|
} else if chapter != currentChapter {
|
||||||
if chapter.0 == currentChapter.0 {
|
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)
|
assert(chapter.1! == currentChapter.1 ?? 1)
|
||||||
} else {
|
} 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)
|
assert(chapter.0 == currentChapter.0 + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,7 +662,12 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate {
|
|||||||
)
|
)
|
||||||
|
|
||||||
builder.finish(offset: metadata)
|
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() {
|
func saveLocalState() {
|
||||||
|
|||||||
Reference in New Issue
Block a user