Skip to content

Commit 2f94292

Browse files
Show information for non-text files in the status bar (#1713)
* properly name `utilityAreaViewModel` across the project * add article docs for `CodeEdit/UtilityAreaView` * update article docs for `CodeEdit/StatusBarView` * properly name items in `CodeEdit/Features/UtilityArea/Toolbar` * remove UtilityAreaViewModel properties from status bar implementation * remove unused properties in `UtilityAreaViewModel` * delete `CursorLocation` model * rename `StatusBarCursorLocationLabel` to `StatusBarCursorPositionLabel` * add `StatusBarViewModel` * show non-text file info in the status bar * fix unpredictable image dimensions in status bar * add UpdateStatusBarInfo view modifier to clean up implementation * move the `NonTextFileView.onDisappear` modifier to inside the view * change `StatusBarViewModel.dimensions` from tuple to struct * refactor `StatusBarFileInfoView` * fix SwiftLint violation * minor doc change in `UpdateStatusBarInfo` * remove unused editor variable in `UpdateStatusBarInfo` * refactor - stylistic changes - docs change - properly name `UtilityAreaSplitTerminalButton` - remove unused `isBreakpointEnabled` in `StatusBarBreakpointButton` * Update CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarFileInfoView.swift * properly resolve merge conflict I used the GitHub UI, it didn't come out how I expected --------- Co-authored-by: Austin Condiff <[email protected]>
1 parent 60e4b4f commit 2f94292

28 files changed

+370
-192
lines changed

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 60 additions & 32 deletions
Large diffs are not rendered by default.

CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
8989
WorkspaceView()
9090
.environmentObject(workspace)
9191
.environmentObject(workspace.editorManager)
92+
.environmentObject(workspace.statusBarViewModel)
9293
.environmentObject(workspace.utilityAreaModel)
9394
}
9495
}

CodeEdit/Features/Documents/WorkspaceDocument.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate {
3030
}
3131
}
3232

33+
var statusBarViewModel = StatusBarViewModel()
3334
var utilityAreaModel = UtilityAreaViewModel()
3435
var searchState: SearchState?
3536
var quickOpenViewModel: QuickOpenViewModel?

CodeEdit/Features/Editor/Views/EditorAreaFileView.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import SwiftUI
1313
struct EditorAreaFileView: View {
1414

1515
@EnvironmentObject private var editorManager: EditorManager
16-
1716
@EnvironmentObject private var editor: Editor
1817

1918
@Environment(\.edgeInsets)

CodeEdit/Features/Editor/Views/ImageFileView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct ImageFileView: View {
4141
maxWidth: min(pixelWidth, proxy.size.width, nsImage.size.width),
4242
maxHeight: min(pixelHeight, proxy.size.height, nsImage.size.height)
4343
)
44+
4445
}
4546
.frame(width: proxy.size.width, height: proxy.size.height)
4647
}

CodeEdit/Features/Editor/Views/NonTextFileView.swift

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,38 @@ 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+
2023
var body: some View {
2124

22-
if let fileURL = fileDocument.fileURL {
25+
Group {
26+
if let fileURL = fileDocument.fileURL {
2327

24-
switch fileDocument.utType {
25-
case .some(.image):
26-
ImageFileView(fileURL)
28+
switch fileDocument.utType {
29+
case .some(.image):
30+
ImageFileView(fileURL)
31+
.modifier(UpdateStatusBarInfo(withURL: fileURL))
2732

28-
case .some(.pdf):
29-
PDFFileView(fileURL)
33+
case .some(.pdf):
34+
PDFFileView(fileURL)
35+
.modifier(UpdateStatusBarInfo(withURL: fileURL))
3036

31-
default:
32-
AnyFileView(fileURL)
33-
}
37+
default:
38+
AnyFileView(fileURL)
39+
.modifier(UpdateStatusBarInfo(withURL: fileURL))
40+
}
3441

35-
} else {
36-
ZStack {
37-
Text("Cannot retrieve URL to the file you opened.")
42+
} else {
43+
ZStack {
44+
Text("Cannot retrieve URL to the file you opened.")
45+
}
3846
}
3947
}
48+
.onDisappear {
49+
statusBarViewModel.dimensions = nil
50+
statusBarViewModel.fileSize = nil
51+
}
4052

4153
}
4254
}

CodeEdit/Features/StatusBar/Models/CursorLocation.swift

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//
2+
// ImageDimensions.swift
3+
// CodeEdit
4+
//
5+
// Created by Paul Ebose on 2024/5/13.
6+
//
7+
8+
import Foundation
9+
10+
/// Helper struct used to store the (width x height) of the currently opened image.
11+
struct ImageDimensions {
12+
var width: Int
13+
var height: Int
14+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// StatusBarViewModel.swift
3+
// CodeEdit
4+
//
5+
// Created by Paul Ebose on 2024/5/12.
6+
//
7+
8+
import SwiftUI
9+
10+
final class StatusBarViewModel: ObservableObject {
11+
12+
/// The file size of the currently opened file.
13+
@Published var fileSize: Int?
14+
15+
/// The dimensions (width x height) of the currently opened image.
16+
@Published var dimensions: ImageDimensions?
17+
18+
/// Indicates whether the breakpoint is enabled or not.
19+
@Published var isBreakpointEnabled = true
20+
21+
/// The font style of items shown in the status bar.
22+
private(set) var statusBarFont = Font.system(size: 11, weight: .medium)
23+
24+
/// The color of the text shown in the status bar.
25+
private(set) var foregroundStyle = Color.secondary
26+
27+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// UpdateStatusBarInfo.swift
3+
// CodeEdit
4+
//
5+
// Created by Paul Ebose on 2024/5/12.
6+
//
7+
8+
import SwiftUI
9+
10+
/// Updates ``StatusBarFileInfoView``'s `fileSize` and `dimensions`.
11+
/// ```swift
12+
/// FileView
13+
/// .modifier(UpdateStatusBarInfo(withURL))
14+
/// ```
15+
struct UpdateStatusBarInfo: ViewModifier {
16+
17+
/// The URL of the file to compute information from.
18+
let withURL: URL
19+
20+
@EnvironmentObject private var editorManager: EditorManager
21+
@EnvironmentObject private var statusBarViewModel: StatusBarViewModel
22+
23+
/// This is returned by ``UpdateStatusBarInfo`` `.computeStatusBarInfo`.
24+
private struct ComputedStatusBarInfo {
25+
let fileSize: Int
26+
let dimensions: ImageDimensions?
27+
}
28+
29+
/// Compute information that can be used to update properties in ``StatusBarFileInfoView``.
30+
/// - Parameter url: URL of the file to compute information from.
31+
/// - 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]),
34+
let contentType = resourceValues.contentType,
35+
let fileSize = resourceValues.fileSize
36+
else {
37+
return nil
38+
}
39+
40+
if contentType.conforms(to: .image), let imageReps = NSImage(contentsOf: url)?.representations.first {
41+
let dimensions = ImageDimensions(width: imageReps.pixelsWide, height: imageReps.pixelsHigh)
42+
return ComputedStatusBarInfo(fileSize: fileSize, dimensions: dimensions)
43+
} else { // non-image file
44+
return ComputedStatusBarInfo(fileSize: fileSize, dimensions: nil)
45+
}
46+
}
47+
48+
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+
}
61+
}
62+
63+
}

0 commit comments

Comments
 (0)