-
Notifications
You must be signed in to change notification settings - Fork 16
/
MainVC.swift
130 lines (116 loc) Β· 3.31 KB
/
MainVC.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import Cocoa
import os.log
import Quartz
enum PreviewError: Error {
case fileSizeError(path: String)
}
extension PreviewError: LocalizedError {
public var errorDescription: String? {
switch self {
case let .fileSizeError(path):
return NSLocalizedString("File \(path) is too large to preview", comment: "")
}
}
}
class MainVC: NSViewController, QLPreviewingController {
/// Max size of files to render
let maxFileSize = 10_000_000 // 10 MB
let stats = Stats()
override var nibName: NSNib.Name? {
NSNib.Name("MainVC")
}
override func viewDidLoad() {
super.viewDidLoad()
setUpView()
}
private func setUpView() {
// Draw border around previews, in similar style to macOS's default previews
view.wantsLayer = true
view.layer?.borderWidth = 1
view.layer?.borderColor = NSColor.tertiaryLabelColor.cgColor
}
/// Function responsible for generating file previews. It's called for previews in Finder,
/// Spotlight, Quick Look and any other UI elements which implement the API.
func preparePreviewOfFile(
at fileUrl: URL,
completionHandler handler: @escaping (Error?) -> Void
) {
DispatchQueue.main.async {
// Read information about the file to preview
var file: File
do {
file = try File(url: fileUrl)
} catch {
os_log(
"Could not obtain information about file %{public}s: %{public}s",
log: Log.general,
type: .error,
fileUrl.path,
error.localizedDescription
)
handler(error)
return
}
// Skip preview if the file is too large
if !file.isDirectory, !file.isArchive, file.size > self.maxFileSize {
// Log error and fall back to default preview (by calling the completion handler
// with the error)
let error = PreviewError.fileSizeError(path: file.path)
os_log(
"Skipping file preview: %{public}s",
log: Log.general,
error.localizedDescription
)
handler(error)
return
}
// Render file preview
os_log(
"Generating preview for file %{public}s",
log: Log.general,
type: .info,
file.path
)
do {
try self.previewFile(file: file)
} catch {
// Log error and fall back to default preview (by calling the completion handler
// with the error)
os_log(
"Could not generate preview for file %{public}s: %{public}s",
log: Log.general,
type: .error,
file.path,
error.localizedDescription
)
handler(error)
return
}
// Hide preview loading spinner
handler(nil)
}
}
/// Generates a preview of the selected file and adds the corresponding child view controller.
private func previewFile(file: File) throws {
// Initialize `PreviewVC` for the file type
if let previewInitializerType = PreviewVCFactory.getPreviewInitializer(fileURL: file.url) {
// Generate file preview
let previewInitializer = previewInitializerType.init()
let previewVC = try previewInitializer.createPreviewVC(file: file)
// Add `PreviewVC` as a child view controller
addChild(previewVC)
previewVC.view.autoresizingMask = [.height, .width]
previewVC.view.frame = view.bounds
view.addSubview(previewVC.view)
// Update stats
stats.increaseStatsCounts(fileExtension: file.url.pathExtension)
} else {
os_log(
"Skipping preview for file %{public}s: File type not supported",
log: Log.general,
type: .info,
file.path
)
}
}
}