yattee/Model/DocumentsModel.swift

167 lines
5.3 KiB
Swift
Raw Normal View History

2022-11-12 23:01:04 +00:00
import Foundation
final class DocumentsModel: ObservableObject {
static var shared = DocumentsModel()
@Published private(set) var refreshID = UUID()
typealias AreInIncreasingOrder = (URL, URL) -> Bool
private var fileManager: FileManager {
.default
}
var sortPredicates: [AreInIncreasingOrder] {
[
{ self.isDirectory($0) && !self.isDirectory($1) },
{ $0.lastPathComponent.caseInsensitiveCompare($1.lastPathComponent) == .orderedAscending }
]
}
2022-12-17 15:18:14 +00:00
func sortedDirectoryContents(_ directoryURL: URL) -> [URL] {
directoryContents(directoryURL).sorted { lhs, rhs in
2022-11-12 23:01:04 +00:00
for predicate in sortPredicates {
if !predicate(lhs, rhs), !predicate(rhs, lhs) {
continue
}
return predicate(lhs, rhs)
}
return false
}
}
2022-12-17 15:18:14 +00:00
func directoryContents(_ directoryURL: URL) -> [URL] {
contents(of: directoryURL)
2022-11-12 23:01:04 +00:00
}
var documentsDirectory: URL? {
if let url = try? fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) {
2022-12-04 12:21:50 +00:00
return standardizedURL(url)
2022-11-12 23:01:04 +00:00
}
return nil
}
2022-11-18 22:39:52 +00:00
func recentDocuments(_ limit: Int = 10) -> [URL] {
guard let documentsDirectory else { return [] }
return Array(
contents(of: documentsDirectory)
.filter { !isDirectory($0) }
2022-11-18 22:39:52 +00:00
.sorted {
((try? $0.resourceValues(forKeys: [.creationDateKey]).creationDate) ?? Date()) >
((try? $1.resourceValues(forKeys: [.creationDateKey]).creationDate) ?? Date())
}
.prefix(limit)
)
}
2022-11-12 23:01:04 +00:00
func isDocument(_ video: Video) -> Bool {
2022-12-04 12:21:50 +00:00
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return false }
2022-11-12 23:01:04 +00:00
return isDocument(url)
}
func isDocument(_ url: URL) -> Bool {
2022-12-04 12:21:50 +00:00
guard let url = standardizedURL(url), let documentsDirectory else { return false }
2022-11-12 23:01:04 +00:00
return url.absoluteString.starts(with: documentsDirectory.absoluteString)
}
func isDirectory(_ url: URL) -> Bool {
(try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) ?? false
}
var creationDateFormatter: DateFormatter {
let formatter = DateFormatter()
2022-11-19 14:09:09 +00:00
formatter.setLocalizedDateFormatFromTemplate("YYMMddHHmm")
2022-11-12 23:01:04 +00:00
return formatter
}
func creationDate(_ video: Video) -> Date? {
2022-12-04 12:21:50 +00:00
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
2022-11-12 23:01:04 +00:00
return creationDate(url)
}
func creationDate(_ url: URL) -> Date? {
try? url.resourceValues(forKeys: [.creationDateKey]).creationDate
}
func formattedCreationDate(_ video: Video) -> String? {
2022-12-04 12:21:50 +00:00
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
2022-11-12 23:01:04 +00:00
return formattedCreationDate(url)
}
func formattedCreationDate(_ url: URL) -> String? {
if let date = try? url.resourceValues(forKeys: [.creationDateKey]).creationDate {
return creationDateFormatter.string(from: date)
}
return nil
}
var sizeFormatter: ByteCountFormatter {
let formatter = ByteCountFormatter()
formatter.allowedUnits = .useAll
formatter.countStyle = .file
formatter.includesUnit = true
formatter.isAdaptive = true
return formatter
}
func size(_ video: Video) -> Int? {
2022-12-04 12:21:50 +00:00
guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
2022-11-12 23:01:04 +00:00
return size(url)
}
func size(_ url: URL) -> Int? {
try? url.resourceValues(forKeys: [.fileAllocatedSizeKey]).fileAllocatedSize
}
func formattedSize(_ video: Video) -> String? {
guard let size = size(video) else { return nil }
return sizeFormatter.string(fromByteCount: Int64(size))
}
func formattedSize(_ url: URL) -> String? {
guard let size = size(url) else { return nil }
return sizeFormatter.string(fromByteCount: Int64(size))
}
func removeDocument(_ url: URL) throws {
guard isDocument(url) else { return }
try fileManager.removeItem(at: url)
URLBookmarkModel.shared.removeBookmark(url)
refresh()
}
private func contents(of directory: URL) -> [URL] {
(try? fileManager.contentsOfDirectory(
at: directory,
includingPropertiesForKeys: [.creationDateKey, .fileAllocatedSizeKey, .isDirectoryKey],
options: [.includesDirectoriesPostOrder, .skipsHiddenFiles]
)) ?? []
}
2022-12-17 15:18:14 +00:00
func displayLabelForDocument(_ file: URL) -> String {
2022-11-12 23:01:04 +00:00
let components = file.absoluteString.components(separatedBy: "/Documents/")
if components.count == 2 {
let component = components[1]
return component.isEmpty ? "Documents" : component.removingPercentEncoding ?? component
}
return "Document"
}
2022-12-04 12:21:50 +00:00
func standardizedURL(_ url: URL) -> URL? {
let standardizedURL = NSString(string: url.absoluteString).standardizingPath
return URL(string: standardizedURL)
2022-11-12 23:01:04 +00:00
}
func refresh() {
refreshID = UUID()
}
}