Skip to content

Commit 0200c87

Browse files
Fix Tab State, Add Window Restoration (#1368)
1 parent d5a44c7 commit 0200c87

24 files changed

+353
-100
lines changed

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@
246246
6C049A372A49E2DB00D42923 /* DirectoryEventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C049A362A49E2DB00D42923 /* DirectoryEventStream.swift */; };
247247
6C05A8AF284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */; };
248248
6C092EC62A4E803300489202 /* CodeEditTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 6C092EC52A4E803300489202 /* CodeEditTextView */; };
249+
6C092EDA2A53A58600489202 /* TabGroup+StateRestoration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C092ED92A53A58600489202 /* TabGroup+StateRestoration.swift */; };
250+
6C092EE02A53BFCF00489202 /* WorkspaceStateKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C092EDF2A53BFCF00489202 /* WorkspaceStateKey.swift */; };
249251
6C0D0C6829E861B000AE4D3F /* SettingsSidebarFix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0D0C6729E861B000AE4D3F /* SettingsSidebarFix.swift */; };
250252
6C0F3A3C2A1D0D5000223D19 /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */; };
251253
6C147C4029A328BC0089B630 /* SplitViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C3F29A328560089B630 /* SplitViewData.swift */; };
@@ -703,6 +705,8 @@
703705
5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = "<group>"; };
704706
6C049A362A49E2DB00D42923 /* DirectoryEventStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectoryEventStream.swift; sourceTree = "<group>"; };
705707
6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+Listeners.swift"; sourceTree = "<group>"; };
708+
6C092ED92A53A58600489202 /* TabGroup+StateRestoration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TabGroup+StateRestoration.swift"; sourceTree = "<group>"; };
709+
6C092EDF2A53BFCF00489202 /* WorkspaceStateKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceStateKey.swift; sourceTree = "<group>"; };
706710
6C0D0C6729E861B000AE4D3F /* SettingsSidebarFix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSidebarFix.swift; sourceTree = "<group>"; };
707711
6C147C3D29A3281D0089B630 /* TabGroupData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabGroupData.swift; sourceTree = "<group>"; };
708712
6C147C3E29A3281D0089B630 /* TabGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabGroup.swift; sourceTree = "<group>"; };
@@ -903,6 +907,7 @@
903907
043C321527E3201F006AE443 /* WorkspaceDocument.swift */,
904908
043BCF02281DA18A000AC47C /* WorkspaceDocument+Search.swift */,
905909
6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */,
910+
6C092EDF2A53BFCF00489202 /* WorkspaceStateKey.swift */,
906911
);
907912
path = Documents;
908913
sourceTree = "<group>";
@@ -2025,30 +2030,47 @@
20252030
name = Frameworks;
20262031
sourceTree = "<group>";
20272032
};
2033+
6C092EDC2A53A63E00489202 /* Views */ = {
2034+
isa = PBXGroup;
2035+
children = (
2036+
6C147C4829A32A080089B630 /* EditorView.swift */,
2037+
6C53AAD729A6C4FD00EE9ED6 /* SplitView.swift */,
2038+
6C2C156029B4F52F00EA60A5 /* SplitViewModifiers.swift */,
2039+
6C2C155C29B4F4E500EA60A5 /* SplitViewReader.swift */,
2040+
6C2C155929B4F4CC00EA60A5 /* Variadic.swift */,
2041+
6C7256D629A3D7D000C2D3E0 /* SplitViewControllerView.swift */,
2042+
);
2043+
path = Views;
2044+
sourceTree = "<group>";
2045+
};
2046+
6C092EDD2A53A64900489202 /* Model */ = {
2047+
isa = PBXGroup;
2048+
children = (
2049+
6C147C4A29A32A7B0089B630 /* Environment+SplitEditor.swift */,
2050+
6C5228B429A868BD00AC48F6 /* Environment+ContentInsets.swift */,
2051+
6C2C155729B4F49100EA60A5 /* SplitViewItem.swift */,
2052+
6C147C3F29A328560089B630 /* SplitViewData.swift */,
2053+
);
2054+
path = Model;
2055+
sourceTree = "<group>";
2056+
};
20282057
6C147C3C29A328020089B630 /* TabGroup */ = {
20292058
isa = PBXGroup;
20302059
children = (
20312060
6C147C4C29A32AA30089B630 /* WorkspaceTabGroupView.swift */,
20322061
6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */,
20332062
6C147C3E29A3281D0089B630 /* TabGroup.swift */,
20342063
6C147C3D29A3281D0089B630 /* TabGroupData.swift */,
2064+
6C092ED92A53A58600489202 /* TabGroup+StateRestoration.swift */,
20352065
);
20362066
path = TabGroup;
20372067
sourceTree = "<group>";
20382068
};
20392069
6C147C4729A329E50089B630 /* SplitView */ = {
20402070
isa = PBXGroup;
20412071
children = (
2042-
6C147C4A29A32A7B0089B630 /* Environment+SplitEditor.swift */,
2043-
6C5228B429A868BD00AC48F6 /* Environment+ContentInsets.swift */,
2044-
6C147C4829A32A080089B630 /* EditorView.swift */,
2045-
6C53AAD729A6C4FD00EE9ED6 /* SplitView.swift */,
2046-
6C2C156029B4F52F00EA60A5 /* SplitViewModifiers.swift */,
2047-
6C2C155C29B4F4E500EA60A5 /* SplitViewReader.swift */,
2048-
6C2C155929B4F4CC00EA60A5 /* Variadic.swift */,
2049-
6C7256D629A3D7D000C2D3E0 /* SplitViewControllerView.swift */,
2050-
6C2C155729B4F49100EA60A5 /* SplitViewItem.swift */,
2051-
6C147C3F29A328560089B630 /* SplitViewData.swift */,
2072+
6C092EDD2A53A64900489202 /* Model */,
2073+
6C092EDC2A53A63E00489202 /* Views */,
20522074
);
20532075
path = SplitView;
20542076
sourceTree = "<group>";
@@ -2911,6 +2933,8 @@
29112933
B6F0517729D9E3AD00D72287 /* SourceControlGeneralView.swift in Sources */,
29122934
587B9E8929301D8F00AC7927 /* GitHubGist.swift in Sources */,
29132935
0485EB1F27E7458B00138301 /* WorkspaceCodeFileView.swift in Sources */,
2936+
6C092EDA2A53A58600489202 /* TabGroup+StateRestoration.swift in Sources */,
2937+
6C092EE02A53BFCF00489202 /* WorkspaceStateKey.swift in Sources */,
29142938
58D01C94293167DC00C5B6B4 /* Color+HEX.swift in Sources */,
29152939
6C578D8729CD345900DC73B2 /* ExtensionSceneView.swift in Sources */,
29162940
B640A9A129E2188F00715F20 /* View+NavigationBarBackButtonVisible.swift in Sources */,

CodeEdit/Features/CodeFile/CodeFile.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,26 @@ final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem {
8585

8686
override func makeWindowControllers() {
8787
let window = NSWindow(
88-
contentRect: NSRect(x: 0, y: 0, width: 1400, height: 600),
88+
contentRect: NSRect(x: 0, y: 0, width: 750, height: 800),
8989
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
9090
backing: .buffered, defer: false
9191
)
9292
let windowController = NSWindowController(window: window)
93+
if let fileURL {
94+
windowController.shouldCascadeWindows = false
95+
windowController.windowFrameAutosaveName = fileURL.path
96+
}
9397
addWindowController(windowController)
9498

9599
window.contentView = NSHostingView(rootView: SettingsInjector {
96100
WindowCodeFileView(codeFile: self)
97101
})
98102

99103
window.makeKeyAndOrderFront(nil)
100-
window.center()
104+
105+
if let fileURL, UserDefaults.standard.object(forKey: "NSWindow Frame \(fileURL.path)") == nil {
106+
window.center()
107+
}
101108
}
102109

103110
override func data(ofType _: String) throws -> Data {

CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ import SwiftUI
1212
/// A model class to host and manage data for the ``StatusBarView``
1313
///
1414
class DebugAreaViewModel: ObservableObject {
15-
private let isDebugAreaViewCollapsedStateName: String
16-
= "\(String(describing: DebugAreaViewModel.self))-IsDebugAreaViewCollapsed"
17-
private let statusBarDrawerHeightStateName: String
18-
= "\(String(describing: DebugAreaViewModel.self))-DebugAreaViewHeight"
19-
2015
/// Returns the current location of the cursor in an editing view
2116
@Published var cursorLocation: CursorLocation = .init(line: 1, column: 1) // Implementation needed!!
2217

@@ -45,16 +40,6 @@ class DebugAreaViewModel: ObservableObject {
4540
/// Returns the font for status bar items to use
4641
private(set) var toolbarFont: Font = .system(size: 11, weight: .medium)
4742

48-
/// The maximum height of the drawer
49-
/// when isMaximized is true the height gets set to maxHeight
50-
private(set) var maxHeight: Double = 5000
51-
52-
/// The default height of the drawer
53-
private(set) var standardHeight: Double = 300
54-
55-
/// The minimum height of the drawer
56-
private(set) var minHeight: Double = 100
57-
5843
func removeTerminals(_ ids: Set<UUID>) {
5944
terminals.removeAll(where: { terminal in
6045
ids.contains(terminal.id)
@@ -63,7 +48,15 @@ class DebugAreaViewModel: ObservableObject {
6348
selectedTerminals = [terminals.last?.id ?? UUID()]
6449
}
6550

66-
init() {
67-
// !!!: Lots of things in this class can be removed, such as maxHeight, as they are defined in the UI.
51+
func restoreFromState(_ workspace: WorkspaceDocument) {
52+
isCollapsed = workspace.getFromWorkspaceState(.debugAreaCollapsed) as? Bool ?? false
53+
currentHeight = workspace.getFromWorkspaceState(.debugAreaHeight) as? Double ?? 300.0
54+
isMaximized = workspace.getFromWorkspaceState(.debugAreaMaximized) as? Bool ?? false
55+
}
56+
57+
func saveRestorationState(_ workspace: WorkspaceDocument) {
58+
workspace.addToWorkspaceState(key: .debugAreaCollapsed, value: isCollapsed)
59+
workspace.addToWorkspaceState(key: .debugAreaHeight, value: currentHeight)
60+
workspace.addToWorkspaceState(key: .debugAreaMaximized, value: isMaximized)
6861
}
6962
}

CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ private extension CGFloat {
2727

2828
final class CodeEditSplitViewController: NSSplitViewController {
2929
private var workspace: WorkspaceDocument
30-
private let widthStateName: String = "\(String(describing: CodeEditSplitViewController.self))-Width"
31-
private let isNavigatorCollapsedStateName: String
32-
= "\(String(describing: CodeEditSplitViewController.self))-IsNavigatorCollapsed"
33-
private let isInspectorCollapsedStateName: String
34-
= "\(String(describing: CodeEditSplitViewController.self))-IsInspectorCollapsed"
3530
private var setWidthFromState = false
3631
private var viewIsReady = false
3732

@@ -64,19 +59,19 @@ final class CodeEditSplitViewController: NSSplitViewController {
6459
super.viewWillAppear()
6560

6661
viewIsReady = false
67-
let width = workspace.getFromWorkspaceState(key: self.widthStateName) as? CGFloat
62+
let width = workspace.getFromWorkspaceState(.splitViewWidth) as? CGFloat
6863
splitView.setPosition(width ?? .snapWidth, ofDividerAt: .zero)
6964
setWidthFromState = true
7065

7166
if let firstSplitView = splitViewItems.first {
7267
firstSplitView.isCollapsed = workspace.getFromWorkspaceState(
73-
key: isNavigatorCollapsedStateName
68+
.navigatorCollapsed
7469
) as? Bool ?? false
7570
}
7671

7772
if let lastSplitView = splitViewItems.last {
7873
lastSplitView.isCollapsed = workspace.getFromWorkspaceState(
79-
key: isInspectorCollapsedStateName
74+
.inspectorCollapsed
8075
) as? Bool ?? true
8176
}
8277

@@ -131,17 +126,17 @@ final class CodeEditSplitViewController: NSSplitViewController {
131126
let panel = splitView.subviews[0]
132127
let width = panel.frame.size.width
133128
if width > 0 && setWidthFromState {
134-
workspace.addToWorkspaceState(key: self.widthStateName, value: width)
129+
workspace.addToWorkspaceState(key: .splitViewWidth, value: width)
135130
}
136131
}
137132
}
138133

139134
func saveNavigatorCollapsedState(isCollapsed: Bool) {
140-
workspace.addToWorkspaceState(key: isNavigatorCollapsedStateName, value: isCollapsed)
135+
workspace.addToWorkspaceState(key: .navigatorCollapsed, value: isCollapsed)
141136
}
142137

143138
func saveInspectorCollapsedState(isCollapsed: Bool) {
144-
workspace.addToWorkspaceState(key: isInspectorCollapsedStateName, value: isCollapsed)
139+
workspace.addToWorkspaceState(key: .inspectorCollapsed, value: isCollapsed)
145140
}
146141

147142
/// Quick fix for list tracking separator needing to be added again after closing,

CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
2525
init(window: NSWindow, workspace: WorkspaceDocument) {
2626
super.init(window: window)
2727
self.workspace = workspace
28-
2928
setupSplitView(with: workspace)
3029

3130
let view = CodeEditSplitView(controller: splitViewController).ignoresSafeArea()
@@ -189,15 +188,15 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
189188
) -> NSToolbarItem? {
190189
switch itemIdentifier {
191190
case .itemListTrackingSeparator:
192-
guard let splitViewController else {
193-
return nil
194-
}
191+
guard let splitViewController else {
192+
return nil
193+
}
195194

196-
return NSTrackingSeparatorToolbarItem(
197-
identifier: .itemListTrackingSeparator,
198-
splitView: splitViewController.splitView,
199-
dividerIndex: 1
200-
)
195+
return NSTrackingSeparatorToolbarItem(
196+
identifier: .itemListTrackingSeparator,
197+
splitView: splitViewController.splitView,
198+
dividerIndex: 1
199+
)
201200
case .toggleFirstSidebarItem:
202201
let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.toggleFirstSidebarItem)
203202
toolbarItem.label = "Navigator Sidebar"
@@ -242,10 +241,6 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
242241
}
243242
}
244243

245-
override func windowDidLoad() {
246-
super.windowDidLoad()
247-
}
248-
249244
private func getSelectedCodeFile() -> CodeFileDocument? {
250245
workspace?.tabManager.activeTabGroup.selected?.fileDocument
251246
}

CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ struct WorkspaceCodeFileView: View {
1616

1717
var file: CEWorkspaceFile
1818

19+
@State private var update: Bool = false
20+
1921
@ViewBuilder var codeView: some View {
2022
if let document = file.fileDocument {
2123
Group {
@@ -28,12 +30,30 @@ struct WorkspaceCodeFileView: View {
2830
}
2931
.frame(maxWidth: .infinity, maxHeight: .infinity)
3032
} else {
33+
if update {
34+
Spacer()
35+
}
3136
Spacer()
3237
VStack(spacing: 10) {
3338
ProgressView()
3439
Text("Opening \(file.name)...")
3540
}
3641
Spacer()
42+
.onAppear {
43+
Task.detached {
44+
let contentType = try await file.url.resourceValues(forKeys: [.contentTypeKey]).contentType
45+
let codeFile = try await CodeFileDocument(
46+
for: file.url,
47+
withContentsOf: file.url,
48+
ofType: contentType?.identifier ?? ""
49+
)
50+
await MainActor.run {
51+
file.fileDocument = codeFile
52+
CodeEditDocumentController.shared.addDocument(codeFile)
53+
update.toggle()
54+
}
55+
}
56+
}
3757
}
3858
}
3959

0 commit comments

Comments
 (0)