mirror of
				https://github.com/yattee/yattee.git
				synced 2025-10-31 20:52:04 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			167 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
| 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 }
 | |
|         ]
 | |
|     }
 | |
| 
 | |
|     func sortedDirectoryContents(_ directoryURL: URL) -> [URL] {
 | |
|         directoryContents(directoryURL).sorted { lhs, rhs in
 | |
|             for predicate in sortPredicates {
 | |
|                 if !predicate(lhs, rhs), !predicate(rhs, lhs) {
 | |
|                     continue
 | |
|                 }
 | |
| 
 | |
|                 return predicate(lhs, rhs)
 | |
|             }
 | |
| 
 | |
|             return false
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     func directoryContents(_ directoryURL: URL) -> [URL] {
 | |
|         contents(of: directoryURL)
 | |
|     }
 | |
| 
 | |
|     var documentsDirectory: URL? {
 | |
|         if let url = try? fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) {
 | |
|             return standardizedURL(url)
 | |
|         }
 | |
|         return nil
 | |
|     }
 | |
| 
 | |
|     func recentDocuments(_ limit: Int = 10) -> [URL] {
 | |
|         guard let documentsDirectory else { return [] }
 | |
| 
 | |
|         return Array(
 | |
|             contents(of: documentsDirectory)
 | |
|                 .filter { !isDirectory($0) }
 | |
|                 .sorted {
 | |
|                     ((try? $0.resourceValues(forKeys: [.creationDateKey]).creationDate) ?? Date()) >
 | |
|                         ((try? $1.resourceValues(forKeys: [.creationDateKey]).creationDate) ?? Date())
 | |
|                 }
 | |
|                 .prefix(limit)
 | |
|         )
 | |
|     }
 | |
| 
 | |
|     func isDocument(_ video: Video) -> Bool {
 | |
|         guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return false }
 | |
|         return isDocument(url)
 | |
|     }
 | |
| 
 | |
|     func isDocument(_ url: URL) -> Bool {
 | |
|         guard let url = standardizedURL(url), let documentsDirectory else { return false }
 | |
|         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()
 | |
| 
 | |
|         formatter.setLocalizedDateFormatFromTemplate("YYMMddHHmm")
 | |
| 
 | |
|         return formatter
 | |
|     }
 | |
| 
 | |
|     func creationDate(_ video: Video) -> Date? {
 | |
|         guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
 | |
|         return creationDate(url)
 | |
|     }
 | |
| 
 | |
|     func creationDate(_ url: URL) -> Date? {
 | |
|         try? url.resourceValues(forKeys: [.creationDateKey]).creationDate
 | |
|     }
 | |
| 
 | |
|     func formattedCreationDate(_ video: Video) -> String? {
 | |
|         guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
 | |
|         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? {
 | |
|         guard video.isLocal, let url = video.localStream?.localURL, let url = standardizedURL(url) else { return nil }
 | |
|         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]
 | |
|         )) ?? []
 | |
|     }
 | |
| 
 | |
|     func displayLabelForDocument(_ file: URL) -> String {
 | |
|         let components = file.absoluteString.components(separatedBy: "/Documents/")
 | |
|         if components.count == 2 {
 | |
|             let component = components[1]
 | |
|             return component.isEmpty ? "Documents" : component.removingPercentEncoding ?? component
 | |
|         }
 | |
|         return "Document"
 | |
|     }
 | |
| 
 | |
|     func standardizedURL(_ url: URL) -> URL? {
 | |
|         let standardizedURL = NSString(string: url.absoluteString).standardizingPath
 | |
|         return URL(string: standardizedURL)
 | |
|     }
 | |
| 
 | |
|     func refresh() {
 | |
|         refreshID = UUID()
 | |
|     }
 | |
| }
 | 
