Skip to content

Commit 2e4bec8

Browse files
authored
Correctly view non-text files in single file window and Open Quickly (#1820)
* add `updateStatusBarInfo` view modifier * fix QuickLook previews in single file window * change `fileURL` type to `NSURL` in `AnyFileView` * fix QuickLook previews in Open Quickly Use `dismantleNSView` in `AnyFileView` to prevent crashes when using Open Quickly. What crashes? 1. When using Open Quickly without the workaround in `AnyFileView`, search for a media file (.png, .gif, .mp4, etc) 2. Press escape to close Open Quickly 3. re-open Open Quickly. The media preview is gone 4. Attempt to navigate upwards or downwards using the arrow buttons 5. A crash occurs (QuickLook is attempting to reuse an already closed preview) * add assertionFailure in `CodeEditWindowController.openQuickly` for when an editorManager or statusBarViewModel is unavailable * make `UpdateStatusBarInfo.fileURL` an optional * remove the need to pass environment objects to `NonTextFileView` This also prevents Open Quickly previews from updating the status bar * rename function parameters in `UpdateStatusBarInfo` view modifier * remove `updateStatusBarInfo` view extension * remove guard in `CodeEditWindowController.openQuickly` editorManager and statusBarViewModel environment objects are not used in Open Quickly anymore * merge #1822 fix into this branch allow files with a utType that is neither image nor PDF to be previewed (#1822)
1 parent 96c3165 commit 2e4bec8

File tree

7 files changed

+48
-51
lines changed

7 files changed

+48
-51
lines changed

CodeEdit/Features/Editor/Views/AnyFileView.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,27 @@ import QuickLookUI
1717
struct AnyFileView: NSViewRepresentable {
1818

1919
/// URL of the file to preview. You can pass in any file type.
20-
private let fileURL: URL
20+
private let fileURL: NSURL
2121

2222
init(_ fileURL: URL) {
23-
self.fileURL = fileURL
23+
self.fileURL = fileURL as NSURL
2424
}
2525

2626
func makeNSView(context: Context) -> QLPreviewView {
2727
let qlPreviewView = QLPreviewView()
28-
qlPreviewView.previewItem = fileURL as any QLPreviewItem
28+
qlPreviewView.previewItem = fileURL
29+
qlPreviewView.shouldCloseWithWindow = false // Temp work around for something more reasonable.
2930
return qlPreviewView
3031
}
3132

3233
func updateNSView(_ qlPreviewView: QLPreviewView, context: Context) {
33-
qlPreviewView.previewItem = fileURL as any QLPreviewItem
34+
qlPreviewView.previewItem = fileURL
3435
}
3536

37+
// Temp work around for something more reasonable.
38+
// Open quickly should empty the results (but cache the query) when closed,
39+
// and then re-search or recompute the results when re-opened.
40+
static func dismantleNSView(_ qlPreviewView: QLPreviewView, coordinator: ()) {
41+
qlPreviewView.close()
42+
}
3643
}

CodeEdit/Features/Editor/Views/CodeFileView.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ struct CodeFileView: View {
4646
@Environment(\.colorScheme)
4747
private var colorScheme
4848

49-
@EnvironmentObject private var editorManager: EditorManager
50-
5149
@ObservedObject private var themeModel: ThemeModel = .shared
5250

5351
private var cancellables = Set<AnyCancellable>()
@@ -105,8 +103,6 @@ struct CodeFileView: View {
105103
@Environment(\.edgeInsets)
106104
private var edgeInsets
107105

108-
@EnvironmentObject private var editor: Editor
109-
110106
var body: some View {
111107
CodeEditSourceEditor(
112108
codeFile.content ?? NSTextStorage(),

CodeEdit/Features/Editor/Views/EditorAreaFileView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct EditorAreaFileView: View {
1414

1515
@EnvironmentObject private var editorManager: EditorManager
1616
@EnvironmentObject private var editor: Editor
17+
@EnvironmentObject private var statusBarViewModel: StatusBarViewModel
1718

1819
@Environment(\.edgeInsets)
1920
private var edgeInsets
@@ -32,6 +33,11 @@ struct EditorAreaFileView: View {
3233
NonTextFileView(fileDocument: document)
3334
.padding(.top, edgeInsets.top - 1.74) // Use the magic number to fine-tune its appearance.
3435
.padding(.bottom, StatusBarView.height + 1.26) // Use the magic number to fine-tune its appearance.
36+
.modifier(UpdateStatusBarInfo(with: document.fileURL))
37+
.onDisappear {
38+
statusBarViewModel.dimensions = nil
39+
statusBarViewModel.fileSize = nil
40+
}
3541
}
3642

3743
} else {

CodeEdit/Features/Editor/Views/NonTextFileView.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,26 @@ struct NonTextFileView: View {
1717
/// The file document you wish to open.
1818
let fileDocument: CodeFileDocument
1919

20-
@EnvironmentObject private var editorManager: EditorManager
21-
@EnvironmentObject private var statusBarViewModel: StatusBarViewModel
22-
2320
var body: some View {
2421
Group {
2522
if let fileURL = fileDocument.fileURL {
26-
if let utType = fileDocument.utType {
2723

24+
if let utType = fileDocument.utType {
2825
if utType.conforms(to: .image) {
2926
ImageFileView(fileURL)
30-
.modifier(UpdateStatusBarInfo(withURL: fileURL))
3127
} else if utType.conforms(to: .pdf) {
3228
PDFFileView(fileURL)
33-
.modifier(UpdateStatusBarInfo(withURL: fileURL))
3429
} else {
3530
AnyFileView(fileURL)
36-
.modifier(UpdateStatusBarInfo(withURL: fileURL))
3731
}
3832
} else {
3933
AnyFileView(fileURL)
40-
.modifier(UpdateStatusBarInfo(withURL: fileURL))
4134
}
4235
} else {
4336
ZStack {
4437
Text("Cannot retrieve URL to the file you opened.")
4538
}
4639
}
4740
}
48-
.onDisappear {
49-
statusBarViewModel.dimensions = nil
50-
statusBarViewModel.fileSize = nil
51-
}
5241
}
5342
}

CodeEdit/Features/Editor/Views/WindowCodeFileView.swift

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,11 @@ import SwiftUI
1313
struct WindowCodeFileView: View {
1414
var codeFile: CodeFileDocument
1515

16-
@State var hasAppeared = false
17-
@FocusState var focused: Bool
18-
1916
var body: some View {
20-
Group {
21-
if !hasAppeared {
22-
Color.clear.onAppear {
23-
hasAppeared = true
24-
focused = true
25-
}
26-
} else {
27-
CodeFileView(codeFile: codeFile)
28-
.focused($focused)
29-
}
17+
if let utType = codeFile.utType, utType.conforms(to: .text) {
18+
CodeFileView(codeFile: codeFile)
19+
} else {
20+
NonTextFileView(fileDocument: codeFile)
3021
}
3122
}
3223
}

CodeEdit/Features/OpenQuickly/Views/OpenQuicklyPreviewView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct OpenQuicklyPreviewView: View {
1919
let doc = try? CodeFileDocument(
2020
for: item.url,
2121
withContentsOf: item.url,
22-
ofType: "public.source-code"
22+
ofType: item.contentType?.identifier ?? "public.source-code"
2323
)
2424
self._document = .init(wrappedValue: doc ?? .init())
2525
}

CodeEdit/Features/StatusBar/ViewModifiers/UpdateStatusBarInfo.swift

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ import SwiftUI
1515
struct UpdateStatusBarInfo: ViewModifier {
1616

1717
/// The URL of the file to compute information from.
18-
let withURL: URL
18+
let fileURL: URL?
19+
20+
init(with fileURL: URL?) {
21+
self.fileURL = fileURL
22+
}
1923

2024
@EnvironmentObject private var editorManager: EditorManager
2125
@EnvironmentObject private var statusBarViewModel: StatusBarViewModel
@@ -27,17 +31,17 @@ struct UpdateStatusBarInfo: ViewModifier {
2731
}
2832

2933
/// Compute information that can be used to update properties in ``StatusBarFileInfoView``.
30-
/// - Parameter url: URL of the file to compute information from.
34+
/// - Parameter with fileURL: URL of the file to compute information from.
3135
/// - Returns: The file size and its image dimensions (if any).
32-
private func computeStatusBarInfo(url: URL) -> ComputedStatusBarInfo? {
33-
guard let resourceValues = try? url.resourceValues(forKeys: [.contentTypeKey, .fileSizeKey]),
36+
private func computeStatusBarInfo(with fileURL: URL) -> ComputedStatusBarInfo? {
37+
guard let resourceValues = try? fileURL.resourceValues(forKeys: [.contentTypeKey, .fileSizeKey]),
3438
let contentType = resourceValues.contentType,
3539
let fileSize = resourceValues.fileSize
3640
else {
3741
return nil
3842
}
3943

40-
if contentType.conforms(to: .image), let imageReps = NSImage(contentsOf: url)?.representations.first {
44+
if contentType.conforms(to: .image), let imageReps = NSImage(contentsOf: fileURL)?.representations.first {
4145
let dimensions = ImageDimensions(width: imageReps.pixelsWide, height: imageReps.pixelsHigh)
4246
return ComputedStatusBarInfo(fileSize: fileSize, dimensions: dimensions)
4347
} else { // non-image file
@@ -46,18 +50,22 @@ struct UpdateStatusBarInfo: ViewModifier {
4650
}
4751

4852
func body(content: Content) -> some View {
49-
content
50-
.onAppear {
51-
let statusBarInfo = computeStatusBarInfo(url: withURL)
52-
statusBarViewModel.fileSize = statusBarInfo?.fileSize
53-
statusBarViewModel.dimensions = statusBarInfo?.dimensions
54-
}
55-
.onChange(of: editorManager.activeEditor.selectedTab) { newTab in
56-
guard let newTab else { return }
57-
let statusBarInfo = computeStatusBarInfo(url: newTab.file.url)
58-
statusBarViewModel.fileSize = statusBarInfo?.fileSize
59-
statusBarViewModel.dimensions = statusBarInfo?.dimensions
60-
}
53+
if let fileURL {
54+
content
55+
.onAppear {
56+
let statusBarInfo = computeStatusBarInfo(with: fileURL)
57+
statusBarViewModel.fileSize = statusBarInfo?.fileSize
58+
statusBarViewModel.dimensions = statusBarInfo?.dimensions
59+
}
60+
.onChange(of: editorManager.activeEditor.selectedTab) { newTab in
61+
guard let newTab else { return }
62+
let statusBarInfo = computeStatusBarInfo(with: newTab.file.url)
63+
statusBarViewModel.fileSize = statusBarInfo?.fileSize
64+
statusBarViewModel.dimensions = statusBarInfo?.dimensions
65+
}
66+
} else {
67+
content
68+
}
6169
}
6270

6371
}

0 commit comments

Comments
 (0)