diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 1d9d1aae26..ad376b434e 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -94,7 +94,7 @@ 30CB648D2C12680F00CC8A9E /* LSPService+Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CB648C2C12680F00CC8A9E /* LSPService+Events.swift */; }; 30CB64912C16CA8100CC8A9E /* LanguageServerProtocol in Frameworks */ = {isa = PBXBuildFile; productRef = 30CB64902C16CA8100CC8A9E /* LanguageServerProtocol */; }; 30CB64942C16CA9100CC8A9E /* LanguageClient in Frameworks */ = {isa = PBXBuildFile; productRef = 30CB64932C16CA9100CC8A9E /* LanguageClient */; }; - 30E6D0012A6E505200A58B20 /* NavigatorSidebarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */; }; + 30E6D0012A6E505200A58B20 /* NavigatorAreaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E6D0002A6E505200A58B20 /* NavigatorAreaViewModel.swift */; }; 3E0196732A3921AC002648D8 /* codeedit_shell_integration_rc.zsh in Resources */ = {isa = PBXBuildFile; fileRef = 3E0196722A3921AC002648D8 /* codeedit_shell_integration_rc.zsh */; }; 3E01967A2A392B45002648D8 /* codeedit_shell_integration.bash in Resources */ = {isa = PBXBuildFile; fileRef = 3E0196792A392B45002648D8 /* codeedit_shell_integration.bash */; }; 4A6F0DB52CBA462B00499627 /* ProjectNavigatorMenuActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A6F0DB42CBA462B00499627 /* ProjectNavigatorMenuActions.swift */; }; @@ -524,7 +524,7 @@ B62423302C21EE280096668B /* ThemeModel+CRUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = B624232F2C21EE280096668B /* ThemeModel+CRUD.swift */; }; B628B7932B18369800F9775A /* GitClient+Validate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B628B7922B18369800F9775A /* GitClient+Validate.swift */; }; B628B7B72B223BAD00F9775A /* FindModePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B628B7B62B223BAD00F9775A /* FindModePicker.swift */; }; - B62AEDAA2A1FCBE5009A9F52 /* AreaTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDA92A1FCBE5009A9F52 /* AreaTabBar.swift */; }; + B62AEDAA2A1FCBE5009A9F52 /* WorkspacePanelTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDA92A1FCBE5009A9F52 /* WorkspacePanelTabBar.swift */; }; B62AEDB32A1FD95B009A9F52 /* UtilityAreaTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB22A1FD95B009A9F52 /* UtilityAreaTerminalView.swift */; }; B62AEDB52A1FE295009A9F52 /* UtilityAreaDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB42A1FE295009A9F52 /* UtilityAreaDebugView.swift */; }; B62AEDB82A1FE2DC009A9F52 /* UtilityAreaOutputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB72A1FE2DC009A9F52 /* UtilityAreaOutputView.swift */; }; @@ -558,6 +558,7 @@ B66A4E5329C91831004573B4 /* CodeEditCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66A4E5229C91831004573B4 /* CodeEditCommands.swift */; }; B66A4E5629C918A0004573B4 /* SceneID.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66A4E5529C918A0004573B4 /* SceneID.swift */; }; B67431CC2C3E45F30047FCA6 /* SourceControlSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B67431CB2C3E45F30047FCA6 /* SourceControlSwitchView.swift */; }; + B67700F92D2A2662004FD61F /* WorkspacePanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B67700F82D2A2662004FD61F /* WorkspacePanelView.swift */; }; B67DB0EF2AF3E381002DC647 /* PaneTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B67DB0EE2AF3E381002DC647 /* PaneTextField.swift */; }; B67DB0F62AFC2A7A002DC647 /* FindNavigatorToolbarBottom.swift in Sources */ = {isa = PBXBuildFile; fileRef = B67DB0F52AFC2A7A002DC647 /* FindNavigatorToolbarBottom.swift */; }; B67DB0F92AFDF638002DC647 /* IconButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B67DB0F82AFDF638002DC647 /* IconButtonStyle.swift */; }; @@ -789,7 +790,7 @@ 30B087F82C0D53080063A882 /* LSPService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LSPService.swift; sourceTree = ""; }; 30B087FA2C0D53080063A882 /* LSPUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LSPUtil.swift; sourceTree = ""; }; 30CB648C2C12680F00CC8A9E /* LSPService+Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LSPService+Events.swift"; sourceTree = ""; }; - 30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorSidebarViewModel.swift; sourceTree = ""; }; + 30E6D0002A6E505200A58B20 /* NavigatorAreaViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorAreaViewModel.swift; sourceTree = ""; }; 3E0196722A3921AC002648D8 /* codeedit_shell_integration_rc.zsh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = codeedit_shell_integration_rc.zsh; sourceTree = ""; }; 3E0196792A392B45002648D8 /* codeedit_shell_integration.bash */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = codeedit_shell_integration.bash; sourceTree = ""; }; 4A6F0DB42CBA462B00499627 /* ProjectNavigatorMenuActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectNavigatorMenuActions.swift; sourceTree = ""; }; @@ -1200,7 +1201,7 @@ B624232F2C21EE280096668B /* ThemeModel+CRUD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThemeModel+CRUD.swift"; sourceTree = ""; }; B628B7922B18369800F9775A /* GitClient+Validate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GitClient+Validate.swift"; sourceTree = ""; }; B628B7B62B223BAD00F9775A /* FindModePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindModePicker.swift; sourceTree = ""; }; - B62AEDA92A1FCBE5009A9F52 /* AreaTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AreaTabBar.swift; sourceTree = ""; }; + B62AEDA92A1FCBE5009A9F52 /* WorkspacePanelTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspacePanelTabBar.swift; sourceTree = ""; }; B62AEDB22A1FD95B009A9F52 /* UtilityAreaTerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaTerminalView.swift; sourceTree = ""; }; B62AEDB42A1FE295009A9F52 /* UtilityAreaDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaDebugView.swift; sourceTree = ""; }; B62AEDB72A1FE2DC009A9F52 /* UtilityAreaOutputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UtilityAreaOutputView.swift; sourceTree = ""; }; @@ -1239,6 +1240,7 @@ B66A4E5229C91831004573B4 /* CodeEditCommands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeEditCommands.swift; sourceTree = ""; }; B66A4E5529C918A0004573B4 /* SceneID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneID.swift; sourceTree = ""; }; B67431CB2C3E45F30047FCA6 /* SourceControlSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlSwitchView.swift; sourceTree = ""; }; + B67700F82D2A2662004FD61F /* WorkspacePanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspacePanelView.swift; sourceTree = ""; }; B67DB0EE2AF3E381002DC647 /* PaneTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaneTextField.swift; sourceTree = ""; }; B67DB0F52AFC2A7A002DC647 /* FindNavigatorToolbarBottom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorToolbarBottom.swift; sourceTree = ""; }; B67DB0F82AFDF638002DC647 /* IconButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconButtonStyle.swift; sourceTree = ""; }; @@ -1572,7 +1574,7 @@ 307AC4CB2ABABD9800163376 /* ViewModels */ = { isa = PBXGroup; children = ( - 30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */, + 30E6D0002A6E505200A58B20 /* NavigatorAreaViewModel.swift */, ); path = ViewModels; sourceTree = ""; @@ -2087,8 +2089,9 @@ 587B9D8629300ABD00AC7927 /* Views */ = { isa = PBXGroup; children = ( + B67700F82D2A2662004FD61F /* WorkspacePanelView.swift */, + B62AEDA92A1FCBE5009A9F52 /* WorkspacePanelTabBar.swift */, 30AB4EC12BF7253200ED4431 /* KeyValueTable.swift */, - B62AEDA92A1FCBE5009A9F52 /* AreaTabBar.swift */, B65B10EB2B073913002852CF /* CEContentUnavailableView.swift */, B65B10FA2B08B054002852CF /* Divided.swift */, 587B9D8B29300ABD00AC7927 /* EffectView.swift */, @@ -4322,6 +4325,7 @@ 77EF6C052C57DE4B00984B69 /* URL+ResouceValues.swift in Sources */, B640A9A129E2188F00715F20 /* View+NavigationBarBackButtonVisible.swift in Sources */, 587B9E7929301D8F00AC7927 /* GitHubIssueRouter.swift in Sources */, + B67700F92D2A2662004FD61F /* WorkspacePanelView.swift in Sources */, 587B9E8029301D8F00AC7927 /* GitHubConfiguration.swift in Sources */, 58822524292C280D00E83CDE /* StatusBarView.swift in Sources */, 581550D429FBD37D00684881 /* ProjectNavigatorToolbarBottom.swift in Sources */, @@ -4377,7 +4381,7 @@ 4A6F0DB52CBA462B00499627 /* ProjectNavigatorMenuActions.swift in Sources */, 58F2EB05292FB2B0004A9BDE /* Settings.swift in Sources */, 6CBD1BC62978DE53006639D5 /* Font+Caption3.swift in Sources */, - 30E6D0012A6E505200A58B20 /* NavigatorSidebarViewModel.swift in Sources */, + 30E6D0012A6E505200A58B20 /* NavigatorAreaViewModel.swift in Sources */, 6CD26C7B2C8EA8A500ADBA38 /* LSPCache+Data.swift in Sources */, B6E41C9429DEAE260088F9F4 /* SourceControlAccount.swift in Sources */, 2806E9022979588B000040F4 /* Contributor.swift in Sources */, @@ -4467,7 +4471,7 @@ 58D01C9A293167DC00C5B6B4 /* CodeEditKeychain.swift in Sources */, 6CB94CFE2C9F1C9A00E8651C /* TextView+LSPRange.swift in Sources */, B6966A2E2C3056AD00259C2D /* SourceControlCommands.swift in Sources */, - B62AEDAA2A1FCBE5009A9F52 /* AreaTabBar.swift in Sources */, + B62AEDAA2A1FCBE5009A9F52 /* WorkspacePanelTabBar.swift in Sources */, 20D839AB280DEB2900B27357 /* NoSelectionInspectorView.swift in Sources */, 30B0880F2C0D53080063A882 /* LanguageServer+SelectionRange.swift in Sources */, 30B0880C2C0D53080063A882 /* LanguageServer+InlayHint.swift in Sources */, diff --git a/CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift b/CodeEdit/Features/CodeEditUI/Views/WorkspacePanelTabBar.swift similarity index 97% rename from CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift rename to CodeEdit/Features/CodeEditUI/Views/WorkspacePanelTabBar.swift index 4f45f27649..d3ef997a01 100644 --- a/CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift +++ b/CodeEdit/Features/CodeEditUI/Views/WorkspacePanelTabBar.swift @@ -1,5 +1,5 @@ // -// AreaTabBar.swift +// WorkspacePanelTabBar.swift // CodeEdit // // Created by Austin Condiff on 5/25/23. @@ -7,12 +7,12 @@ import SwiftUI -protocol AreaTab: View, Identifiable, Hashable { +protocol WorkspacePanelTab: View, Identifiable, Hashable { var title: String { get } var systemImage: String { get } } -struct AreaTabBar: View { +struct WorkspacePanelTabBar: View { @Binding var items: [Tab] @Binding var selection: Tab? @@ -113,7 +113,7 @@ struct AreaTabBar: View { ) ) .focusable(false) - .accessibilityIdentifier("TabAreaTab-\(tab.title)") + .accessibilityIdentifier("WorkspacePanelTab-\(tab.title)") .accessibilityLabel(tab.title) } diff --git a/CodeEdit/Features/CodeEditUI/Views/WorkspacePanelView.swift b/CodeEdit/Features/CodeEditUI/Views/WorkspacePanelView.swift new file mode 100644 index 0000000000..4637d2785e --- /dev/null +++ b/CodeEdit/Features/CodeEditUI/Views/WorkspacePanelView.swift @@ -0,0 +1,64 @@ +// +// WorkspacePanelView.swift +// CodeEdit +// +// Created by Austin Condiff on 1/4/25. +// + +import SwiftUI + +struct WorkspacePanelView: View { + @ObservedObject var viewModel: ViewModel + @Binding var selectedTab: Tab? + @Binding var tabItems: [Tab] + + @Environment(\.colorScheme) + private var colorScheme + + var sidebarPosition: SettingsData.SidebarTabBarPosition + var darkDivider: Bool + + init( + viewModel: ViewModel, + selectedTab: Binding, + tabItems: Binding<[Tab]>, + sidebarPosition: SettingsData.SidebarTabBarPosition, + darkDivider: Bool = false + ) { + self.viewModel = viewModel + self._selectedTab = selectedTab + self._tabItems = tabItems + self.sidebarPosition = sidebarPosition + self.darkDivider = darkDivider + } + + var body: some View { + VStack(spacing: 0) { + if let selection = selectedTab { + selection + } else { + CEContentUnavailableView("No Selection") + } + } + .safeAreaInset(edge: .leading, spacing: 0) { + if sidebarPosition == .side { + HStack(spacing: 0) { + WorkspacePanelTabBar(items: $tabItems, selection: $selectedTab, position: sidebarPosition) + Divider() + .overlay(Color(nsColor: darkDivider && colorScheme == .dark ? .black : .clear)) + } + } + } + .safeAreaInset(edge: .top, spacing: 0) { + if sidebarPosition == .top { + VStack(spacing: 0) { + Divider() + WorkspacePanelTabBar(items: $tabItems, selection: $selectedTab, position: sidebarPosition) + Divider() + } + } else if !darkDivider { + Divider() + } + } + } +} diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index a28b3e1f62..7551c0bedc 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -15,7 +15,7 @@ final class CodeEditSplitViewController: NSSplitViewController { static let minSnapWidth: CGFloat = snapWidth - 10 private weak var workspace: WorkspaceDocument? - private weak var navigatorViewModel: NavigatorSidebarViewModel? + private weak var navigatorViewModel: NavigatorAreaViewModel? private weak var windowRef: NSWindow? private unowned var hapticPerformer: NSHapticFeedbackPerformer @@ -23,7 +23,7 @@ final class CodeEditSplitViewController: NSSplitViewController { init( workspace: WorkspaceDocument, - navigatorViewModel: NavigatorSidebarViewModel, + navigatorViewModel: NavigatorAreaViewModel, windowRef: NSWindow, hapticPerformer: NSHapticFeedbackPerformer = NSHapticFeedbackManager.defaultPerformer ) { diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift index c3ee61af47..3d581f079f 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift @@ -22,7 +22,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs var workspaceSettingsWindow: NSWindow? var quickOpenPanel: SearchPanel? var commandPalettePanel: SearchPanel? - var navigatorSidebarViewModel: NavigatorSidebarViewModel? + var navigatorSidebarViewModel: NavigatorAreaViewModel? internal var cancellables = [AnyCancellable]() @@ -86,7 +86,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs return nil } - let navigatorModel = NavigatorSidebarViewModel() + let navigatorModel = NavigatorAreaViewModel() navigatorSidebarViewModel = navigatorModel self.listenToDocumentEdited(workspace: workspace) return CodeEditSplitViewController( diff --git a/CodeEdit/Features/InspectorArea/Models/InspectorTab.swift b/CodeEdit/Features/InspectorArea/Models/InspectorTab.swift index 62bcf53d60..209083a072 100644 --- a/CodeEdit/Features/InspectorArea/Models/InspectorTab.swift +++ b/CodeEdit/Features/InspectorArea/Models/InspectorTab.swift @@ -9,7 +9,7 @@ import SwiftUI import CodeEditKit import ExtensionFoundation -enum InspectorTab: AreaTab { +enum InspectorTab: WorkspacePanelTab { case file case gitHistory case uiExtension(endpoint: AppExtensionIdentity, data: ResolvedSidebar.SidebarStore) diff --git a/CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift b/CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift index 3c4e157492..c6491f00d5 100644 --- a/CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift +++ b/CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift @@ -9,71 +9,20 @@ import SwiftUI struct InspectorAreaView: View { @EnvironmentObject private var workspace: WorkspaceDocument + @EnvironmentObject private var editorManager: EditorManager @ObservedObject private var extensionManager = ExtensionManager.shared @ObservedObject public var viewModel: InspectorAreaViewModel - @EnvironmentObject private var editorManager: EditorManager - - @AppSettings(\.sourceControl.general.sourceControlIsEnabled) - private var sourceControlIsEnabled: Bool - @AppSettings(\.general.inspectorTabBarPosition) var sidebarPosition: SettingsData.SidebarTabBarPosition - @State private var selection: InspectorTab? = .file - init(viewModel: InspectorAreaViewModel) { self.viewModel = viewModel - updateTabItems() - } - - func getExtension(_ id: String) -> ExtensionInfo? { - return extensionManager.extensions.first( - where: { $0.endpoint.bundleIdentifier == id } - ) - } - - var body: some View { - VStack { - if let selection { - selection - } else { - NoSelectionInspectorView() - } - } - .safeAreaInset(edge: .trailing, spacing: 0) { - if sidebarPosition == .side { - HStack(spacing: 0) { - Divider() - AreaTabBar(items: $viewModel.tabItems, selection: $selection, position: sidebarPosition) - } - } - } - .safeAreaInset(edge: .top, spacing: 0) { - if sidebarPosition == .top { - VStack(spacing: 0) { - Divider() - AreaTabBar(items: $viewModel.tabItems, selection: $selection, position: sidebarPosition) - Divider() - } - } else { - Divider() - } - } - .formStyle(.grouped) - .accessibilityElement(children: .contain) - .accessibilityLabel("inspector") - .onChange(of: sourceControlIsEnabled) { _ in - updateTabItems() - } - } - private func updateTabItems() { - viewModel.tabItems = [.file] + - (sourceControlIsEnabled ? [.gitHistory] : []) + + viewModel.tabItems = [.file, .gitHistory] + extensionManager .extensions - .flatMap { ext in + .map { ext in ext.availableFeatures.compactMap { if case .sidebarItem(let data) = $0, data.kind == .inspector { return InspectorTab.uiExtension(endpoint: ext.endpoint, data: data) @@ -81,10 +30,18 @@ struct InspectorAreaView: View { return nil } } - if let selectedTab = selection, - !viewModel.tabItems.isEmpty && - !viewModel.tabItems.contains(selectedTab) { - selection = viewModel.tabItems[0] - } + .joined() + } + + var body: some View { + WorkspacePanelView( + viewModel: viewModel, + selectedTab: $viewModel.selectedTab, + tabItems: $viewModel.tabItems, + sidebarPosition: sidebarPosition + ) + .formStyle(.grouped) + .accessibilityElement(children: .contain) + .accessibilityLabel("inspector") } } diff --git a/CodeEdit/Features/NavigatorArea/Models/NavigatorTab.swift b/CodeEdit/Features/NavigatorArea/Models/NavigatorTab.swift index 118ccb2a06..f8d240e798 100644 --- a/CodeEdit/Features/NavigatorArea/Models/NavigatorTab.swift +++ b/CodeEdit/Features/NavigatorArea/Models/NavigatorTab.swift @@ -9,7 +9,7 @@ import SwiftUI import CodeEditKit import ExtensionFoundation -enum NavigatorTab: AreaTab { +enum NavigatorTab: WorkspacePanelTab { case project case sourceControl case search diff --git a/CodeEdit/Features/NavigatorArea/ViewModels/NavigatorSidebarViewModel.swift b/CodeEdit/Features/NavigatorArea/ViewModels/NavigatorAreaViewModel.swift similarity index 78% rename from CodeEdit/Features/NavigatorArea/ViewModels/NavigatorSidebarViewModel.swift rename to CodeEdit/Features/NavigatorArea/ViewModels/NavigatorAreaViewModel.swift index 82199b107d..0133d81414 100644 --- a/CodeEdit/Features/NavigatorArea/ViewModels/NavigatorSidebarViewModel.swift +++ b/CodeEdit/Features/NavigatorArea/ViewModels/NavigatorAreaViewModel.swift @@ -1,5 +1,5 @@ // -// NavigatorSidebarViewModel.swift +// NavigatorAreaViewModel.swift // CodeEdit // // Created by Abe Malla on 7/23/23. @@ -7,7 +7,7 @@ import Foundation -class NavigatorSidebarViewModel: ObservableObject { +class NavigatorAreaViewModel: ObservableObject { @Published var selectedTab: NavigatorTab? = .project /// The tab bar items in the Navigator @Published var tabItems: [NavigatorTab] = [] diff --git a/CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift b/CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift index 5f2e605c8f..a3fdabf65c 100644 --- a/CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift +++ b/CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift @@ -10,62 +10,19 @@ import SwiftUI struct NavigatorAreaView: View { @ObservedObject private var workspace: WorkspaceDocument @ObservedObject private var extensionManager = ExtensionManager.shared - @ObservedObject public var viewModel: NavigatorSidebarViewModel + @ObservedObject public var viewModel: NavigatorAreaViewModel @AppSettings(\.general.navigatorTabBarPosition) var sidebarPosition: SettingsData.SidebarTabBarPosition - @AppSettings(\.sourceControl.general.sourceControlIsEnabled) - private var sourceControlIsEnabled: Bool - - init(workspace: WorkspaceDocument, viewModel: NavigatorSidebarViewModel) { + init(workspace: WorkspaceDocument, viewModel: NavigatorAreaViewModel) { self.workspace = workspace self.viewModel = viewModel - updateTabItems() - } - - var body: some View { - VStack { - if let selection = viewModel.selectedTab { - selection - } else { - NoSelectionInspectorView() - } - } - .safeAreaInset(edge: .leading, spacing: 0) { - if sidebarPosition == .side { - HStack(spacing: 0) { - AreaTabBar(items: $viewModel.tabItems, selection: $viewModel.selectedTab, position: sidebarPosition) - Divider() - } - } - } - .safeAreaInset(edge: .top, spacing: 0) { - if sidebarPosition == .top { - VStack(spacing: 0) { - Divider() - AreaTabBar(items: $viewModel.tabItems, selection: $viewModel.selectedTab, position: sidebarPosition) - Divider() - } - } else { - Divider() - } - } - .environmentObject(workspace) - .accessibilityElement(children: .contain) - .accessibilityLabel("navigator") - .onChange(of: sourceControlIsEnabled) { _ in - updateTabItems() - } - } - private func updateTabItems() { - viewModel.tabItems = [.project] + - (sourceControlIsEnabled ? [.sourceControl] : []) + - [.search] + + viewModel.tabItems = [.project, .sourceControl, .search] + extensionManager .extensions - .flatMap { ext in + .map { ext in ext.availableFeatures.compactMap { if case .sidebarItem(let data) = $0, data.kind == .navigator { return NavigatorTab.uiExtension(endpoint: ext.endpoint, data: data) @@ -73,10 +30,18 @@ struct NavigatorAreaView: View { return nil } } - if let selectedTab = viewModel.selectedTab, - !viewModel.tabItems.isEmpty && - !viewModel.tabItems.contains(selectedTab) { - viewModel.selectedTab = viewModel.tabItems[0] - } + .joined() + } + + var body: some View { + WorkspacePanelView( + viewModel: viewModel, + selectedTab: $viewModel.selectedTab, + tabItems: $viewModel.tabItems, + sidebarPosition: sidebarPosition + ) + .environmentObject(workspace) + .accessibilityElement(children: .contain) + .accessibilityLabel("navigator") } } diff --git a/CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift b/CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift index ff3248161e..2056b6d7d7 100644 --- a/CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift +++ b/CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift @@ -7,7 +7,7 @@ import SwiftUI -enum UtilityAreaTab: AreaTab, CaseIterable { +enum UtilityAreaTab: WorkspacePanelTab, CaseIterable { var id: Self { self } case terminal diff --git a/CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift b/CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift index a89e1e665c..e21f686e83 100644 --- a/CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift +++ b/CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift @@ -8,38 +8,15 @@ import SwiftUI struct UtilityAreaView: View { - @AppSettings(\.theme.matchAppearance) - private var matchAppearance - - @AppSettings(\.terminal.darkAppearance) - private var darkAppearance - - @Environment(\.colorScheme) - private var colorScheme - @EnvironmentObject private var utilityAreaViewModel: UtilityAreaViewModel - @StateObject private var themeModel: ThemeModel = .shared - var body: some View { - VStack(spacing: 0) { - if let selectedTab = utilityAreaViewModel.selectedTab { - selectedTab - } else { - Text("Tab not found") - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - } - .safeAreaInset(edge: .leading, spacing: 0) { - HStack(spacing: 0) { - AreaTabBar( - items: $utilityAreaViewModel.tabItems, - selection: $utilityAreaViewModel.selectedTab, - position: .side - ) - Divider() - .overlay(Color(nsColor: colorScheme == .dark ? .black : .clear)) - } - } + WorkspacePanelView( + viewModel: utilityAreaViewModel, + selectedTab: $utilityAreaViewModel.selectedTab, + tabItems: $utilityAreaViewModel.tabItems, + sidebarPosition: .side, + darkDivider: true + ) } } diff --git a/CodeEdit/Features/WindowCommands/ViewCommands.swift b/CodeEdit/Features/WindowCommands/ViewCommands.swift index b796b20d31..fc6b8b72d8 100644 --- a/CodeEdit/Features/WindowCommands/ViewCommands.swift +++ b/CodeEdit/Features/WindowCommands/ViewCommands.swift @@ -141,7 +141,7 @@ extension ViewCommands { extension ViewCommands { struct NavigatorCommands: View { - @ObservedObject var model: NavigatorSidebarViewModel + @ObservedObject var model: NavigatorAreaViewModel var body: some View { Menu("Navigators", content: { diff --git a/CodeEditTests/Features/Documents/DocumentsUnitTests.swift b/CodeEditTests/Features/Documents/DocumentsUnitTests.swift index aa66fdac2b..5c9fb5b668 100644 --- a/CodeEditTests/Features/Documents/DocumentsUnitTests.swift +++ b/CodeEditTests/Features/Documents/DocumentsUnitTests.swift @@ -12,7 +12,7 @@ final class DocumentsUnitTests: XCTestCase { // Properties private var splitViewController: CodeEditSplitViewController! private var hapticFeedbackPerformerMock: NSHapticFeedbackPerformerMock! - private var navigatorViewModel: NavigatorSidebarViewModel! + private var navigatorViewModel: NavigatorAreaViewModel! private var window: NSWindow! private var workspace = WorkspaceDocument()