Caps-iOS/CapCollector/Data/DiskManager.swift
Christoph Hagen 2806733b71 Version 1
2019-03-15 13:19:19 +01:00

215 lines
6.1 KiB
Swift

//
// DiskManager.swift
// CapFinder
//
// Created by User on 23.04.18.
// Copyright © 2018 User. All rights reserved.
//
import Foundation
import UIKit
final class DiskManager {
enum LocalDirectory: String {
/// Folder for new images to upload
case upload = "Upload"
/// Folder for downloaded images
case images = "Images"
/// Folder for downloaded images
case thumbnails = "Thumbnails"
/// Directory for name file
case files = "Files"
private static let fm = FileManager.default
/// The url to the file sstem
var url: URL {
return URL(fileURLWithPath: self.rawValue, isDirectory: true, relativeTo: DiskManager.documentsDirectory)
}
fileprivate func create() -> Bool {
return DiskManager.create(directory: url)
}
var content: [URL]? {
do {
return try LocalDirectory.fm.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [])
} catch {
print("[LocalDirectory] Could not read directory \(self.rawValue): \(error)")
return nil
}
}
}
/// The folder where images and name list are stored
static let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
private static let fm = FileManager.default
// MARK: - First launch
@discardableResult static func setupOnFirstLaunch() -> Bool {
return LocalDirectory.files.create() &&
LocalDirectory.images.create() &&
LocalDirectory.thumbnails.create() &&
LocalDirectory.upload.create()
}
private static func create(directory: URL) -> Bool {
do {
if !fm.fileExists(atPath: directory.path) {
try fm.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
}
return true
} catch {
event("Could not create \(directory): \(error)")
return false
}
}
// MARK: - Image retrieval
/**
Check if an image exists for a cap
- parameter cap: The id of the cap
- returns: True, if an image exists
*/
static func hasImage(for cap: Int) -> Bool {
let url = localUrl(for: cap)
return fm.fileExists(atPath: url.path)
}
private static func localUrl(for cap: Int) -> URL {
return URL(fileURLWithPath: "\(cap).jpg", isDirectory: true, relativeTo: LocalDirectory.images.url)
}
private static func thumbnailUrl(for cap: Int) -> URL {
return URL(fileURLWithPath: "\(cap).jpg", isDirectory: true, relativeTo: LocalDirectory.thumbnails.url)
}
/**
Get the image for a cap.
If the image exists on disk, it is returned.
If no image exists locally, then this function returns nil.
- parameter cap: The id of the cap
- returns: The image data, or `nil`
*/
static func image(for cap: Int) -> Data? {
// If the image exists on disk, get it
let url = localUrl(for: cap)
return readData(from: url)
}
private static let mosaicURL: URL = documentsDirectory.appendingPathComponent("mosaic.png")
static var mosaicExists: Bool {
return fm.fileExists(atPath: mosaicURL.path)
}
static func saveMosaicData(_ data: Data) -> Bool {
return write(data, to: mosaicURL)
}
static var mosaicData: Data? {
return readData(from: mosaicURL)
}
/**
Get the thumbnail for a cap.
If the image exists on disk, it is returned.
If no image exists locally, then this function returns nil.
- parameter cap: The id of the cap
- returns: The image data, or `nil`
*/
static func thumbnail(for cap: Int) -> Data? {
// If the image exists on disk, get it
let url = thumbnailUrl(for: cap)
return readData(from: url)
}
private static func readData(from url: URL) -> Data? {
guard fm.fileExists(atPath: url.path) else {
return nil
}
do {
return try Data(contentsOf: url)
} catch {
self.error("Could not read data from \(url): \(error)")
return nil
}
}
/**
Save an image to the download folder
- parameter imageData: The data of the image
- parameter cap: The cap id
- returns: True, if the image was saved
*/
static func save(imageData: Data, for cap: Int) -> Bool {
let url = localUrl(for: cap)
return write(imageData, to: url)
}
/**
Save a thumbnail to the download folder
- parameter thumbnailData: The data of the image
- parameter cap: The cap id
- returns: True, if the image was saved
*/
static func save(thumbnailData: Data, for cap: Int) -> Bool {
let url = thumbnailUrl(for: cap)
return write(thumbnailData, to: url)
}
private static func write(_ data: Data, to url: URL) -> Bool {
do {
try data.write(to: url)
} catch {
self.error("Could not write data to \(url): \(error)")
return false
}
return true
}
static func removeFromUpload(url: URL) -> Bool {
guard fm.fileExists(atPath: url.path) else {
return true
}
do {
try fm.removeItem(at: url)
return true
} catch {
self.error("Could not delete file \(url.path)")
return false
}
}
static var pendingUploads: [URL]? {
return LocalDirectory.upload.content
}
static var availableImages: [Int]? {
return LocalDirectory.images.content?.compactMap {
Int($0.lastPathComponent.components(separatedBy: ".").first ?? "")
}
}
/**
Save an image to the uploads folder for later
*/
static func saveForUpload(imageData: Data, name: String) -> URL? {
let url = LocalDirectory.upload.url.appendingPathComponent(name)
return write(imageData, to: url) ? url : nil
}
}
extension DiskManager: Logger {
static let logToken = "[DiskManager]"
}