From be53359bc4f9263c5bf166d11540cc0b997a817f Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Mon, 16 Jan 2023 10:24:01 -0600 Subject: [PATCH 01/11] Initial Workspace State logic --- .../CodeEditSplitViewController.swift | 31 ++++++++++++++++--- .../CodeEditWindowController.swift | 2 +- .../Documents/WorkspaceDocument.swift | 19 ++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index bd43c4876..d5febf1c6 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -15,6 +15,10 @@ private extension CGFloat { } final class CodeEditSplitViewController: NSSplitViewController { + private var workspace: WorkspaceDocument + private let widthStateName: String = "\(String(describing: CodeEditSplitViewController.self))-Width" + private var setWidthFromState = false + // Properties private(set) var isSnapped: Bool = false { willSet { @@ -29,7 +33,8 @@ final class CodeEditSplitViewController: NSSplitViewController { // MARK: - Initialization - init(feedbackPerformer: NSHapticFeedbackPerformer) { + init(workspace: WorkspaceDocument, feedbackPerformer: NSHapticFeedbackPerformer) { + self.workspace = workspace self.feedbackPerformer = feedbackPerformer super.init(nibName: nil, bundle: nil) } @@ -39,10 +44,12 @@ final class CodeEditSplitViewController: NSSplitViewController { fatalError("init(coder:) has not been implemented") } - // TODO: Set user preferences width if it is not the snap width -// override func viewWillAppear() { -// super.viewWillAppear() -// } + override func viewWillAppear() { + super.viewWillAppear() + let width = workspace.getFromWorkspaceState(key: self.widthStateName) as? CGFloat ?? 0 + splitView.setPosition(width, ofDividerAt: .zero) + setWidthFromState = true + } // MARK: - NSSplitViewDelegate @@ -78,6 +85,20 @@ final class CodeEditSplitViewController: NSSplitViewController { return proposedPosition } + override func splitViewDidResizeSubviews(_ notification: Notification) { + guard let resizedDivider = notification.userInfo?["NSSplitViewDividerIndex"] as? Int else { + return + } + + if resizedDivider == 0 { + let panel = splitView.subviews[0] + let width = panel.frame.size.width + if width > 0 && setWidthFromState { + workspace.addToWorkspaceState(key: self.widthStateName, value: width) + } + } + } + /// Quick fix for list tracking separator needing to be added again after closing, /// then opening the inspector with a drag. private func insertToolbarItemIfNeeded() { diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift index ae5859673..166119bce 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift @@ -68,7 +68,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate { private func setupSplitView(with workspace: WorkspaceDocument) { let feedbackPerformer = NSHapticFeedbackManager.defaultPerformer - let splitVC = CodeEditSplitViewController(feedbackPerformer: feedbackPerformer) + let splitVC = CodeEditSplitViewController(workspace: workspace, feedbackPerformer: feedbackPerformer) let navigatorView = NavigatorSidebarView(workspace: workspace) let navigator = NSSplitViewItem( diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index 3713bd64b..6b2d99eb1 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -22,6 +22,17 @@ import CodeEditKit @Published var selectionState: WorkspaceSelectionState = .init() @Published var fileItems: [WorkspaceClient.FileItem] = [] + var workspaceState: [String: Any] { + get { + let key = "workspaceState-\(self.fileURL?.absoluteString ?? "")" + return UserDefaults.standard.object(forKey: key) as? [String: Any] ?? [:] + } + set { + let key = "workspaceState-\(self.fileURL?.absoluteString ?? "")" + UserDefaults.standard.set(newValue, forKey: key) + } + } + var statusBarModel: StatusBarViewModel? var searchState: SearchState? var quickOpenViewModel: QuickOpenViewModel? @@ -36,6 +47,14 @@ import CodeEditKit NotificationCenter.default.removeObserver(self) } + func getFromWorkspaceState(key: String) -> Any? { + return workspaceState[key] + } + + func addToWorkspaceState(key: String, value: Any) { + workspaceState.updateValue(value, forKey: key) + } + // MARK: Open Tabs /// Opens new tab /// - Parameter item: any item which can be represented as a tab From 4c5ad35d6f6fb3599151a3a789f62270fecd1ed3 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Mon, 16 Jan 2023 11:00:57 -0600 Subject: [PATCH 02/11] Default width, test fix. --- .../Documents/Controllers/CodeEditSplitViewController.swift | 4 ++-- CodeEditTests/Features/Documents/DocumentsUnitTests.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index d5febf1c6..35c19b32c 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -46,8 +46,8 @@ final class CodeEditSplitViewController: NSSplitViewController { override func viewWillAppear() { super.viewWillAppear() - let width = workspace.getFromWorkspaceState(key: self.widthStateName) as? CGFloat ?? 0 - splitView.setPosition(width, ofDividerAt: .zero) + let width = workspace.getFromWorkspaceState(key: self.widthStateName) as? CGFloat + splitView.setPosition(width ?? CodeEditWindowController.minSidebarWidth, ofDividerAt: .zero) setWidthFromState = true } diff --git a/CodeEditTests/Features/Documents/DocumentsUnitTests.swift b/CodeEditTests/Features/Documents/DocumentsUnitTests.swift index 73ef89c2c..6cce3e50f 100644 --- a/CodeEditTests/Features/Documents/DocumentsUnitTests.swift +++ b/CodeEditTests/Features/Documents/DocumentsUnitTests.swift @@ -18,7 +18,7 @@ final class DocumentsUnitTests: XCTestCase { override func setUp() { super.setUp() hapticFeedbackPerformerMock = .init() - splitViewController = .init(feedbackPerformer: hapticFeedbackPerformerMock) + splitViewController = .init(workspace: WorkspaceDocument(), feedbackPerformer: hapticFeedbackPerformerMock) } override func tearDown() { From e6789645b287c9bbb688e209c84da19eab780bb8 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:19:27 -0600 Subject: [PATCH 03/11] snapWidth fix, remember open tabs. --- .../CodeEditSplitViewController.swift | 2 +- .../Documents/WorkspaceDocument.swift | 64 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index 35c19b32c..d95c1f7b5 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -47,7 +47,7 @@ final class CodeEditSplitViewController: NSSplitViewController { override func viewWillAppear() { super.viewWillAppear() let width = workspace.getFromWorkspaceState(key: self.widthStateName) as? CGFloat - splitView.setPosition(width ?? CodeEditWindowController.minSidebarWidth, ofDividerAt: .zero) + splitView.setPosition(width ?? .snapWidth, ofDividerAt: .zero) setWidthFromState = true } diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index 6b2d99eb1..19dac1cc0 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -38,7 +38,10 @@ import CodeEditKit var quickOpenViewModel: QuickOpenViewModel? var commandsPaletteState: CommandPaletteViewModel? var listenerModel: WorkspaceNotificationModel = .init() + private var cancellables = Set() + private let openTabsStateName: String = "\(String(describing: WorkspaceDocument.self))-OpenTabs" + private var openedTabsFromState = false @Published var targets: [Target] = [] @@ -215,6 +218,14 @@ import CodeEditKit selectionState.openedCodeFiles.removeValue(forKey: item) selectionState.openFileItems.remove(at: openFileItemIndex) removeTab(id: item.tabID) + + if openedTabsFromState { + var openTabsInState = self.getFromWorkspaceState(key: openTabsStateName) as? [String] ?? [] + if let index = openTabsInState.firstIndex(of: item.url.absoluteString) { + openTabsInState.remove(at: index) + self.addToWorkspaceState(key: openTabsStateName, value: openTabsInState) + } + } } private func closeExtensionTab(item: Plugin) { @@ -228,8 +239,19 @@ import CodeEditKit @objc func convertTemporaryTab() { if selectionState.selectedId == selectionState.temporaryTab && selectionState.temporaryTab != nil { + let item = selectionState.getItemByTab(id: selectionState.temporaryTab!) selectionState.previousTemporaryTab = selectionState.temporaryTab selectionState.temporaryTab = nil + + guard let file = item as? WorkspaceClient.FileItem else { return } + + if openedTabsFromState && item != nil { + var openTabsInState = self.getFromWorkspaceState(key: openTabsStateName) as? [String] ?? [] + if !openTabsInState.contains(file.url.absoluteString) { + openTabsInState.append(file.url.absoluteString) + self.addToWorkspaceState(key: openTabsStateName, value: openTabsInState) + } + } } } @@ -288,6 +310,17 @@ import CodeEditKit windowController.shouldCascadeWindows = false windowController.window?.setFrameAutosaveName(self.fileURL?.absoluteString ?? "Untitled") self.addWindowController(windowController) + + var openTabsInState = self.getFromWorkspaceState(key: openTabsStateName) as? [String] ?? [] + for openTab in openTabsInState { + let tabUrl = URL(string: openTab)! + if FileManager.default.fileExists(atPath: tabUrl.path) { + let item = WorkspaceClient.FileItem(url: tabUrl) + self.openTab(item: item) + self.convertTemporaryTab() + } + } + self.openedTabsFromState = true } // MARK: Set Up Workspace @@ -311,26 +344,10 @@ import CodeEditKit ) } - /// Retrieves selection state from UserDefaults using SHA256 hash of project path as key - /// - Throws: `DecodingError.dataCorrupted` error if retrived data from UserDefaults is not decodable - /// - Returns: retrived state from UserDefaults or default state if not found - private func readSelectionState() throws -> WorkspaceSelectionState { - guard let path = fileURL?.path, - let data = UserDefaults.standard.value(forKey: path.sha256()) as? Data else { return selectionState } - let state = try PropertyListDecoder().decode(WorkspaceSelectionState.self, from: data) - return state - } - override func read(from url: URL, ofType typeName: String) throws { try initWorkspaceState(url) // Initialize Workspace - do { - selectionState = try readSelectionState() - } catch { - Swift.print("couldn't retrieve selection state from user defaults") - } - workspaceClient? .getFiles .sink { [weak self] files in @@ -374,22 +391,7 @@ import CodeEditKit // MARK: Close Workspace - /// Saves selection state to UserDefaults using SHA256 hash of project path as key - /// - Throws: `EncodingError.invalidValue` error if sellection state is not encodable - private func saveSelectionState() throws { - guard let path = fileURL?.path else { return } - let hash = path.sha256() - let data = try PropertyListEncoder().encode(selectionState) - UserDefaults.standard.set(data, forKey: hash) - } - override func close() { - do { - try saveSelectionState() - } catch { - Swift.print("couldn't save selection state from user defaults") - } - selectionState.selectedId = nil selectionState.openedCodeFiles.removeAll() From 5112f4345172f9f3710487e3796ea8ac2b833f57 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Wed, 18 Jan 2023 18:52:36 -0600 Subject: [PATCH 04/11] Save/Restore active tab to state. --- .../Features/Documents/WorkspaceDocument.swift | 18 ++++++++++++++++++ .../Features/TabBar/Views/TabBarItemView.swift | 1 + 2 files changed, 19 insertions(+) diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index 19dac1cc0..79b58dba1 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -41,6 +41,7 @@ import CodeEditKit private var cancellables = Set() private let openTabsStateName: String = "\(String(describing: WorkspaceDocument.self))-OpenTabs" + private let activeTabStateName: String = "\(String(describing: WorkspaceDocument.self))-ActiveTab" private var openedTabsFromState = false @Published var targets: [Target] = [] @@ -169,6 +170,13 @@ import CodeEditKit closeTabs(items: range) } + /// Switched the active tab to current tab + /// - Parameter item: tab item that is now active. + func switchedTab(item: TabBarItemRepresentable) { + guard let fileItem = item as? WorkspaceClient.FileItem else { return } + self.addToWorkspaceState(key: activeTabStateName, value: fileItem.url.absoluteString) + } + /// Closes an open temporary tab, does not save the temporary tab's file. /// Removes the tab item from `openedCodeFiles`, `openedExtensions`, and `openFileItems`. private func closeTemporaryTab() { @@ -311,6 +319,8 @@ import CodeEditKit windowController.window?.setFrameAutosaveName(self.fileURL?.absoluteString ?? "Untitled") self.addWindowController(windowController) + var activeTabID: TabBarItemID? + var activeTabInState = self.getFromWorkspaceState(key: activeTabStateName) as? String ?? "" var openTabsInState = self.getFromWorkspaceState(key: openTabsStateName) as? [String] ?? [] for openTab in openTabsInState { let tabUrl = URL(string: openTab)! @@ -318,8 +328,16 @@ import CodeEditKit let item = WorkspaceClient.FileItem(url: tabUrl) self.openTab(item: item) self.convertTemporaryTab() + if activeTabInState == openTab { + activeTabID = item.tabID + } } } + + if activeTabID != nil { + selectionState.selectedId = activeTabID + } + self.openedTabsFromState = true } diff --git a/CodeEdit/Features/TabBar/Views/TabBarItemView.swift b/CodeEdit/Features/TabBar/Views/TabBarItemView.swift index a228b4e6d..47f081049 100644 --- a/CodeEdit/Features/TabBar/Views/TabBarItemView.swift +++ b/CodeEdit/Features/TabBar/Views/TabBarItemView.swift @@ -96,6 +96,7 @@ struct TabBarItemView: View { // Only set the `selectedId` when they are not equal to avoid performance issue for now. if workspace.selectionState.selectedId != item.tabID { workspace.selectionState.selectedId = item.tabID + workspace.switchedTab(item: item) } } From f332bdb85ea28d429d5f65f89a1ca20bb66fc7ed Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Wed, 18 Jan 2023 20:34:29 -0600 Subject: [PATCH 05/11] Save tab reorder state --- .../Features/Documents/WorkspaceDocument.swift | 16 ++++++++++++++++ CodeEdit/Features/TabBar/Views/TabBarView.swift | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index 79b58dba1..b04e9a90f 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -177,6 +177,22 @@ import CodeEditKit self.addToWorkspaceState(key: activeTabStateName, value: fileItem.url.absoluteString) } + /// Tabs reordered + /// - Parameter openedTabs: reordered tabs + func reorderedTabs(openedTabs: [TabBarItemID]) { + selectionState.openedTabs = openedTabs + + if openedTabsFromState { + var openTabsInState: [String] = [] + for openTabId in openedTabs { + guard let item = selectionState.getItemByTab(id: openTabId) as? WorkspaceClient.FileItem + else { continue } + openTabsInState.append(item.url.absoluteString) + } + self.addToWorkspaceState(key: openTabsStateName, value: openTabsInState) + } + } + /// Closes an open temporary tab, does not save the temporary tab's file. /// Removes the tab item from `openedCodeFiles`, `openedExtensions`, and `openFileItems`. private func closeTemporaryTab() { diff --git a/CodeEdit/Features/TabBar/Views/TabBarView.swift b/CodeEdit/Features/TabBar/Views/TabBarView.swift index 186bbc6aa..edccdc66c 100644 --- a/CodeEdit/Features/TabBar/Views/TabBarView.swift +++ b/CodeEdit/Features/TabBar/Views/TabBarView.swift @@ -237,7 +237,7 @@ struct TabBarView: View { // In order to avoid the lag due to the update of workspace state. DispatchQueue.main.asyncAfter(deadline: .now() + 0.40) { if draggingStartLocation == nil { - workspace.selectionState.openedTabs = openedTabs + workspace.reorderedTabs(openedTabs: openedTabs) } } }) From 38261ace271909f4c659328be1baca253dd2381c Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Wed, 18 Jan 2023 22:26:31 -0600 Subject: [PATCH 06/11] Save navigator and inspector state --- .../CodeEditSplitViewController.swift | 24 +++++++++++++++++++ .../CodeEditWindowController.swift | 6 +++++ 2 files changed, 30 insertions(+) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index d95c1f7b5..441712b84 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -17,6 +17,10 @@ private extension CGFloat { final class CodeEditSplitViewController: NSSplitViewController { private var workspace: WorkspaceDocument private let widthStateName: String = "\(String(describing: CodeEditSplitViewController.self))-Width" + private let isNavigatorCollapsedStateName: String + = "\(String(describing: CodeEditSplitViewController.self))-IsNavigatorCollapsed" + private let isInspectorCollapsedStateName: String + = "\(String(describing: CodeEditSplitViewController.self))-IsInspectorCollapsed" private var setWidthFromState = false // Properties @@ -49,6 +53,18 @@ final class CodeEditSplitViewController: NSSplitViewController { let width = workspace.getFromWorkspaceState(key: self.widthStateName) as? CGFloat splitView.setPosition(width ?? .snapWidth, ofDividerAt: .zero) setWidthFromState = true + + if let firstSplitView = splitViewItems.first { + firstSplitView.isCollapsed = workspace.getFromWorkspaceState( + key: isNavigatorCollapsedStateName + ) as? Bool ?? false + } + + if let lastSplitView = splitViewItems.last { + lastSplitView.isCollapsed = workspace.getFromWorkspaceState( + key: isInspectorCollapsedStateName + ) as? Bool ?? true + } } // MARK: - NSSplitViewDelegate @@ -99,6 +115,14 @@ final class CodeEditSplitViewController: NSSplitViewController { } } + func saveNavigatorCollapsedState(isCollapsed: Bool) { + workspace.addToWorkspaceState(key: isNavigatorCollapsedStateName, value: isCollapsed) + } + + func saveInspectorCollapsedState(isCollapsed: Bool) { + workspace.addToWorkspaceState(key: isInspectorCollapsedStateName, value: isCollapsed) + } + /// Quick fix for list tracking separator needing to be added again after closing, /// then opening the inspector with a drag. private func insertToolbarItemIfNeeded() { diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift index 166119bce..f66edd98f 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift @@ -215,6 +215,9 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate { @objc func toggleFirstPanel() { guard let firstSplitView = splitViewController.splitViewItems.first else { return } firstSplitView.animator().isCollapsed.toggle() + if let codeEditSplitVC = splitViewController as? CodeEditSplitViewController { + codeEditSplitVC.saveNavigatorCollapsedState(isCollapsed: firstSplitView.isCollapsed) + } } @objc func toggleLastPanel() { @@ -225,6 +228,9 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate { } else { window?.toolbar?.insertItem(withItemIdentifier: .itemListTrackingSeparator, at: 4) } + if let codeEditSplitVC = splitViewController as? CodeEditSplitViewController { + codeEditSplitVC.saveInspectorCollapsedState(isCollapsed: lastSplitView.isCollapsed) + } } private func getSelectedCodeFile() -> CodeFileDocument? { From 7353d04ab7cff0e176b274ce73bddb9204ddcb71 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Tue, 24 Jan 2023 22:06:39 -0600 Subject: [PATCH 07/11] Save debug drawer state --- .../Documents/WorkspaceDocument.swift | 2 +- .../ViewModels/StatusBarViewModel.swift | 25 ++++++++++- .../StatusBarDrawer/StatusBarDrawer.swift | 45 +++++++++---------- .../StatusBarToggleDrawerButton.swift | 1 + 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index b04e9a90f..a89e1f5a8 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -368,7 +368,7 @@ import CodeEditKit self.searchState = .init(self) self.quickOpenViewModel = .init(fileURL: url) self.commandsPaletteState = .init() - self.statusBarModel = .init(workspaceURL: url) + self.statusBarModel = .init(workspace: self, workspaceURL: url) NotificationCenter.default.addObserver( self, diff --git a/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift b/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift index 9d1080c48..289bf6420 100644 --- a/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift +++ b/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift @@ -12,6 +12,10 @@ import SwiftUI /// A model class to host and manage data for the ``StatusBarView`` /// class StatusBarViewModel: ObservableObject { + private let isStatusBarDrawerCollapsedStateName: String + = "\(String(describing: StatusBarViewModel.self))-IsStatusBarDrawerCollapsed" + private let statusBarDrawerHeightStateName: String + = "\(String(describing: StatusBarViewModel.self))-StatusBarDrawerHeight" // TODO: Implement logic for updating values // TODO: Add @Published vars for indentation, encoding, linebreak @@ -54,6 +58,8 @@ class StatusBarViewModel: ObservableObject { /// Returns the font for status bar items to use private(set) var toolbarFont: Font = .system(size: 11) + private(set) var workspace: WorkspaceDocument + /// The base URL of the workspace private(set) var workspaceURL: URL @@ -69,7 +75,24 @@ class StatusBarViewModel: ObservableObject { /// Initialize with a GitClient /// - Parameter workspaceURL: the current workspace URL - init(workspaceURL: URL) { + init(workspace: WorkspaceDocument, workspaceURL: URL) { + self.workspace = workspace self.workspaceURL = workspaceURL + + var currentHeight = workspace.getFromWorkspaceState(key: statusBarDrawerHeightStateName) as? Double + ?? self.standardHeight + + self.isExpanded = workspace.getFromWorkspaceState(key: isStatusBarDrawerCollapsedStateName) as? Bool ?? false + if self.isExpanded { + self.currentHeight = currentHeight + } + } + + func saveIsExpandedToState() { + self.workspace.addToWorkspaceState(key: isStatusBarDrawerCollapsedStateName, value: self.isExpanded) + } + + func saveHeightToState(height: Double) { + self.workspace.addToWorkspaceState(key: statusBarDrawerHeightStateName, value: height) } } diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift b/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift index 9280bcb1b..fd6ff9fa8 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift @@ -11,12 +11,6 @@ struct StatusBarDrawer: View { @EnvironmentObject private var model: StatusBarViewModel - @ObservedObject - private var prefs: AppPreferencesModel = .shared - - @Environment(\.colorScheme) - private var colorScheme - @State private var searchText = "" @@ -32,26 +26,31 @@ struct StatusBarDrawer: View { var body: some View { VStack(spacing: 0) { - switch model.selectedTab { - case 0: - TerminalEmulatorView(url: model.workspaceURL) - .background { - if colorScheme == .dark { - if prefs.preferences.theme.selectedTheme == prefs.preferences.theme.selectedLightTheme { - Color.white - } else { - EffectView(.underPageBackground) - } - } else { - if prefs.preferences.theme.selectedTheme == prefs.preferences.theme.selectedDarkTheme { - Color.black + GeometryReader { geometryProxy in + switch model.selectedTab { + case 0: + TerminalEmulatorView(url: model.workspaceURL) + .background { + if colorScheme == .dark { + if prefs.preferences.theme.selectedTheme == prefs.preferences.theme.selectedLightTheme { + Color.white + } else { + EffectView(.underPageBackground) + } } else { - EffectView(.contentBackground) + if prefs.preferences.theme.selectedTheme == prefs.preferences.theme.selectedDarkTheme { + Color.black + } else { + EffectView(.contentBackground) + } } - } - } - default: Rectangle().foregroundColor(Color(nsColor: .textBackgroundColor)) + // When size changes, save new height to workspace state. + .onChange(of: geometryProxy.size.height) { _ in + model.saveHeightToState(height: geometryProxy.size.height) + } + default: Rectangle().foregroundColor(Color(nsColor: .textBackgroundColor)) + } } HStack(alignment: .center, spacing: 10) { FilterTextField(title: "Filter", text: $searchText) diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift index e465cd861..bf0cf3e61 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift @@ -27,6 +27,7 @@ internal struct StatusBarToggleDrawerButton: View { model.currentHeight = 300 } } + self.model.saveIsExpandedToState() } internal var body: some View { From a867cf82d6176ba6221bb849dd6ce07e72274163 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Tue, 24 Jan 2023 22:13:10 -0600 Subject: [PATCH 08/11] debug drawer height fix --- .../Features/StatusBar/ViewModels/StatusBarViewModel.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift b/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift index 289bf6420..be0b08fa3 100644 --- a/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift +++ b/CodeEdit/Features/StatusBar/ViewModels/StatusBarViewModel.swift @@ -81,6 +81,9 @@ class StatusBarViewModel: ObservableObject { var currentHeight = workspace.getFromWorkspaceState(key: statusBarDrawerHeightStateName) as? Double ?? self.standardHeight + if currentHeight == 0 { + currentHeight = self.standardHeight + } self.isExpanded = workspace.getFromWorkspaceState(key: isStatusBarDrawerCollapsedStateName) as? Bool ?? false if self.isExpanded { From 7ce2b1f5fe9131341d63426359a364dde6309ae2 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Tue, 24 Jan 2023 23:04:51 -0600 Subject: [PATCH 09/11] Bug fixes --- .../Documents/Controllers/CodeEditSplitViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index 441712b84..e582080fc 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -65,6 +65,8 @@ final class CodeEditSplitViewController: NSSplitViewController { key: isInspectorCollapsedStateName ) as? Bool ?? true } + + self.insertToolbarItemIfNeeded() } // MARK: - NSSplitViewDelegate From 757a461c6e66f56094142cfc3b720f802f6049cc Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Sat, 18 Feb 2023 11:52:32 -0600 Subject: [PATCH 10/11] Fix linter --- CodeEdit/Features/Documents/WorkspaceDocument.swift | 1 + CodeEdit/Features/TabBar/Views/TabBarItemView.swift | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index a89e1f5a8..04bdbbca1 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -173,6 +173,7 @@ import CodeEditKit /// Switched the active tab to current tab /// - Parameter item: tab item that is now active. func switchedTab(item: TabBarItemRepresentable) { + selectionState.selectedId = item.tabID guard let fileItem = item as? WorkspaceClient.FileItem else { return } self.addToWorkspaceState(key: activeTabStateName, value: fileItem.url.absoluteString) } diff --git a/CodeEdit/Features/TabBar/Views/TabBarItemView.swift b/CodeEdit/Features/TabBar/Views/TabBarItemView.swift index 47f081049..049082168 100644 --- a/CodeEdit/Features/TabBar/Views/TabBarItemView.swift +++ b/CodeEdit/Features/TabBar/Views/TabBarItemView.swift @@ -95,7 +95,6 @@ struct TabBarItemView: View { private func switchAction() { // Only set the `selectedId` when they are not equal to avoid performance issue for now. if workspace.selectionState.selectedId != item.tabID { - workspace.selectionState.selectedId = item.tabID workspace.switchedTab(item: item) } } From a4351e625ee5b8397fc7d46b51d93a3b105b84e9 Mon Sep 17 00:00:00 2001 From: Code-DJ <8212554+Code-DJ@users.noreply.github.com> Date: Mon, 20 Feb 2023 02:33:41 +0000 Subject: [PATCH 11/11] Rebase fix --- .../StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift b/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift index fd6ff9fa8..d9a24b5e1 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarDrawer/StatusBarDrawer.swift @@ -11,6 +11,12 @@ struct StatusBarDrawer: View { @EnvironmentObject private var model: StatusBarViewModel + @ObservedObject + private var prefs: AppPreferencesModel = .shared + + @Environment(\.colorScheme) + private var colorScheme + @State private var searchText = ""