diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index c8de7d0f1..1cbe56db2 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -283,6 +283,10 @@ 6C578D8929CD36E400DC73B2 /* Commands+ForEach.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C578D8829CD36E400DC73B2 /* Commands+ForEach.swift */; }; 6C578D8C29CD372700DC73B2 /* ExtensionCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C578D8B29CD372700DC73B2 /* ExtensionCommands.swift */; }; 6C5B63DE29C76213005454BA /* WindowCodeFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B63DD29C76213005454BA /* WindowCodeFileView.swift */; }; + 6C5BE51C2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5BE51B2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift */; }; + 6C5BE51E2A3D545F002DA0FC /* FeatureFlagsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5BE51D2A3D545F002DA0FC /* FeatureFlagsSettings.swift */; }; + 6C5BE5222A3D5666002DA0FC /* WindowManagement in Frameworks */ = {isa = PBXBuildFile; productRef = 6C5BE5212A3D5666002DA0FC /* WindowManagement */; }; + 6C5C891B2A3F736500A94FE1 /* FocusedValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5C891A2A3F736500A94FE1 /* FocusedValues.swift */; }; 6C5FDF7A29E6160000BC08C0 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5FDF7929E6160000BC08C0 /* AppSettings.swift */; }; 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = 6C66C31229D05CDC00DE9ED2 /* GRDB */; }; 6C6BD6EF29CD12E900235D17 /* ExtensionManagerWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6BD6EE29CD12E900235D17 /* ExtensionManagerWindow.swift */; }; @@ -296,6 +300,8 @@ 6C6BD70129CD172700235D17 /* ExtensionsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6BD70029CD172700235D17 /* ExtensionsListView.swift */; }; 6C6BD70429CD17B600235D17 /* ExtensionsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C6BD70329CD17B600235D17 /* ExtensionsManager.swift */; }; 6C7256D729A3D7D000C2D3E0 /* SplitViewControllerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7256D629A3D7D000C2D3E0 /* SplitViewControllerView.swift */; }; + 6C7F37FE2A3EA6FA00217B83 /* View+focusedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7F37FD2A3EA6FA00217B83 /* View+focusedValue.swift */; }; + 6C7F38012A3EA71400217B83 /* WindowSplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7F38002A3EA71400217B83 /* WindowSplitView.swift */; }; 6C81916729B3E80700B75C92 /* ModifierKeysObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C81916629B3E80700B75C92 /* ModifierKeysObserver.swift */; }; 6C81916B29B41DD300B75C92 /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = 6C81916A29B41DD300B75C92 /* DequeModule */; }; 6C82D6B329BFD88700495C54 /* NavigateCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C82D6B229BFD88700495C54 /* NavigateCommands.swift */; }; @@ -319,7 +325,6 @@ 6CD03B6A29FC773F001BD1D0 /* SettingsInjector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */; }; 6CDA84AD284C1BA000C1CC3A /* TabBarContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */; }; 6CDEFC9629E22C2700B7C684 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 6CDEFC9529E22C2700B7C684 /* Introspect */; }; - 6CE60BDD2A226A870075D21E /* Scene+Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE60BDC2A226A870075D21E /* Scene+Environment.swift */; }; 6CE622692A2A174A0013085C /* InspectorTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE622682A2A174A0013085C /* InspectorTab.swift */; }; 6CE6226B2A2A1C730013085C /* DebugAreaTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */; }; 6CE6226E2A2A1CDE0013085C /* NavigatorTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */; }; @@ -739,6 +744,9 @@ 6C578D8B29CD372700DC73B2 /* ExtensionCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionCommands.swift; sourceTree = ""; }; 6C5AB9D629C1496E003B5F96 /* SceneID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneID.swift; sourceTree = ""; }; 6C5B63DD29C76213005454BA /* WindowCodeFileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowCodeFileView.swift; sourceTree = ""; }; + 6C5BE51B2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlagsSettingsView.swift; sourceTree = ""; }; + 6C5BE51D2A3D545F002DA0FC /* FeatureFlagsSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlagsSettings.swift; sourceTree = ""; }; + 6C5C891A2A3F736500A94FE1 /* FocusedValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusedValues.swift; sourceTree = ""; }; 6C5FDF7929E6160000BC08C0 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; 6C6BD6EE29CD12E900235D17 /* ExtensionManagerWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionManagerWindow.swift; sourceTree = ""; }; 6C6BD6F029CD13FA00235D17 /* ExtensionDiscovery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDiscovery.swift; sourceTree = ""; }; @@ -747,6 +755,8 @@ 6C6BD70029CD172700235D17 /* ExtensionsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionsListView.swift; sourceTree = ""; }; 6C6BD70329CD17B600235D17 /* ExtensionsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionsManager.swift; sourceTree = ""; }; 6C7256D629A3D7D000C2D3E0 /* SplitViewControllerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitViewControllerView.swift; sourceTree = ""; }; + 6C7F37FD2A3EA6FA00217B83 /* View+focusedValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+focusedValue.swift"; sourceTree = ""; }; + 6C7F38002A3EA71400217B83 /* WindowSplitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowSplitView.swift; sourceTree = ""; }; 6C81916629B3E80700B75C92 /* ModifierKeysObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModifierKeysObserver.swift; sourceTree = ""; }; 6C82D6B229BFD88700495C54 /* NavigateCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigateCommands.swift; sourceTree = ""; }; 6C82D6B529BFDB5100495C54 /* SourceControlCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlCommands.swift; sourceTree = ""; }; @@ -763,7 +773,6 @@ 6CD0375E2A3504540071C4DA /* FuzzySearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FuzzySearch.swift; sourceTree = ""; }; 6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInjector.swift; sourceTree = ""; }; 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarContextMenu.swift; sourceTree = ""; }; - 6CE60BDC2A226A870075D21E /* Scene+Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Scene+Environment.swift"; sourceTree = ""; }; 6CE622682A2A174A0013085C /* InspectorTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorTab.swift; sourceTree = ""; }; 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTab.swift; sourceTree = ""; }; 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorTab.swift; sourceTree = ""; }; @@ -863,6 +872,7 @@ buildActionMask = 2147483647; files = ( 6C0F3A3C2A1D0D5000223D19 /* CodeEditKit in Frameworks */, + 6C5BE5222A3D5666002DA0FC /* WindowManagement in Frameworks */, 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */, 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */, 6C2149412A1BB9AB00748382 /* LogStream in Frameworks */, @@ -1250,6 +1260,7 @@ isa = PBXGroup; children = ( 5882251A292C280D00E83CDE /* View+isHovering.swift */, + 6C7F37FD2A3EA6FA00217B83 /* View+focusedValue.swift */, ); path = View; sourceTree = ""; @@ -1933,6 +1944,7 @@ 58D01C85293167DC00C5B6B4 /* Utils */ = { isa = PBXGroup; children = ( + 6C5C891A2A3F736500A94FE1 /* FocusedValues.swift */, 587B9D54292FC27A00AC7927 /* FolderMonitor.swift */, 6C48D8EF2972DAC300D6D205 /* Environment */, 58D01C87293167DC00C5B6B4 /* Extensions */, @@ -2083,6 +2095,15 @@ path = Environment; sourceTree = ""; }; + 6C5BE51A2A3D5419002DA0FC /* FeatureFlags */ = { + isa = PBXGroup; + children = ( + 6C5BE51B2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift */, + 6C5BE51D2A3D545F002DA0FC /* FeatureFlagsSettings.swift */, + ); + path = FeatureFlags; + sourceTree = ""; + }; 6C6BD6ED29CD123000235D17 /* Extensions */ = { isa = PBXGroup; children = ( @@ -2154,6 +2175,7 @@ B61DA9DD29D929BF00BF4A43 /* Pages */ = { isa = PBXGroup; children = ( + 6C5BE51A2A3D5419002DA0FC /* FeatureFlags */, B6CF632629E5417C0085880A /* Keybindings */, B6E41C6E29DD15540088F9F4 /* AccountsSettings */, B6EA1FF329DA37D3001BF195 /* TextEditingSettings */, @@ -2244,7 +2266,7 @@ B658FB3327DA9E1000EA4DBD /* Assets.xcassets */, B658FB3827DA9E1000EA4DBD /* CodeEdit.entitlements */, B66A4E4B29C9179B004573B4 /* CodeEditApp.swift */, - 6CE60BDC2A226A870075D21E /* Scene+Environment.swift */, + 6C7F38002A3EA71400217B83 /* WindowSplitView.swift */, 04660F6027E3A68A00477777 /* Info.plist */, B66A4E5529C918A0004573B4 /* SceneID.swift */, B658FB3127DA9E0F00EA4DBD /* WorkspaceView.swift */, @@ -2487,6 +2509,7 @@ 6CDEFC9529E22C2700B7C684 /* Introspect */, 6CC81CEB2A16BB8F00487975 /* CodeEditTextView */, 6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */, + 6C5BE5212A3D5666002DA0FC /* WindowManagement */, ); productName = CodeEdit; productReference = B658FB2C27DA9E0F00EA4DBD /* CodeEdit.app */; @@ -2582,6 +2605,7 @@ 6CDEFC9429E22C2700B7C684 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, 6CC81CEA2A16BB8F00487975 /* XCRemoteSwiftPackageReference "CodeEditTextView" */, 6C0F3A3A2A1D0D5000223D19 /* XCRemoteSwiftPackageReference "CodeEditKit" */, + 6C5BE5202A3D5666002DA0FC /* XCRemoteSwiftPackageReference "SwiftUI-WindowManagement" */, ); productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */; projectDirPath = ""; @@ -2752,6 +2776,7 @@ 587B9E5E29301D8F00AC7927 /* GitLabCommitRouter.swift in Sources */, 58F2EB0D292FB2B0004A9BDE /* ThemeSettings.swift in Sources */, 85CD0C5F2A10CC3200E531FD /* URL+isImage.swift in Sources */, + 6C5BE51E2A3D545F002DA0FC /* FeatureFlagsSettings.swift in Sources */, 587B9D9F29300ABD00AC7927 /* SegmentedControl.swift in Sources */, 6C7256D729A3D7D000C2D3E0 /* SplitViewControllerView.swift in Sources */, B6EA1FE529DA33DB001BF195 /* ThemeModel.swift in Sources */, @@ -2803,6 +2828,7 @@ 587B9E8D29301D8F00AC7927 /* GitHubAccount.swift in Sources */, 201169E72837B5CA00F92B46 /* SourceControlModel.swift in Sources */, 58822528292C280D00E83CDE /* StatusBarEncodingSelector.swift in Sources */, + 6C7F37FE2A3EA6FA00217B83 /* View+focusedValue.swift in Sources */, B6C6A43029771F7100A3D28F /* TabBarItemBackground.swift in Sources */, 6C578D8129CD294800DC73B2 /* ExtensionActivatorView.swift in Sources */, B6F0517D29D9E4B100D72287 /* TerminalSettingsView.swift in Sources */, @@ -2824,11 +2850,13 @@ 587B9E6629301D8F00AC7927 /* GitLabProjectHook.swift in Sources */, 587B9E9329301D8F00AC7927 /* BitBucketOAuthConfiguration.swift in Sources */, 6C18620A298BF5A800C663EA /* RecentProjectsListView.swift in Sources */, + 6C7F38012A3EA71400217B83 /* WindowSplitView.swift in Sources */, 58F2EB0A292FB2B0004A9BDE /* SettingsData.swift in Sources */, 20EBB503280C327C00F3A5DA /* HistoryInspectorView.swift in Sources */, B6EA1FE729DA341D001BF195 /* Theme.swift in Sources */, 587B9E7529301D8F00AC7927 /* String+QueryParameters.swift in Sources */, 58798219292D92370085B254 /* SearchModeModel.swift in Sources */, + 6C5C891B2A3F736500A94FE1 /* FocusedValues.swift in Sources */, B62AEDD72A27B3D0009A9F52 /* DebugAreaTabViewModel.swift in Sources */, B66A4E4F29C917B8004573B4 /* WelcomeWindow.swift in Sources */, 58D01C9D293167DC00C5B6B4 /* KeychainSwiftAccessOptions.swift in Sources */, @@ -2901,6 +2929,7 @@ 285FEC7027FE4B9800E57D53 /* ProjectNavigatorTableViewCell.swift in Sources */, 6CB9144B29BEC7F100BC47F2 /* (null) in Sources */, 587B9E7429301D8F00AC7927 /* URL+URLParameters.swift in Sources */, + 6C5BE51C2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift in Sources */, 581BFB6B2926431000D251EC /* RecentProjectItem.swift in Sources */, 587FB99029C1246400B519DD /* TabBarItemView.swift in Sources */, 587B9DA429300ABD00AC7927 /* OverlayPanel.swift in Sources */, @@ -2922,7 +2951,6 @@ 587B9E7E29301D8F00AC7927 /* GitHubGistRouter.swift in Sources */, 6CAAF69229BCC71C00A1F48A /* (null) in Sources */, 581BFB682926431000D251EC /* WelcomeView.swift in Sources */, - 6CE60BDD2A226A870075D21E /* Scene+Environment.swift in Sources */, 6CFF967829BEBCF600182D6F /* MainCommands.swift in Sources */, 587B9E7129301D8F00AC7927 /* GitURLSession.swift in Sources */, 5882252C292C280D00E83CDE /* DebugAreaView.swift in Sources */, @@ -3990,6 +4018,14 @@ minimumVersion = 1.0.0; }; }; + 6C5BE5202A3D5666002DA0FC /* XCRemoteSwiftPackageReference "SwiftUI-WindowManagement" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Wouter01/SwiftUI-WindowManagement"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.1.0; + }; + }; 6C66C31129D05CC800DE9ED2 /* XCRemoteSwiftPackageReference "GRDB.swift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/groue/GRDB.swift.git"; @@ -4060,6 +4096,11 @@ package = 6C21493F2A1BB9AB00748382 /* XCRemoteSwiftPackageReference "LogStream" */; productName = LogStream; }; + 6C5BE5212A3D5666002DA0FC /* WindowManagement */ = { + isa = XCSwiftPackageProductDependency; + package = 6C5BE5202A3D5666002DA0FC /* XCRemoteSwiftPackageReference "SwiftUI-WindowManagement" */; + productName = WindowManagement; + }; 6C66C31229D05CDC00DE9ED2 /* GRDB */ = { isa = XCSwiftPackageProductDependency; package = 6C66C31129D05CC800DE9ED2 /* XCRemoteSwiftPackageReference "GRDB.swift" */; diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 469944e7d..39b4b71b3 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -225,6 +225,15 @@ "version" : "0.6.1" } }, + { + "identity" : "swiftui-windowmanagement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Wouter01/SwiftUI-WindowManagement", + "state" : { + "revision" : "03642ad06a3aa51e8284eb22146a208269cdc1ca", + "version" : "2.1.0" + } + }, { "identity" : "textformation", "kind" : "remoteSourceControl", diff --git a/CodeEdit/CodeEditApp.swift b/CodeEdit/CodeEditApp.swift index ed6f06bae..3cea4b7f2 100644 --- a/CodeEdit/CodeEditApp.swift +++ b/CodeEdit/CodeEditApp.swift @@ -6,11 +6,15 @@ // import SwiftUI +import WindowManagement @main struct CodeEditApp: App { @NSApplicationDelegateAdaptor var appdelegate: AppDelegate @ObservedObject var settings = Settings.shared + + @Environment(\.openWindow) var openWindow + let updater: SoftwareUpdater = SoftwareUpdater() init() { @@ -30,9 +34,19 @@ struct CodeEditApp: App { AboutWindow() SettingsWindow() - .commands { - CodeEditCommands() - } + + NSDocumentGroup(for: WorkspaceDocument.self) { workspace in + WindowSplitView(workspace: workspace) + } defaultAction: { + openWindow(id: SceneID.welcome.rawValue) + } + .register(.document(WorkspaceDocument.self)) // Required to make transition modifier work + .transition(.documentWindow) + .windowToolbarStyle(.unifiedCompact(showsTitle: false)) + .enableOpenWindow() // Required for opening windows through NSApp + .commands { + CodeEditCommands() + } } .environment(\.settings, settings.preferences) // Add settings to each window environment } diff --git a/CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift b/CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift index e5085fb39..585acb901 100644 --- a/CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift +++ b/CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift @@ -21,6 +21,12 @@ class DebugAreaViewModel: ObservableObject { @Published var cursorLocation: CursorLocation = .init(line: 1, column: 1) // Implementation needed!! + @Published + var terminals: [DebugAreaTerminal] = [] + + @Published + var selectedTerminals: Set = [] + /// Indicates whether debugger is collapse or not @Published var isCollapsed: Bool = false @@ -58,6 +64,14 @@ class DebugAreaViewModel: ObservableObject { /// The minimum height of the drawer private(set) var minHeight: Double = 100 + func removeTerminals(_ ids: Set) { + terminals.removeAll(where: { terminal in + ids.contains(terminal.id) + }) + + selectedTerminals = [terminals.last?.id ?? UUID()] + } + init() { // !!!: Lots of things in this class can be removed, such as maxHeight, as they are defined in the UI. } diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift b/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift index e27929a91..c116d195a 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift +++ b/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift @@ -39,17 +39,6 @@ struct DebugAreaTerminalTab: View { TextField("Name", text: terminalTitle) .focused($isFocused) .padding(.leading, -8) - .background { - if isSelected { - Button("Kill Terminal") { - removeTerminals(selectedIDs) - } - .keyboardShortcut(.delete, modifiers: [.command]) - .frame(width: 0, height: 0) - .clipped() - .opacity(0) - } - } } icon: { Image(systemName: "terminal") } @@ -60,7 +49,6 @@ struct DebugAreaTerminalTab: View { Button("Kill Terminal") { if isSelected { removeTerminals([terminal.id]) } } - .keyboardShortcut(.delete, modifiers: [.command]) } } } diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift b/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift index 4654f63b7..5fc7bfc30 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift +++ b/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift @@ -45,12 +45,6 @@ struct DebugAreaTerminalView: View { @StateObject private var themeModel: ThemeModel = .shared - @State - var terminals: [DebugAreaTerminal] = [] - - @State - private var selectedIDs: Set = [UUID()] - @State private var isMenuVisible = false @@ -60,7 +54,7 @@ struct DebugAreaTerminalView: View { private func initializeTerminals() { let id = UUID() - terminals = [ + model.terminals = [ DebugAreaTerminal( id: id, url: workspace.workspaceFileManager?.folderUrl ?? URL(filePath: "/"), @@ -69,13 +63,13 @@ struct DebugAreaTerminalView: View { ) ] - selectedIDs = [id] + model.selectedTerminals = [id] } private func addTerminal(shell: String? = nil) { let id = UUID() - terminals.append( + model.terminals.append( DebugAreaTerminal( id: id, url: URL(filePath: "\(id)"), @@ -84,25 +78,17 @@ struct DebugAreaTerminalView: View { ) ) - selectedIDs = [id] - } - - private func removeTerminals(_ ids: Set) { - terminals.removeAll(where: { terminal in - ids.contains(terminal.id) - }) - - selectedIDs = [terminals.last?.id ?? UUID()] + model.selectedTerminals = [id] } private func getTerminal(_ id: UUID) -> DebugAreaTerminal? { - return terminals.first(where: { $0.id == id }) ?? nil + return model.terminals.first(where: { $0.id == id }) ?? nil } private func updateTerminal(_ id: UUID, title: String? = nil) { - let terminalIndex = terminals.firstIndex(where: { $0.id == id }) + let terminalIndex = model.terminals.firstIndex(where: { $0.id == id }) if terminalIndex != nil { - updateTerminalByReference(of: &terminals[terminalIndex!], title: title) + updateTerminalByReference(of: &model.terminals[terminalIndex!], title: title) } } @@ -134,19 +120,19 @@ struct DebugAreaTerminalView: View { } func moveItems(from source: IndexSet, to destination: Int) { - terminals.move(fromOffsets: source, toOffset: destination) + model.terminals.move(fromOffsets: source, toOffset: destination) } var body: some View { DebugAreaTabView { tabState in ZStack { - if selectedIDs.isEmpty { + if model.selectedTerminals.isEmpty { Text("No Selection") .font(.system(size: 16)) .foregroundColor(.secondary) .frame(maxWidth: .infinity, maxHeight: .infinity) } - ForEach(terminals) { terminal in + ForEach(model.terminals) { terminal in TerminalEmulatorView( url: terminal.url!, shellType: terminal.shell, @@ -157,13 +143,13 @@ struct DebugAreaTerminalView: View { .padding(.top, 10) .padding(.horizontal, 10) .contentShape(Rectangle()) - .disabled(terminal.id != selectedIDs.first) - .opacity(terminal.id == selectedIDs.first ? 1 : 0) + .disabled(terminal.id != model.selectedTerminals.first) + .opacity(terminal.id == model.selectedTerminals.first ? 1 : 0) } } .paneToolbar { PaneToolbarSection { - DebugAreaTerminalPicker(selectedIDs: $selectedIDs, terminals: terminals) + DebugAreaTerminalPicker(selectedIDs: $model.selectedTerminals, terminals: model.terminals) .opacity(tabState.leadingSidebarIsCollapsed ? 1 : 0) } Spacer() @@ -181,7 +167,7 @@ struct DebugAreaTerminalView: View { } } .background { - if selectedIDs.isEmpty { + if model.selectedTerminals.isEmpty { EffectView(.contentBackground) } else if useThemeBackground { Color(nsColor: backgroundColor) @@ -194,25 +180,26 @@ struct DebugAreaTerminalView: View { } } .colorScheme( - selectedIDs.isEmpty + model.selectedTerminals.isEmpty ? colorScheme : matchAppearance && darkAppearance ? themeModel.selectedDarkTheme?.appearance == .dark ? .dark : .light : themeModel.selectedTheme?.appearance == .dark ? .dark : .light ) } leadingSidebar: { _ in - List(selection: $selectedIDs) { - ForEach($terminals, id: \.self.id) { $terminal in + List(selection: $model.selectedTerminals) { + ForEach($model.terminals, id: \.self.id) { $terminal in DebugAreaTerminalTab( terminal: $terminal, - removeTerminals: removeTerminals, - isSelected: selectedIDs.contains(terminal.id), - selectedIDs: selectedIDs + removeTerminals: model.removeTerminals, + isSelected: model.selectedTerminals.contains(terminal.id), + selectedIDs: model.selectedTerminals ) .tag(terminal.id) } .onMove(perform: moveItems) } + .focusedObject(model) .listStyle(.automatic) .accentColor(.secondary) .contextMenu { @@ -232,7 +219,7 @@ struct DebugAreaTerminalView: View { } } } - .onChange(of: terminals) { newValue in + .onChange(of: model.terminals) { newValue in if newValue.isEmpty { addTerminal() } @@ -245,12 +232,12 @@ struct DebugAreaTerminalView: View { Image(systemName: "plus") } Button { - removeTerminals(selectedIDs) + model.removeTerminals(model.selectedTerminals) } label: { Image(systemName: "minus") } - .disabled(terminals.count <= 1) - .opacity(terminals.count <= 1 ? 0.5 : 1) + .disabled(model.terminals.count <= 1) + .opacity(model.terminals.count <= 1 ? 0.5 : 1) } Spacer() } diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index b0431305c..8bb83ac49 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -9,6 +9,7 @@ import Foundation import AppKit import SwiftUI import Combine +import WindowManagement @objc(WorkspaceDocument) final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { @@ -72,22 +73,28 @@ import Combine } override func makeWindowControllers() { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 800, height: 600), - styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], - backing: .buffered, defer: false - ) - window.center() - window.minSize = .init(width: 1000, height: 600) - let windowController = CodeEditWindowController( - window: window, - workspace: self - ) - - windowController.shouldCascadeWindows = true - windowController.window?.setFrameAutosaveName(self.fileURL?.absoluteString ?? "Untitled") - self.addWindowController(windowController) + if Settings[\.featureFlags.useNewWindowingSystem] { + let window = NSApp.openDocument(self) + if let windowController = window?.windowController { + self.addWindowController(windowController) + } + } else { + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 800, height: 600), + styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], + backing: .buffered, defer: false + ) + window.center() + window.minSize = .init(width: 1000, height: 600) + let windowController = CodeEditWindowController( + window: window, + workspace: self + ) + windowController.shouldCascadeWindows = true + windowController.window?.setFrameAutosaveName(self.fileURL?.absoluteString ?? "Untitled") + self.addWindowController(windowController) + } // TODO: Fix restoration // var activeTabID: TabBarItemID? // var activeTabInState = self.getFromWorkspaceState(key: activeTabStateName) as? String ?? "" diff --git a/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift b/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift index a8c32d088..801b325ee 100644 --- a/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift +++ b/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift @@ -23,7 +23,8 @@ struct InspectorSidebarView: View { @State private var selection: InspectorTab? = .quickhelp - var path: String? { tabManager.activeTabGroup.selected?.fileDocument?.fileURL?.path(percentEncoded: false) + var path: String? { + tabManager.activeTabGroup.selected?.fileDocument?.fileURL?.path(percentEncoded: false) } var fileTreeAndGitHistory: [InspectorTab] { diff --git a/CodeEdit/Features/Settings/Models/SettingsData.swift b/CodeEdit/Features/Settings/Models/SettingsData.swift index b7e2844e3..96560de55 100644 --- a/CodeEdit/Features/Settings/Models/SettingsData.swift +++ b/CodeEdit/Features/Settings/Models/SettingsData.swift @@ -43,6 +43,9 @@ struct SettingsData: Codable, Hashable { /// The global settings for keybindings var keybindings: KeybindingsSettings = .init() + /// Featureflags settings + var featureFlags: FeatureFlagsSettings = .init() + /// Default initializer init() {} @@ -59,5 +62,6 @@ struct SettingsData: Codable, Hashable { forKey: .sourceControl ) ?? .init() self.keybindings = try container.decodeIfPresent(KeybindingsSettings.self, forKey: .keybindings) ?? .init() + self.featureFlags = try container.decodeIfPresent(FeatureFlagsSettings.self, forKey: .featureFlags) ?? .init() } } diff --git a/CodeEdit/Features/Settings/Models/SettingsPage.swift b/CodeEdit/Features/Settings/Models/SettingsPage.swift index 613cb3933..41788f2a6 100644 --- a/CodeEdit/Features/Settings/Models/SettingsPage.swift +++ b/CodeEdit/Features/Settings/Models/SettingsPage.swift @@ -55,6 +55,7 @@ struct SettingsPage: Hashable, Identifiable { case sourceControl = "Source Control" case components = "Components" case location = "Locations" + case featureFlags = "Feature Flags" case advanced = "Advanced" } diff --git a/CodeEdit/Features/Settings/Pages/FeatureFlags/FeatureFlagsSettings.swift b/CodeEdit/Features/Settings/Pages/FeatureFlags/FeatureFlagsSettings.swift new file mode 100644 index 000000000..5f91ef789 --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/FeatureFlags/FeatureFlagsSettings.swift @@ -0,0 +1,15 @@ +// +// FeatureFlagsSettings.swift +// CodeEdit +// +// Created by Wouter Hennen on 17/06/2023. +// + +import Foundation + +extension SettingsData { + + struct FeatureFlagsSettings: Codable, Hashable { + var useNewWindowingSystem = false + } +} diff --git a/CodeEdit/Features/Settings/Pages/FeatureFlags/FeatureFlagsSettingsView.swift b/CodeEdit/Features/Settings/Pages/FeatureFlags/FeatureFlagsSettingsView.swift new file mode 100644 index 000000000..55e5d58fa --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/FeatureFlags/FeatureFlagsSettingsView.swift @@ -0,0 +1,30 @@ +// +// FeatureFlagsSettingsView.swift +// CodeEdit +// +// Created by Wouter Hennen on 17/06/2023. +// + +import SwiftUI + +struct FeatureFlagsSettingsView: View { + + @AppSettings(\.featureFlags.useNewWindowingSystem) var useNewWindowingSystem + + var body: some View { + Form { + VStack(alignment: .leading) { + Toggle("New Windowing System", isOn: $useNewWindowingSystem) + Text( + """ + Active workspaces must be reopened in order to take effect. + Inspector only works on macOS Sonoma. + """ + ) + .font(.footnote) + .foregroundStyle(.secondary) + } + } + .formStyle(.grouped) + } +} diff --git a/CodeEdit/Features/Settings/SettingsView.swift b/CodeEdit/Features/Settings/SettingsView.swift index 1591d20e9..6269a66f3 100644 --- a/CodeEdit/Features/Settings/SettingsView.swift +++ b/CodeEdit/Features/Settings/SettingsView.swift @@ -28,6 +28,7 @@ struct SettingsView: View { .init(.sourceControl, baseColor: .blue, icon: .symbol("vault")), // .init(.components, baseColor: .blue, icon: .system("puzzlepiece.fill")), .init(.location, baseColor: .green, icon: .system("externaldrive.fill")), + .init(.featureFlags, baseColor: .cyan, icon: .system("flag.2.crossed.fill")) // .init(.advanced, baseColor: .gray, icon: .system("gearshape.2.fill")) ] @@ -76,6 +77,8 @@ struct SettingsView: View { SourceControlSettingsView() case .location: LocationsSettingsView() + case .featureFlags: + FeatureFlagsSettingsView() default: Text("Implementation Needed").frame(alignment: .center) } diff --git a/CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift b/CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift index 570158065..239247d11 100644 --- a/CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift +++ b/CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift @@ -207,6 +207,30 @@ final class TabGroupData: ObservableObject, Identifiable { CodeEditDocumentController.shared.addDocument(codeFile) print("Opening file for item: ", item.url) } + + func goBackInHistory() { + if canGoBackInHistory { + historyOffset += 1 + } + } + + func goForwardInHistory() { + if canGoForwardInHistory { + historyOffset -= 1 + } + } + + // TODO: move to @Observable so this works better + /// Warning: NOT published! + var canGoBackInHistory: Bool { + historyOffset != history.count-1 && !history.isEmpty + } + + // TODO: move to @Observable so this works better + /// Warning: NOT published! + var canGoForwardInHistory: Bool { + historyOffset != 0 + } } extension TabGroupData: Equatable, Hashable { diff --git a/CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift b/CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift index 726556976..99895be83 100644 --- a/CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift +++ b/CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift @@ -21,6 +21,7 @@ struct WorkspaceTabGroupView: View { VStack { if let selected = tabgroup.selected { WorkspaceCodeFileView(file: selected) + .focusedObject(tabgroup) .transformEnvironment(\.edgeInsets) { insets in insets.top += TabBarView.height + PathBarView.height + 1 + 1 } diff --git a/CodeEdit/Features/Tabs/Views/TabBarView.swift b/CodeEdit/Features/Tabs/Views/TabBarView.swift index 0ff4f3619..8427d46a4 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarView.swift +++ b/CodeEdit/Features/Tabs/Views/TabBarView.swift @@ -486,7 +486,7 @@ struct TabBarView: View { ) } primaryAction: { tabManager.activeTabGroup = tabgroup - tabgroup.historyOffset += 1 + tabgroup.goBackInHistory() } .disabled(tabgroup.historyOffset == tabgroup.history.count-1 || tabgroup.history.isEmpty) .help("Navigate back") @@ -512,7 +512,7 @@ struct TabBarView: View { .opacity(tabgroup.historyOffset == 0 ? 0.5 : 1.0) } primaryAction: { tabManager.activeTabGroup = tabgroup - tabgroup.historyOffset -= 1 + tabgroup.goForwardInHistory() } .disabled(tabgroup.historyOffset == 0) .help("Navigate forward") diff --git a/CodeEdit/Features/WindowCommands/FileCommands.swift b/CodeEdit/Features/WindowCommands/FileCommands.swift index 4cea8ca30..412c3145c 100644 --- a/CodeEdit/Features/WindowCommands/FileCommands.swift +++ b/CodeEdit/Features/WindowCommands/FileCommands.swift @@ -8,6 +8,9 @@ import SwiftUI struct FileCommands: Commands { + + @FocusedObject var debugAreaViewModel: DebugAreaViewModel? + var body: some Commands { CommandGroup(replacing: .newItem) { Group { @@ -53,6 +56,13 @@ struct FileCommands: Commands { } .keyboardShortcut("w", modifiers: [.control, .option, .command]) + if let debugAreaViewModel { + Button("Close Terminal") { + debugAreaViewModel.removeTerminals(debugAreaViewModel.selectedTerminals) + } + .keyboardShortcut(.delete) + } + Divider() Button("Save") { diff --git a/CodeEdit/Features/WindowCommands/NavigateCommands.swift b/CodeEdit/Features/WindowCommands/NavigateCommands.swift index 563b8036a..54d5162e0 100644 --- a/CodeEdit/Features/WindowCommands/NavigateCommands.swift +++ b/CodeEdit/Features/WindowCommands/NavigateCommands.swift @@ -8,6 +8,9 @@ import SwiftUI struct NavigateCommands: Commands { + + @FocusedObject var tabGroup: TabGroupData? + var body: some Commands { CommandMenu("Navigate") { Group { @@ -32,61 +35,31 @@ struct NavigateCommands: Commands { Divider() - Button("Show Previous Tab") { - - } - - Button("Show Next Tab") { - - } - - Divider() - - Button("Go Forward") { - - } } .disabled(true) Group { - - Button("Go Back") { - - } - - Divider() - - Button("Jump to Selection") { - - } - .keyboardShortcut("l", modifiers: [.command, .option]) - - Button("Jump to Definition") { - - } - .keyboardShortcut("j") - - Button("Jump to Original Source") { + Button("Show Previous Tab") { } - Button("Jump to Last Destination") { + Button("Show Next Tab") { } Divider() - Button("Jump to Next Issue") { - + Button("Go Forward") { + tabGroup?.goForwardInHistory() } - .keyboardShortcut("'") - - Button("Jump to Previous Issue") { + .disabled(!(tabGroup?.canGoForwardInHistory ?? false)) + Button("Go Back") { + tabGroup?.goBackInHistory() } - .keyboardShortcut("\"") + .disabled(!(tabGroup?.canGoBackInHistory ?? false)) } - .disabled(true) + .disabled(tabGroup == nil) } } } diff --git a/CodeEdit/Features/WindowCommands/ViewCommands.swift b/CodeEdit/Features/WindowCommands/ViewCommands.swift index 5e23b923d..db06653fd 100644 --- a/CodeEdit/Features/WindowCommands/ViewCommands.swift +++ b/CodeEdit/Features/WindowCommands/ViewCommands.swift @@ -10,12 +10,17 @@ import SwiftUI struct ViewCommands: Commands { @AppSettings(\.textEditing.font.size) var editorFontSize @AppSettings(\.terminal.font.size) var terminalFontSize + @AppSettings(\.featureFlags.useNewWindowingSystem) var useNewWindowingSystem @State var windowController: CodeEditWindowController? private let documentController: CodeEditDocumentController = CodeEditDocumentController() private let statusBarViewModel: DebugAreaViewModel = DebugAreaViewModel() + @FocusedBinding(\.navigationSplitViewVisibility) var navigationSplitViewVisibility + + @FocusedBinding(\.inspectorVisibility) var inspectorVisibility + var navigatorCollapsed: Bool { windowController?.navigatorCollapsed ?? false } @@ -60,20 +65,41 @@ struct ViewCommands: Commands { Divider() - Button("\(navigatorCollapsed ? "Show" : "Hide") Navigator") { - windowController?.toggleFirstPanel() - } - .disabled(windowController == nil) - .keyboardShortcut("s", modifiers: [.control, .command]) - .onReceive(NSApp.publisher(for: \.keyWindow)) { window in - windowController = window?.windowController as? CodeEditWindowController - } + if useNewWindowingSystem { + Button("\(navigationSplitViewVisibility == .detailOnly ? "Show" : "Hide") Navigator") { + withAnimation(.linear(duration: .zero)) { + if navigationSplitViewVisibility == .all { + navigationSplitViewVisibility = .detailOnly + } else { + navigationSplitViewVisibility = .all + } + } + } + .disabled(navigationSplitViewVisibility == nil) + .keyboardShortcut("s", modifiers: [.control, .command]) - Button("\(inspectorCollapsed ? "Show" : "Hide") Inspector") { - windowController?.toggleLastPanel() + Button("\(inspectorVisibility == false ? "Show" : "Hide") Inspector") { + inspectorVisibility?.toggle() + } + .disabled(inspectorVisibility == nil) + .keyboardShortcut("i", modifiers: [.control, .command]) + + } else { + Button("\(navigatorCollapsed ? "Show" : "Hide") Navigator") { + windowController?.toggleFirstPanel() + } + .disabled(windowController == nil) + .keyboardShortcut("s", modifiers: [.control, .command]) + .onReceive(NSApp.publisher(for: \.keyWindow)) { window in + windowController = window?.windowController as? CodeEditWindowController + } + + Button("\(inspectorCollapsed ? "Show" : "Hide") Inspector") { + windowController?.toggleLastPanel() + } + .disabled(windowController == nil) + .keyboardShortcut("i", modifiers: [.control, .command]) } - .disabled(windowController == nil) - .keyboardShortcut("i", modifiers: [.control, .command]) } } } diff --git a/CodeEdit/Scene+Environment.swift b/CodeEdit/Scene+Environment.swift deleted file mode 100644 index eeb21fb80..000000000 --- a/CodeEdit/Scene+Environment.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Scene+Environment.swift -// CodeEdit -// -// Created by Wouter Hennen on 27/05/2023. -// - -import SwiftUI - -extension SwiftUI.Scene { - @inlinable - func modifier(_ modifier: T) -> ModifiedContent { - return .init(content: self, modifier: modifier) - } - - @inlinable - func environment(_ keyPath: WritableKeyPath, _ value: V) -> some Scene { - modifier(_EnvironmentKeyWritingModifier(keyPath: keyPath, value: value)) - } -} diff --git a/CodeEdit/Utils/Extensions/View/View+focusedValue.swift b/CodeEdit/Utils/Extensions/View/View+focusedValue.swift new file mode 100644 index 000000000..8e46de901 --- /dev/null +++ b/CodeEdit/Utils/Extensions/View/View+focusedValue.swift @@ -0,0 +1,18 @@ +// +// View+focusedValue.swift +// CodeEdit +// +// Created by Wouter Hennen on 18/06/2023. +// + +import SwiftUI + +extension View { + func focusedValue( + _ keyPath: WritableKeyPath, + disabled: Bool, + _ value: Value + ) -> some View { + focusedValue(keyPath, disabled ? nil : value) + } +} diff --git a/CodeEdit/Utils/FocusedValues.swift b/CodeEdit/Utils/FocusedValues.swift new file mode 100644 index 000000000..c1e983938 --- /dev/null +++ b/CodeEdit/Utils/FocusedValues.swift @@ -0,0 +1,28 @@ +// +// FocusedValues.swift +// CodeEdit +// +// Created by Wouter Hennen on 18/06/2023. +// + +import SwiftUI + +extension FocusedValues { + var navigationSplitViewVisibility: Binding? { + get { self[NavSplitViewVisibilityFocusedValueKey.self] } + set { self[NavSplitViewVisibilityFocusedValueKey.self] = newValue } + } + + var inspectorVisibility: Binding? { + get { self[InspectorVisibilityFocusedValueKey.self] } + set { self[InspectorVisibilityFocusedValueKey.self] = newValue } + } + + private struct NavSplitViewVisibilityFocusedValueKey: FocusedValueKey { + typealias Value = Binding + } + + private struct InspectorVisibilityFocusedValueKey: FocusedValueKey { + typealias Value = Binding + } +} diff --git a/CodeEdit/WindowSplitView.swift b/CodeEdit/WindowSplitView.swift new file mode 100644 index 000000000..ea6d3993e --- /dev/null +++ b/CodeEdit/WindowSplitView.swift @@ -0,0 +1,79 @@ +// +// WindowSplitView.swift +// CodeEdit +// +// Created by Wouter Hennen on 18/06/2023. +// + +import SwiftUI + +struct WindowSplitView: View { + @StateObject var workspace: WorkspaceDocument + @State var visibility: NavigationSplitViewVisibility = .all + @State var showInspector = true + @State var window: NSWindow = .init() + + var body: some View { + WindowObserver(window: window) { + NavigationSplitView(columnVisibility: $visibility) { + NavigatorSidebarView(workspace: workspace) + .toolbar { + ToolbarItem { + Button { + withAnimation(.linear(duration: 0)) { + if visibility == .detailOnly { + visibility = .all + } else { + visibility = .detailOnly + } + } + } label: { + Image(systemName: "sidebar.left") + .imageScale(.large) + } + } + } + } detail: { + if #available(macOS 14.0, *) { + WorkspaceView() + .toolbar { + ToolbarItem(id: "com.apple.SwiftUI.navigationSplitView.toggleSidebar") { + ToolbarBranchPicker( + shellClient: currentWorld.shellClient, + workspaceFileManager: workspace.workspaceFileManager + ) + } + .defaultCustomization(.hidden, options: []) + } +#if swift(>=5.9) // Fix build on Xcode 14 + .inspector(isPresented: $showInspector) { + InspectorSidebarView() + .inspectorColumnWidth(min: 100, ideal: 200, max: 400) + .toolbar { + Spacer() + Button { + showInspector.toggle() + } label: { + Image(systemName: "sidebar.right") + .imageScale(.large) + } + } + } +#endif + } else { + WorkspaceView() + } + } + } + .focusedSceneValue(\.navigationSplitViewVisibility, $visibility) + .focusedSceneValue(\.inspectorVisibility, $showInspector) + .environmentObject(workspace) + .environmentObject(workspace.tabManager) + .environmentObject(workspace.debugAreaModel) + .task { + if let newWindow = workspace.windowControllers.first?.window { + window = newWindow + } + } + } +} diff --git a/CodeEdit/WorkspaceView.swift b/CodeEdit/WorkspaceView.swift index 055fa7ff8..20de44548 100644 --- a/CodeEdit/WorkspaceView.swift +++ b/CodeEdit/WorkspaceView.swift @@ -22,9 +22,6 @@ struct WorkspaceView: View { @EnvironmentObject private var debugAreaModel: DebugAreaViewModel - @Environment(\.window) - private var window - private var keybindings: KeybindingManager = .shared @State