From 1d590a9657bde6ccd650ce241c94200d3ba076ec Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:20:58 -0500 Subject: [PATCH 01/15] Update Project, Use local WelcomeWindow for now --- CodeEdit.xcodeproj/project.pbxproj | 59 +++++++++++++------ .../xcshareddata/swiftpm/Package.resolved | 11 +--- .../xcshareddata/xcschemes/CodeEdit.xcscheme | 2 +- .../xcschemes/OpenWithCodeEdit.xcscheme | 2 +- .../OpenWithCodeEdit.entitlements | 4 -- 5 files changed, 44 insertions(+), 34 deletions(-) diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index ff63c4974c..76a598e48f 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -18,11 +18,11 @@ 58F2EB03292FB2B0004A9BDE /* Documentation.docc in Sources */ = {isa = PBXBuildFile; fileRef = 58F2EACE292FB2B0004A9BDE /* Documentation.docc */; }; 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 58F2EB1D292FB954004A9BDE /* Sparkle */; }; 5E4485612DF600D9008BBE69 /* AboutWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 5E4485602DF600D9008BBE69 /* AboutWindow */; }; - 5EACE6222DF4BF08005E08B8 /* WelcomeWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 5EACE6212DF4BF08005E08B8 /* WelcomeWindow */; }; 6C0617D62BDB4432008C9C42 /* LogStream in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0617D52BDB4432008C9C42 /* LogStream */; }; 6C0824A12C5C0C9700A0751E /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0824A02C5C0C9700A0751E /* SwiftTerm */; }; 6C147C4529A329350089B630 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 6C147C4429A329350089B630 /* OrderedCollections */; }; 6C315FC82E05E33D0011BFC5 /* CodeEditSourceEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 6C315FC72E05E33D0011BFC5 /* CodeEditSourceEditor */; }; + 6C33D9FB2E5F9184007782E7 /* WelcomeWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */; }; 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = 6C66C31229D05CDC00DE9ED2 /* GRDB */; }; 6C6BD6F429CD142C00235D17 /* CollectionConcurrencyKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C6BD6F329CD142C00235D17 /* CollectionConcurrencyKit */; }; 6C6BD6F829CD14D100235D17 /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C6BD6F729CD14D100235D17 /* CodeEditKit */; }; @@ -187,12 +187,12 @@ 30CB64912C16CA8100CC8A9E /* LanguageServerProtocol in Frameworks */, 5E4485612DF600D9008BBE69 /* AboutWindow in Frameworks */, 6C6BD6F429CD142C00235D17 /* CollectionConcurrencyKit in Frameworks */, + 6C33D9FB2E5F9184007782E7 /* WelcomeWindow in Frameworks */, 6C85BB442C210EFD00EB5DEF /* SwiftUIIntrospect in Frameworks */, 6CB446402B6DFF3A00539ED0 /* CodeEditSourceEditor in Frameworks */, 6C73A6D32D4F1E550012D95C /* CodeEditSourceEditor in Frameworks */, 2816F594280CF50500DD548B /* CodeEditSymbols in Frameworks */, 30CB64942C16CA9100CC8A9E /* LanguageClient in Frameworks */, - 5EACE6222DF4BF08005E08B8 /* WelcomeWindow in Frameworks */, 6C6BD6F829CD14D100235D17 /* CodeEditKit in Frameworks */, 6C0824A12C5C0C9700A0751E /* SwiftTerm in Frameworks */, 6C81916B29B41DD300B75C92 /* DequeModule in Frameworks */, @@ -331,12 +331,12 @@ 6CC00A8A2CBEF150004E8134 /* CodeEditSourceEditor */, 30818CB42D4E563900967860 /* ZIPFoundation */, 6C73A6D22D4F1E550012D95C /* CodeEditSourceEditor */, - 5EACE6212DF4BF08005E08B8 /* WelcomeWindow */, 5E4485602DF600D9008BBE69 /* AboutWindow */, 6C315FC72E05E33D0011BFC5 /* CodeEditSourceEditor */, 6C76D6D32E15B91E00EF52C3 /* CodeEditSourceEditor */, 6CCF6DD22E26D48F00B94F75 /* SwiftTerm */, 6CCF73CF2E26DE3200B94F75 /* SwiftTerm */, + 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */, ); productName = CodeEdit; productReference = B658FB2C27DA9E0F00EA4DBD /* CodeEdit.app */; @@ -397,7 +397,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1330; - LastUpgradeCheck = 1640; + LastUpgradeCheck = 2600; TargetAttributes = { 2BE487EB28245162003F3F64 = { CreatedOnToolsVersion = 13.3.1; @@ -439,10 +439,10 @@ 303E88462C276FD600EEA8D9 /* XCRemoteSwiftPackageReference "LanguageServerProtocol" */, 6CB94D012CA1205100E8651C /* XCRemoteSwiftPackageReference "swift-async-algorithms" */, 30ED7B722DD299E600ACC922 /* XCRemoteSwiftPackageReference "ZIPFoundation" */, - 5EACE6202DF4BF08005E08B8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */, 5E44855F2DF600D9008BBE69 /* XCRemoteSwiftPackageReference "AboutWindow" */, 6C76D6D22E15B91E00EF52C3 /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */, 6CCF73CE2E26DE3200B94F75 /* XCRemoteSwiftPackageReference "SwiftTerm" */, + 6C33D9F92E5F9184007782E7 /* XCLocalSwiftPackageReference "../WelcomeWindow" */, ); preferredProjectObjectVersion = 55; productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */; @@ -650,6 +650,7 @@ OTHER_SWIFT_FLAGS = "-D ALPHA"; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -673,6 +674,7 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -690,6 +692,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -766,6 +770,7 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -847,6 +852,7 @@ OTHER_SWIFT_FLAGS = "-D BETA"; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -870,6 +876,7 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -887,6 +894,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -963,6 +972,7 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -998,6 +1008,7 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1033,6 +1044,7 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1115,6 +1127,7 @@ OTHER_SWIFT_FLAGS = "-D ALPHA"; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -1139,6 +1152,7 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -1156,6 +1170,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1232,6 +1248,7 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1319,6 +1336,7 @@ ONLY_ACTIVE_ARCH = YES; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -1384,6 +1402,7 @@ MTL_FAST_MATH = YES; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -1407,6 +1426,7 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -1424,6 +1444,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1448,6 +1470,7 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -1465,6 +1488,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1649,6 +1674,13 @@ }; /* End XCConfigurationList section */ +/* Begin XCLocalSwiftPackageReference section */ + 6C33D9F92E5F9184007782E7 /* XCLocalSwiftPackageReference "../WelcomeWindow" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = ../WelcomeWindow; + }; +/* End XCLocalSwiftPackageReference section */ + /* Begin XCRemoteSwiftPackageReference section */ 2816F592280CF50500DD548B /* XCRemoteSwiftPackageReference "CodeEditSymbols" */ = { isa = XCRemoteSwiftPackageReference; @@ -1738,14 +1770,6 @@ minimumVersion = 1.0.0; }; }; - 5EACE6202DF4BF08005E08B8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/CodeEditApp/WelcomeWindow"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.0.0; - }; - }; 6C0617D42BDB4432008C9C42 /* XCRemoteSwiftPackageReference "LogStream" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Wouter01/LogStream"; @@ -1864,11 +1888,6 @@ package = 5E44855F2DF600D9008BBE69 /* XCRemoteSwiftPackageReference "AboutWindow" */; productName = AboutWindow; }; - 5EACE6212DF4BF08005E08B8 /* WelcomeWindow */ = { - isa = XCSwiftPackageProductDependency; - package = 5EACE6202DF4BF08005E08B8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */; - productName = WelcomeWindow; - }; 6C0617D52BDB4432008C9C42 /* LogStream */ = { isa = XCSwiftPackageProductDependency; package = 6C0617D42BDB4432008C9C42 /* XCRemoteSwiftPackageReference "LogStream" */; @@ -1887,6 +1906,10 @@ isa = XCSwiftPackageProductDependency; productName = CodeEditSourceEditor; }; + 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */ = { + isa = XCSwiftPackageProductDependency; + productName = WelcomeWindow; + }; 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 9532347a14..5e6529adf7 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "01191ca9685501db65981a6fd21ab2d11c32196633d4cb776b5bb25908ed212f", + "originHash" : "658d82cd25b5cc6cfb47311fe2463f0a4d7e5cfaa82200a1fe9f7e4b2f10e1ef", "pins" : [ { "identity" : "aboutwindow", @@ -289,15 +289,6 @@ "version" : "0.25.6" } }, - { - "identity" : "welcomewindow", - "kind" : "remoteSourceControl", - "location" : "https://github.com/CodeEditApp/WelcomeWindow", - "state" : { - "revision" : "5168cf1ce9579b35ad00706fafef441418d8011f", - "version" : "1.0.0" - } - }, { "identity" : "zipfoundation", "kind" : "remoteSourceControl", diff --git a/CodeEdit.xcodeproj/xcshareddata/xcschemes/CodeEdit.xcscheme b/CodeEdit.xcodeproj/xcshareddata/xcschemes/CodeEdit.xcscheme index d05b0034c1..2c80a13978 100644 --- a/CodeEdit.xcodeproj/xcshareddata/xcschemes/CodeEdit.xcscheme +++ b/CodeEdit.xcodeproj/xcshareddata/xcschemes/CodeEdit.xcscheme @@ -1,6 +1,6 @@ - com.apple.security.app-sandbox - com.apple.security.application-groups app.codeedit.CodeEdit.shared $(TeamIdentifierPrefix) - com.apple.security.files.user-selected.read-only - From 9d74f8af509f179c03ca2f27d7c4397e0e558b7e Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:21:33 -0500 Subject: [PATCH 02/15] Fix Concurrency Issues --- CodeEdit/CodeEditApp.swift | 4 +++- .../CodeEditDocumentController.swift | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CodeEdit/CodeEditApp.swift b/CodeEdit/CodeEditApp.swift index 8222163ff1..17de696d90 100644 --- a/CodeEdit/CodeEditApp.swift +++ b/CodeEdit/CodeEditApp.swift @@ -37,7 +37,9 @@ struct CodeEditApp: App { OpenFileOrFolderButton(dismissWindow: dismissWindow) }, onDrop: { url, dismissWindow in - Task { CodeEditDocumentController.shared.openDocument(at: url, onCompletion: { dismissWindow() }) } + Task { + await CodeEditDocumentController.shared.openDocument(at: url, onCompletion: { dismissWindow() }) + } } ) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditDocumentController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditDocumentController.swift index 757aad3fdf..e666f7668f 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditDocumentController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditDocumentController.swift @@ -85,15 +85,17 @@ final class CodeEditDocumentController: NSDocumentController { } super.openDocument(withContentsOf: url, display: displayDocument) { document, documentWasAlreadyOpen, error in - if let document { - self.addDocument(document) - } else { - let errorMessage = error?.localizedDescription ?? "unknown error" - print("Unable to open document '\(url)': \(errorMessage)") - } + MainActor.assumeIsolated { + if let document { + self.addDocument(document) + } else { + let errorMessage = error?.localizedDescription ?? "unknown error" + print("Unable to open document '\(url)': \(errorMessage)") + } - RecentsStore.documentOpened(at: url) - completionHandler(document, documentWasAlreadyOpen, error) + RecentsStore.documentOpened(at: url) + completionHandler(document, documentWasAlreadyOpen, error) + } } } From a4c879f4a48b77929324be5cfa6b8ae3778ee8a0 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:22:11 -0500 Subject: [PATCH 03/15] Add Start/Stop Task Toolbar Group --- .../CodeEditSplitViewController.swift | 4 +- .../CodeEditWindowController+Toolbar.swift | 119 +++++++++++++----- .../CodeEditWindowControllerExtensions.swift | 2 + .../ToolbarItems/StartTaskToolbarItem.swift | 44 +++++++ .../ToolbarItems/StopTaskToolbarItem.swift | 81 ++++++++++++ .../Tasks/Views/StartTaskToolbarButton.swift | 4 +- 6 files changed, 216 insertions(+), 38 deletions(-) create mode 100644 CodeEdit/Features/Tasks/ToolbarItems/StartTaskToolbarItem.swift create mode 100644 CodeEdit/Features/Tasks/ToolbarItems/StopTaskToolbarItem.swift diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index a15ac9311e..27d2b4f4fc 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -97,7 +97,9 @@ final class CodeEditSplitViewController: NSSplitViewController { private func makeNavigator(view: some View) -> NSSplitViewItem { let navigator = NSSplitViewItem(sidebarWithViewController: NSHostingController(rootView: view)) - navigator.titlebarSeparatorStyle = .none + if #unavailable(macOS 26) { + navigator.titlebarSeparatorStyle = .none + } navigator.isSpringLoaded = true navigator.minimumThickness = Self.minSidebarWidth navigator.collapseBehavior = .useConstraints diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift index 4b434fbd44..7a8a5368ab 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift @@ -15,18 +15,34 @@ extension CodeEditWindowController { toolbar.delegate = self toolbar.displayMode = .labelOnly toolbar.showsBaselineSeparator = false - self.window?.titleVisibility = toolbarCollapsed ? .visible : .hidden - self.window?.toolbarStyle = .unifiedCompact + self.window?.titleVisibility = toolbarCollapsed ? .visible : .hidden + if #available(macOS 26, *) { + self.window?.toolbarStyle = .unified + } else { + self.window?.toolbarStyle = .unifiedCompact + } self.window?.titlebarSeparatorStyle = .automatic self.window?.toolbar = toolbar } func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { - [ + var items: [NSToolbarItem.Identifier] = [ .toggleFirstSidebarItem, .flexibleSpace, - .stopTaskSidebarItem, - .startTaskSidebarItem, + ] + + if #available(macOS 26, *) { + items += [ + .taskSidebarItem + ] + } else { + items += [ + .stopTaskSidebarItem, + .startTaskSidebarItem, + ] + } + + items += [ .sidebarTrackingSeparator, .branchPicker, .flexibleSpace, @@ -37,10 +53,12 @@ extension CodeEditWindowController { .flexibleSpace, .toggleLastSidebarItem ] + + return items } func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { - [ + var items: [NSToolbarItem.Identifier] = [ .toggleFirstSidebarItem, .sidebarTrackingSeparator, .flexibleSpace, @@ -49,9 +67,20 @@ extension CodeEditWindowController { .branchPicker, .activityViewer, .notificationItem, - .startTaskSidebarItem, - .stopTaskSidebarItem ] + + if #available(macOS 26, *) { + items += [ + .taskSidebarItem + ] + } else { + items += [ + .startTaskSidebarItem, + .stopTaskSidebarItem + ] + } + + return items } func toggleToolbar() { @@ -88,7 +117,6 @@ extension CodeEditWindowController { ) case .toggleFirstSidebarItem: let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.toggleFirstSidebarItem) - toolbarItem.label = "Navigator Sidebar" toolbarItem.paletteLabel = " Navigator Sidebar" toolbarItem.toolTip = "Hide or show the Navigator" toolbarItem.isBordered = true @@ -102,7 +130,6 @@ extension CodeEditWindowController { return toolbarItem case .toggleLastSidebarItem: let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.toggleLastSidebarItem) - toolbarItem.label = "Inspector Sidebar" toolbarItem.paletteLabel = "Inspector Sidebar" toolbarItem.toolTip = "Hide or show the Inspectors" toolbarItem.isBordered = true @@ -115,30 +142,9 @@ extension CodeEditWindowController { return toolbarItem case .stopTaskSidebarItem: - let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.stopTaskSidebarItem) - - guard let taskManager = workspace?.taskManager - else { return nil } - - let view = NSHostingView( - rootView: StopTaskToolbarButton(taskManager: taskManager) - ) - toolbarItem.view = view - - return toolbarItem + return stopTaskSidebarItem() case .startTaskSidebarItem: - let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.startTaskSidebarItem) - - guard let taskManager = workspace?.taskManager else { return nil } - guard let workspace = workspace else { return nil } - - let view = NSHostingView( - rootView: StartTaskToolbarButton(taskManager: taskManager) - .environmentObject(workspace) - ) - toolbarItem.view = view - - return toolbarItem + return startTaskSidebarItem() case .branchPicker: let toolbarItem = NSToolbarItem(itemIdentifier: .branchPicker) let view = NSHostingView( @@ -147,7 +153,7 @@ extension CodeEditWindowController { ) ) toolbarItem.view = view - + toolbarItem.isBordered = false return toolbarItem case .activityViewer: let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.activityViewer) @@ -187,8 +193,53 @@ extension CodeEditWindowController { ) toolbarItem.view = view return toolbarItem + case .taskSidebarItem: + guard #available(macOS 26, *) else { + fatalError("Unified task sidebar item used on pre-tahoe platform.") + } + guard let workspace, + let stop = StopTaskToolbarItem(workspace: workspace) else { + return nil + } + let start = StartTaskToolbarItem(workspace: workspace) + + let group = NSToolbarItemGroup(itemIdentifier: .taskSidebarItem) + group.isBordered = true + group.controlRepresentation = .expanded + group.selectionMode = .momentary + group.subitems = [stop, start] + + return group default: return NSToolbarItem(itemIdentifier: itemIdentifier) } } + + private func stopTaskSidebarItem() -> NSToolbarItem? { + let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.stopTaskSidebarItem) + + guard let taskManager = workspace?.taskManager else { return nil } + + let view = NSHostingView( + rootView: StopTaskToolbarButton(taskManager: taskManager) + ) + toolbarItem.view = view + + return toolbarItem + } + + private func startTaskSidebarItem() -> NSToolbarItem? { + let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.startTaskSidebarItem) + + guard let taskManager = workspace?.taskManager else { return nil } + guard let workspace = workspace else { return nil } + + let view = NSHostingView( + rootView: StartTaskToolbarButton(taskManager: taskManager) + .environmentObject(workspace) + ) + toolbarItem.view = view + + return toolbarItem + } } diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowControllerExtensions.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowControllerExtensions.swift index baade6dfdf..d8cb37450c 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowControllerExtensions.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowControllerExtensions.swift @@ -121,4 +121,6 @@ extension NSToolbarItem.Identifier { static let branchPicker: NSToolbarItem.Identifier = NSToolbarItem.Identifier("BranchPicker") static let activityViewer: NSToolbarItem.Identifier = NSToolbarItem.Identifier("ActivityViewer") static let notificationItem = NSToolbarItem.Identifier("notificationItem") + + static let taskSidebarItem: NSToolbarItem.Identifier = NSToolbarItem.Identifier("TaskSidebarItem") } diff --git a/CodeEdit/Features/Tasks/ToolbarItems/StartTaskToolbarItem.swift b/CodeEdit/Features/Tasks/ToolbarItems/StartTaskToolbarItem.swift new file mode 100644 index 0000000000..2d2b5d6e1b --- /dev/null +++ b/CodeEdit/Features/Tasks/ToolbarItems/StartTaskToolbarItem.swift @@ -0,0 +1,44 @@ +// +// StartTaskToolbarItem.swift +// CodeEdit +// +// Created by Khan Winter on 8/28/25. +// + +import AppKit + +@available(macOS 26, *) +final class StartTaskToolbarItem: NSToolbarItem { + private weak var workspace: WorkspaceDocument? + + private var utilityAreaCollapsed: Bool { + workspace?.utilityAreaModel?.isCollapsed ?? true + } + + init(workspace: WorkspaceDocument) { + self.workspace = workspace + super.init(itemIdentifier: NSToolbarItem.Identifier("StartTaskToolbarItem")) + + image = NSImage(systemSymbolName: "play.fill", accessibilityDescription: nil) + let config = NSImage.SymbolConfiguration(pointSize: 14, weight: .regular) + image = image?.withSymbolConfiguration(config) ?? image + + paletteLabel = "Start Task" + toolTip = "Run the selected task" + target = self + action = #selector(startTask) + isBordered = true + } + + @objc + func startTask() { + guard let taskManager = workspace?.taskManager else { return } + + taskManager.executeActiveTask() + if utilityAreaCollapsed { + CommandManager.shared.executeCommand("open.drawer") + } + workspace?.utilityAreaModel?.selectedTab = .debugConsole + taskManager.taskShowingOutput = taskManager.selectedTaskID + } +} diff --git a/CodeEdit/Features/Tasks/ToolbarItems/StopTaskToolbarItem.swift b/CodeEdit/Features/Tasks/ToolbarItems/StopTaskToolbarItem.swift new file mode 100644 index 0000000000..eaa5148439 --- /dev/null +++ b/CodeEdit/Features/Tasks/ToolbarItems/StopTaskToolbarItem.swift @@ -0,0 +1,81 @@ +// +// StopTaskToolbarItem.swift +// CodeEdit +// +// Created by Khan Winter on 8/28/25. +// + +import AppKit +import Combine + +@available(macOS 26, *) +final class StopTaskToolbarItem: NSToolbarItem { + private weak var workspace: WorkspaceDocument? + + private var taskManager: TaskManager? { + workspace?.taskManager + } + + /// The listener that listens to the active task's status publisher. Is updated frequently as the active task + /// changes. + private var statusListener: AnyCancellable? + private var otherListeners: Set = [] + + init?(workspace: WorkspaceDocument) { + guard let taskManager = workspace.taskManager else { return nil } + + self.workspace = workspace + super.init(itemIdentifier: NSToolbarItem.Identifier("StopTaskToolbarItem")) + + image = NSImage(systemSymbolName: "stop.fill", accessibilityDescription: nil) + let config = NSImage.SymbolConfiguration(pointSize: 14, weight: .regular) + image = image?.withSymbolConfiguration(config) ?? image + + paletteLabel = "Stop Task" + toolTip = "Stop the selected task" + target = self + isEnabled = false + isBordered = true + + taskManager.$selectedTaskID.sink { [weak self] selectedId in + self?.updateStatusListener(activeTasks: taskManager.activeTasks, selectedId: selectedId) + } + .store(in: &otherListeners) + + taskManager.$activeTasks.sink { [weak self] activeTasks in + self?.updateStatusListener(activeTasks: activeTasks, selectedId: taskManager.selectedTaskID) + } + .store(in: &otherListeners) + + updateStatusListener(activeTasks: taskManager.activeTasks, selectedId: taskManager.selectedTaskID) + } + + /// Update the ``statusListener`` to listen to a potentially new active task. + private func updateStatusListener(activeTasks: [UUID: CEActiveTask], selectedId: UUID?) { + statusListener?.cancel() + + if let status = activeTasks[selectedId ?? UUID()]?.status { + updateForNewStatus(status) + } + + guard let id = selectedId else { return } + statusListener = activeTasks[id]?.$status.sink { [weak self] status in + self?.updateForNewStatus(status) + } + } + + private func updateForNewStatus(_ status: CETaskStatus) { + isEnabled = status == .running + action = isEnabled ? #selector(stopTask) : nil + } + + @objc + func stopTask() { + taskManager?.terminateActiveTask() + } + + deinit { + statusListener?.cancel() + otherListeners.removeAll() + } +} diff --git a/CodeEdit/Features/Tasks/Views/StartTaskToolbarButton.swift b/CodeEdit/Features/Tasks/Views/StartTaskToolbarButton.swift index 4ab7174746..01bbb97498 100644 --- a/CodeEdit/Features/Tasks/Views/StartTaskToolbarButton.swift +++ b/CodeEdit/Features/Tasks/Views/StartTaskToolbarButton.swift @@ -11,13 +11,11 @@ struct StartTaskToolbarButton: View { @Environment(\.controlActiveState) private var activeState - @UpdatingWindowController var windowController: CodeEditWindowController? - @ObservedObject var taskManager: TaskManager @EnvironmentObject var workspace: WorkspaceDocument var utilityAreaCollapsed: Bool { - windowController?.workspace?.utilityAreaModel?.isCollapsed ?? true + workspace.utilityAreaModel?.isCollapsed ?? true } var body: some View { From f39c4976529fb563f7fb7837a08f5e5f96148aeb Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:22:17 -0500 Subject: [PATCH 04/15] Fix Warning --- .../Pages/TextEditingSettings/Models/NSFont+WithWeight.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/NSFont+WithWeight.swift b/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/NSFont+WithWeight.swift index 561ea4f712..e3b7871f1b 100644 --- a/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/NSFont+WithWeight.swift +++ b/CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/NSFont+WithWeight.swift @@ -44,7 +44,7 @@ extension NSFont { } } -extension NSFont.Weight: Codable { +extension NSFont.Weight: @retroactive Codable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(self.rawValue) From 7e50ff943a2c777f05909095ad540c1e82cf0dce Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:22:32 -0500 Subject: [PATCH 05/15] Adjust Branch Picker and Scheme Dropdown --- .../ActivityViewer/ActivityViewer.swift | 44 +++++---- .../Tasks/SchemeDropDownView.swift | 91 +++++++++++++------ .../Views/ToolbarBranchPicker.swift | 3 + CodeEdit/Utils/Extensions/View/View+if.swift | 34 +++++++ 4 files changed, 130 insertions(+), 42 deletions(-) create mode 100644 CodeEdit/Utils/Extensions/View/View+if.swift diff --git a/CodeEdit/Features/ActivityViewer/ActivityViewer.swift b/CodeEdit/Features/ActivityViewer/ActivityViewer.swift index 5b3e410691..ff226a6f18 100644 --- a/CodeEdit/Features/ActivityViewer/ActivityViewer.swift +++ b/CodeEdit/Features/ActivityViewer/ActivityViewer.swift @@ -32,6 +32,34 @@ struct ActivityViewer: View { self.taskManager = taskManager } var body: some View { + Group { + if #available(macOS 26, *) { + content + .fixedSize(horizontal: false, vertical: false) + .padding(.horizontal, 4) + } else { + content + .fixedSize(horizontal: false, vertical: false) + .padding(.horizontal, 5) + .padding(.vertical, 1.5) + .frame(height: 22) + .clipped() + .background { + if colorScheme == .dark { + RoundedRectangle(cornerRadius: 5) + .opacity(0.1) + } else { + RoundedRectangle(cornerRadius: 5) + .opacity(0.1) + } + } + } + } + .accessibilityElement(children: .contain) + .accessibilityLabel("Activity Viewer") + } + + @ViewBuilder private var content: some View { HStack(spacing: 0) { SchemeDropDownView( workspaceSettingsManager: workspaceSettingsManager, @@ -45,21 +73,5 @@ struct ActivityViewer: View { TaskNotificationView(taskNotificationHandler: taskNotificationHandler) .fixedSize() } - .fixedSize(horizontal: false, vertical: false) - .padding(.horizontal, 5) - .padding(.vertical, 1.5) - .frame(height: 22) - .clipped() - .background { - if colorScheme == .dark { - RoundedRectangle(cornerRadius: 5) - .opacity(0.1) - } else { - RoundedRectangle(cornerRadius: 5) - .opacity(0.1) - } - } - .accessibilityElement(children: .contain) - .accessibilityLabel("Activity Viewer") } } diff --git a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift index c25a985d44..16649b7444 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift @@ -32,30 +32,11 @@ struct SchemeDropDownView: View { } var body: some View { - HStack(spacing: 6) { - Image(systemName: "folder.badge.gearshape") - .imageScale(.medium) - Text(workspaceDisplayName) - .frame(minWidth: 0) - } - .opacity(activeState == .inactive ? 0.4 : 1.0) - .font(.subheadline) - .padding(.trailing, 11.5) - .padding(.horizontal, 2.5) - .padding(.vertical, 2.5) - .background { - Color(nsColor: colorScheme == .dark ? .white : .black) - .opacity(isHoveringScheme || isSchemePopOverPresented ? 0.05 : 0) - .clipShape(RoundedRectangle(cornerSize: CGSize(width: 4, height: 4))) - HStack { - Spacer() - if isHoveringScheme || isSchemePopOverPresented { - chevronDown - .padding(.trailing, 2) - } else { - chevron - .padding(.trailing, 4) - } + Group { + if #available(macOS 26, *) { + tahoe + } else { + seqouia } } .onHover(perform: { hovering in @@ -78,7 +59,65 @@ struct SchemeDropDownView: View { } } - private var chevron: some View { + @available(macOS 26, *) + @ViewBuilder private var tahoe: some View { + HStack(spacing: 4) { + label + chevron + .padding(.leading, 1) + .opacity(isHoveringScheme || isSchemePopOverPresented ? 0.0 : 1.0) + } + .background { + if isHoveringScheme || isSchemePopOverPresented { + HStack { + Spacer() + chevronDown + } + } + } + .padding(6) + .padding(.leading, 2) // apparently this is cummulative? + .background { + Color(nsColor: colorScheme == .dark ? .white : .black) + .opacity(isHoveringScheme || isSchemePopOverPresented ? 0.05 : 0) + .clipShape(Capsule(style: .continuous)) + } + } + + @ViewBuilder private var seqouia: some View { + label + .padding(.trailing, 11.5) + .padding(.horizontal, 2.5) + .padding(.vertical, 2.5) + .background { + Color(nsColor: colorScheme == .dark ? .white : .black) + .opacity(isHoveringScheme || isSchemePopOverPresented ? 0.05 : 0) + .clipShape(RoundedRectangle(cornerSize: CGSize(width: 4, height: 4))) + HStack { + Spacer() + if isHoveringScheme || isSchemePopOverPresented { + chevronDown + .padding(.trailing, 2) + } else { + chevron + .padding(.trailing, 4) + } + } + } + } + + @ViewBuilder private var label: some View { + HStack(spacing: 6) { + Image(systemName: "folder.badge.gearshape") + .imageScale(.medium) + Text(workspaceDisplayName) + .frame(minWidth: 0) + } + .opacity(activeState == .inactive ? 0.4 : 1.0) + .font(.subheadline) + } + + @ViewBuilder private var chevron: some View { Image(systemName: "chevron.compact.right") .font(.system(size: 9, weight: .medium, design: .default)) .foregroundStyle(.secondary) @@ -86,7 +125,7 @@ struct SchemeDropDownView: View { .imageScale(.large) } - private var chevronDown: some View { + @ViewBuilder private var chevronDown: some View { VStack(spacing: 1) { Image(systemName: "chevron.down") } diff --git a/CodeEdit/Features/CodeEditUI/Views/ToolbarBranchPicker.swift b/CodeEdit/Features/CodeEditUI/Views/ToolbarBranchPicker.swift index b199e7b204..7993da1802 100644 --- a/CodeEdit/Features/CodeEditUI/Views/ToolbarBranchPicker.swift +++ b/CodeEdit/Features/CodeEditUI/Views/ToolbarBranchPicker.swift @@ -89,6 +89,9 @@ struct ToolbarBranchPicker: View { await self.sourceControlManager?.refreshBranches() } } + .if(.tahoe) { + $0.padding(.leading, 10).frame(minWidth: 140) + } } private var inactiveColor: Color { diff --git a/CodeEdit/Utils/Extensions/View/View+if.swift b/CodeEdit/Utils/Extensions/View/View+if.swift new file mode 100644 index 0000000000..3b262a2fc2 --- /dev/null +++ b/CodeEdit/Utils/Extensions/View/View+if.swift @@ -0,0 +1,34 @@ +// +// View+if.swift +// CodeEdit +// +// Created by Khan Winter on 8/28/25. +// + +import SwiftUI + +extension View { + /// Applies the given transform if the given condition evaluates to `true`. + /// - Parameters: + /// - condition: The condition to evaluate. + /// - transform: The transform to apply to the source `View`. + /// - Returns: Either the original `View` or the modified `View` if the condition is `true`. + @ViewBuilder + func `if`(_ condition: Bool, transform: (Self) -> Content) -> some View { + if condition { + transform(self) + } else { + self + } + } +} + +extension Bool { + static var tahoe: Bool { + if #available(macOS 26, *) { + return true + } else { + return false + } + } + } From 45aa64c8b2db8061711a09b401246136d881508e Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 11:32:43 -0500 Subject: [PATCH 06/15] Finish Activity Viewer Pills --- .../Tasks/SchemeDropDownView.swift | 2 +- .../Tasks/TaskDropDownView.swift | 67 +++++++++++++------ 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift index 16649b7444..0633b1dc9a 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift @@ -64,7 +64,7 @@ struct SchemeDropDownView: View { HStack(spacing: 4) { label chevron - .padding(.leading, 1) + .offset(x: 2) .opacity(isHoveringScheme || isSchemePopOverPresented ? 0.0 : 1.0) } .background { diff --git a/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift index dc897d2687..37801d1c7f 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift @@ -21,25 +21,12 @@ struct TaskDropDownView: View { var body: some View { Group { - if let selectedTask = taskManager.selectedTask { - if let selectedActiveTask = taskManager.activeTasks[selectedTask.id] { - ActiveTaskView(activeTask: selectedActiveTask) - .fixedSize() - } else { - TaskView(task: selectedTask, status: CETaskStatus.notRunning) - .fixedSize() - } + if #available(macOS 26, *) { + tahoe } else { - Text("Create Tasks") - .frame(minWidth: 0) + seqouia } } - .opacity(activeState == .inactive ? 0.4 : 1.0) - .font(.subheadline) - .padding(.trailing, 11.5) - .padding(.horizontal, 2.5) - .padding(.vertical, 2.5) - .background(backgroundColor) .onHover { hovering in self.isHoveringTasks = hovering } @@ -60,7 +47,49 @@ struct TaskDropDownView: View { } } - private var backgroundColor: some View { + @available(macOS 26, *) + @ViewBuilder private var tahoe: some View { + HStack(spacing: 4) { + label + chevronIcon + .opacity(isHoveringTasks || isTaskPopOverPresented ? 1.0 : 0.0) + } + .padding(6) + .background { + Color(nsColor: colorScheme == .dark ? .white : .black) + .opacity(isHoveringTasks || isTaskPopOverPresented ? 0.05 : 0) + .clipShape(Capsule(style: .continuous)) + } + } + + @ViewBuilder private var seqouia: some View { + label + .opacity(activeState == .inactive ? 0.4 : 1.0) + .padding(.trailing, 11.5) + .padding(.horizontal, 2.5) + .padding(.vertical, 2.5) + .background(backgroundColor) + } + + @ViewBuilder private var label: some View { + Group { + if let selectedTask = taskManager.selectedTask { + if let selectedActiveTask = taskManager.activeTasks[selectedTask.id] { + ActiveTaskView(activeTask: selectedActiveTask) + .fixedSize() + } else { + TaskView(task: selectedTask, status: CETaskStatus.notRunning) + .fixedSize() + } + } else { + Text("Create Tasks") + .frame(minWidth: 0) + } + } + .font(.subheadline) + } + + @ViewBuilder private var backgroundColor: some View { Color(nsColor: colorScheme == .dark ? .white : .black) .opacity(isHoveringTasks || isTaskPopOverPresented ? 0.05 : 0) .clipShape(RoundedRectangle(cornerSize: CGSize(width: 4, height: 4))) @@ -74,14 +103,14 @@ struct TaskDropDownView: View { ) } - private var chevronIcon: some View { + @ViewBuilder private var chevronIcon: some View { Image(systemName: "chevron.down") .font(.system(size: 8, weight: .bold, design: .default)) .padding(.top, 0.5) .padding(.trailing, 2) } - private var taskPopoverContent: some View { + @ViewBuilder private var taskPopoverContent: some View { VStack(alignment: .leading, spacing: 0) { if !taskManager.availableTasks.isEmpty { ForEach(taskManager.availableTasks, id: \.id) { task in From bc152a080d07e79603e9914fae05b47f6f2569aa Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 11:37:46 -0500 Subject: [PATCH 07/15] Use new WelcomeWindow Release --- CodeEdit.xcodeproj/project.pbxproj | 25 +++++++++++++------ .../xcshareddata/swiftpm/Package.resolved | 11 +++++++- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 76a598e48f..7b6eb5c3fe 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 6C81916B29B41DD300B75C92 /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = 6C81916A29B41DD300B75C92 /* DequeModule */; }; 6C85BB402C2105ED00EB5DEF /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C85BB3F2C2105ED00EB5DEF /* CodeEditKit */; }; 6C85BB442C210EFD00EB5DEF /* SwiftUIIntrospect in Frameworks */ = {isa = PBXBuildFile; productRef = 6C85BB432C210EFD00EB5DEF /* SwiftUIIntrospect */; }; + 6C883FD42E620E2B005BCFE8 /* WelcomeWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 6C883FD32E620E2B005BCFE8 /* WelcomeWindow */; }; 6C9DB9E42D55656300ACD86E /* CodeEditSourceEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 6C9DB9E32D55656300ACD86E /* CodeEditSourceEditor */; }; 6CAAF68A29BC9C2300A1F48A /* (null) in Sources */ = {isa = PBXBuildFile; }; 6CAAF69229BCC71C00A1F48A /* (null) in Sources */ = {isa = PBXBuildFile; }; @@ -171,6 +172,7 @@ buildActionMask = 2147483647; files = ( 302AD7FF2D8054D500231E16 /* ZIPFoundation in Frameworks */, + 6C883FD42E620E2B005BCFE8 /* WelcomeWindow in Frameworks */, 6C85BB402C2105ED00EB5DEF /* CodeEditKit in Frameworks */, 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */, 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */, @@ -337,6 +339,7 @@ 6CCF6DD22E26D48F00B94F75 /* SwiftTerm */, 6CCF73CF2E26DE3200B94F75 /* SwiftTerm */, 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */, + 6C883FD32E620E2B005BCFE8 /* WelcomeWindow */, ); productName = CodeEdit; productReference = B658FB2C27DA9E0F00EA4DBD /* CodeEdit.app */; @@ -442,7 +445,7 @@ 5E44855F2DF600D9008BBE69 /* XCRemoteSwiftPackageReference "AboutWindow" */, 6C76D6D22E15B91E00EF52C3 /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */, 6CCF73CE2E26DE3200B94F75 /* XCRemoteSwiftPackageReference "SwiftTerm" */, - 6C33D9F92E5F9184007782E7 /* XCLocalSwiftPackageReference "../WelcomeWindow" */, + 6C883FD22E620E2A005BCFE8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */, ); preferredProjectObjectVersion = 55; productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */; @@ -1674,13 +1677,6 @@ }; /* End XCConfigurationList section */ -/* Begin XCLocalSwiftPackageReference section */ - 6C33D9F92E5F9184007782E7 /* XCLocalSwiftPackageReference "../WelcomeWindow" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = ../WelcomeWindow; - }; -/* End XCLocalSwiftPackageReference section */ - /* Begin XCRemoteSwiftPackageReference section */ 2816F592280CF50500DD548B /* XCRemoteSwiftPackageReference "CodeEditSymbols" */ = { isa = XCRemoteSwiftPackageReference; @@ -1826,6 +1822,14 @@ minimumVersion = 1.2.0; }; }; + 6C883FD22E620E2A005BCFE8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/CodeEditApp/WelcomeWindow"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; 6C9DB9E22D55656300ACD86E /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/CodeEditApp/CodeEditSourceEditor"; @@ -1953,6 +1957,11 @@ package = 6C85BB422C210EFD00EB5DEF /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; productName = SwiftUIIntrospect; }; + 6C883FD32E620E2B005BCFE8 /* WelcomeWindow */ = { + isa = XCSwiftPackageProductDependency; + package = 6C883FD22E620E2A005BCFE8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */; + productName = WelcomeWindow; + }; 6C9DB9E32D55656300ACD86E /* CodeEditSourceEditor */ = { isa = XCSwiftPackageProductDependency; package = 6C9DB9E22D55656300ACD86E /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */; diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5e6529adf7..d340ac124a 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "658d82cd25b5cc6cfb47311fe2463f0a4d7e5cfaa82200a1fe9f7e4b2f10e1ef", + "originHash" : "f457e734c292c01026823cb77c71fe712b1475f93229e48d3c14554bd650f9cd", "pins" : [ { "identity" : "aboutwindow", @@ -289,6 +289,15 @@ "version" : "0.25.6" } }, + { + "identity" : "welcomewindow", + "kind" : "remoteSourceControl", + "location" : "https://github.com/CodeEditApp/WelcomeWindow", + "state" : { + "revision" : "cbd5c0d6f432449e2a8618e2b24e4691acbfcc98", + "version" : "1.1.0" + } + }, { "identity" : "zipfoundation", "kind" : "remoteSourceControl", From c7c30af901c9327f3263f71baa0ce7ec5be0c9fa Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 11:58:05 -0500 Subject: [PATCH 08/15] Update Popover Style --- .../Tasks/DropdownMenuItemStyleModifier.swift | 16 ++++++++ .../Tasks/OptionMenuItemView.swift | 6 +-- .../Tasks/SchemeDropDownView.swift | 37 ++++++++----------- .../Tasks/TaskDropDownView.swift | 29 ++++++--------- .../Tasks/TasksPopoverMenuItem.swift | 5 +-- .../Tasks/WorkspaceMenuItemView.swift | 4 +- .../Views/InstantPopoverModifier.swift | 4 +- .../CodeEditUI/Views/PopoverContainer.swift | 31 ++++++++++++++++ CodeEdit/Utils/Extensions/View/View+if.swift | 20 +++++++++- 9 files changed, 100 insertions(+), 52 deletions(-) create mode 100644 CodeEdit/Features/CodeEditUI/Views/PopoverContainer.swift diff --git a/CodeEdit/Features/ActivityViewer/Tasks/DropdownMenuItemStyleModifier.swift b/CodeEdit/Features/ActivityViewer/Tasks/DropdownMenuItemStyleModifier.swift index 859a7ade29..89226ae038 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/DropdownMenuItemStyleModifier.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/DropdownMenuItemStyleModifier.swift @@ -7,17 +7,33 @@ import SwiftUI +extension View { + @ViewBuilder + func dropdownItemStyle() -> some View { + self.modifier(DropdownMenuItemStyleModifier()) + } +} + struct DropdownMenuItemStyleModifier: ViewModifier { @State private var isHovering = false func body(content: Content) -> some View { content + .padding(.vertical, 4) + .padding(.horizontal, 8) .background( isHovering ? AnyView(EffectView(.selection, blendingMode: .withinWindow, emphasized: true)) : AnyView(Color.clear) ) .foregroundColor(isHovering ? Color(NSColor.white) : .primary) + .if(.tahoe) { + if #available(macOS 26, *) { + $0.clipShape(ContainerRelativeShape()) + } + } else: { + $0.clipShape(RoundedRectangle(cornerRadius: 5)) + } .onHover(perform: { hovering in self.isHovering = hovering }) diff --git a/CodeEdit/Features/ActivityViewer/Tasks/OptionMenuItemView.swift b/CodeEdit/Features/ActivityViewer/Tasks/OptionMenuItemView.swift index 49a78560ef..eaa487bfc5 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/OptionMenuItemView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/OptionMenuItemView.swift @@ -16,10 +16,8 @@ struct OptionMenuItemView: View { Text(label) Spacer() } - .padding(.vertical, 4) - .padding(.horizontal, 28) - .modifier(DropdownMenuItemStyleModifier()) - .clipShape(RoundedRectangle(cornerRadius: 5)) + .padding(.horizontal, 20) + .dropdownItemStyle() .onTapGesture { action() } diff --git a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift index 0633b1dc9a..4cd02f5c95 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift @@ -134,29 +134,24 @@ struct SchemeDropDownView: View { } @ViewBuilder var popoverContent: some View { - VStack(alignment: .leading, spacing: 0) { - WorkspaceMenuItemView( - workspaceFileManager: workspaceFileManager, - item: workspaceFileManager?.workspaceItem - ) - Divider() - .padding(.vertical, 5) - Group { - OptionMenuItemView(label: "Add Folder...") { - // TODO: Implment Add Folder - print("NOT IMPLEMENTED") - } - .disabled(true) - OptionMenuItemView(label: "Workspace Settings...") { - NSApp.sendAction( - #selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil - ) - } + WorkspaceMenuItemView( + workspaceFileManager: workspaceFileManager, + item: workspaceFileManager?.workspaceItem + ) + Divider() + .padding(.vertical, 5) + Group { + OptionMenuItemView(label: "Add Folder...") { + // TODO: Implment Add Folder + print("NOT IMPLEMENTED") + } + .disabled(true) + OptionMenuItemView(label: "Workspace Settings...") { + NSApp.sendAction( + #selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil + ) } } - .font(.subheadline) - .padding(5) - .frame(minWidth: 215) } } diff --git a/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift index 37801d1c7f..9ddca9aa3b 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift @@ -111,25 +111,20 @@ struct TaskDropDownView: View { } @ViewBuilder private var taskPopoverContent: some View { - VStack(alignment: .leading, spacing: 0) { - if !taskManager.availableTasks.isEmpty { - ForEach(taskManager.availableTasks, id: \.id) { task in - TasksPopoverMenuItem(taskManager: taskManager, task: task) { - isTaskPopOverPresented = false - } + if !taskManager.availableTasks.isEmpty { + ForEach(taskManager.availableTasks, id: \.id) { task in + TasksPopoverMenuItem(taskManager: taskManager, task: task) { + isTaskPopOverPresented = false } - Divider() - .padding(.vertical, 5) - } - OptionMenuItemView(label: "Add Task...") { - NSApp.sendAction(#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil) - } - OptionMenuItemView(label: "Manage Tasks...") { - NSApp.sendAction(#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil) } + Divider() + .padding(.vertical, 5) + } + OptionMenuItemView(label: "Add Task...") { + NSApp.sendAction(#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil) + } + OptionMenuItemView(label: "Manage Tasks...") { + NSApp.sendAction(#selector(CodeEditWindowController.openWorkspaceSettings(_:)), to: nil, from: nil) } - .font(.subheadline) - .padding(5) - .frame(minWidth: 215) } } diff --git a/CodeEdit/Features/ActivityViewer/Tasks/TasksPopoverMenuItem.swift b/CodeEdit/Features/ActivityViewer/Tasks/TasksPopoverMenuItem.swift index 2205660b3c..528e0c96b5 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/TasksPopoverMenuItem.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/TasksPopoverMenuItem.swift @@ -20,11 +20,8 @@ struct TasksPopoverMenuItem: View { selectionIndicator popoverContent } - .padding(.vertical, 4) - .padding(.horizontal, 8) - .modifier(DropdownMenuItemStyleModifier()) + .dropdownItemStyle() .onTapGesture(perform: selectAction) - .clipShape(RoundedRectangle(cornerRadius: 5)) .accessibilityElement() .accessibilityLabel(task.name) .accessibilityAction(.default, selectAction) diff --git a/CodeEdit/Features/ActivityViewer/Tasks/WorkspaceMenuItemView.swift b/CodeEdit/Features/ActivityViewer/Tasks/WorkspaceMenuItemView.swift index 6eaa8f262e..9c12b49342 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/WorkspaceMenuItemView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/WorkspaceMenuItemView.swift @@ -27,9 +27,7 @@ struct WorkspaceMenuItemView: View { Text(item?.name ?? "") Spacer() } - .padding(.vertical, 4) - .padding(.horizontal, 8) - .modifier(DropdownMenuItemStyleModifier()) + .dropdownItemStyle() .onTapGesture { } // add accessibility action when this is filled in .clipShape(RoundedRectangle(cornerRadius: 5)) .accessibilityElement() diff --git a/CodeEdit/Features/CodeEditUI/Views/InstantPopoverModifier.swift b/CodeEdit/Features/CodeEditUI/Views/InstantPopoverModifier.swift index c1978b1396..037f7a701d 100644 --- a/CodeEdit/Features/CodeEditUI/Views/InstantPopoverModifier.swift +++ b/CodeEdit/Features/CodeEditUI/Views/InstantPopoverModifier.swift @@ -126,13 +126,13 @@ extension View { func instantPopover( isPresented: Binding, arrowEdge: Edge = .bottom, - @ViewBuilder content: () -> Content + @ViewBuilder content: @escaping () -> Content ) -> some View { self.modifier( InstantPopoverModifier( isPresented: isPresented, arrowEdge: arrowEdge, - popoverContent: content() + popoverContent: PopoverContainer(content: content) ) ) } diff --git a/CodeEdit/Features/CodeEditUI/Views/PopoverContainer.swift b/CodeEdit/Features/CodeEditUI/Views/PopoverContainer.swift new file mode 100644 index 0000000000..7d62b94f56 --- /dev/null +++ b/CodeEdit/Features/CodeEditUI/Views/PopoverContainer.swift @@ -0,0 +1,31 @@ +// +// PopoverContainer.swift +// CodeEdit +// +// Created by Khan Winter on 8/29/25. +// + +import SwiftUI + +/// Container for SwiftUI views presented in a popover. +/// On tahoe and above, adds the correct container shape. +struct PopoverContainer: View { + let content: () -> ContentView + + init(@ViewBuilder content: @escaping () -> ContentView) { + self.content = content + } + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + content() + } + .font(.subheadline) + .if(.tahoe) { + $0.padding(13).containerShape(RoundedRectangle(cornerRadius: 20, style: .continuous)) + } else: { + $0.padding(5) + } + .frame(minWidth: 215) + } +} diff --git a/CodeEdit/Utils/Extensions/View/View+if.swift b/CodeEdit/Utils/Extensions/View/View+if.swift index 3b262a2fc2..1275187510 100644 --- a/CodeEdit/Utils/Extensions/View/View+if.swift +++ b/CodeEdit/Utils/Extensions/View/View+if.swift @@ -14,13 +14,31 @@ extension View { /// - transform: The transform to apply to the source `View`. /// - Returns: Either the original `View` or the modified `View` if the condition is `true`. @ViewBuilder - func `if`(_ condition: Bool, transform: (Self) -> Content) -> some View { + func `if`(_ condition: Bool, @ViewBuilder transform: (Self) -> Content) -> some View { if condition { transform(self) } else { self } } + + /// Applies the given transform if the given condition evaluates to `true`. + /// - Parameters: + /// - condition: The condition to evaluate. + /// - transform: The transform to apply to the source `View`. + /// - Returns: Either the original `View` or the modified `View` if the condition is `true`. + @ViewBuilder + func `if`( + _ condition: Bool, + @ViewBuilder transform: (Self) -> Content, + @ViewBuilder else elseTransform: (Self) -> ElseContent + ) -> some View { + if condition { + transform(self) + } else { + elseTransform(self) + } + } } extension Bool { From 22b5b93d6775a482c16686814f9b9c2de1d00d2e Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 12:38:53 -0500 Subject: [PATCH 09/15] Adjust Task Notification View --- .../ActivityViewer/ActivityViewer.swift | 6 ++ .../Notifications/TaskNotificationView.swift | 90 ++++++++++--------- .../Tasks/SchemeDropDownView.swift | 2 +- .../Tasks/TaskDropDownView.swift | 2 +- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/CodeEdit/Features/ActivityViewer/ActivityViewer.swift b/CodeEdit/Features/ActivityViewer/ActivityViewer.swift index ff226a6f18..82e4356526 100644 --- a/CodeEdit/Features/ActivityViewer/ActivityViewer.swift +++ b/CodeEdit/Features/ActivityViewer/ActivityViewer.swift @@ -37,6 +37,12 @@ struct ActivityViewer: View { content .fixedSize(horizontal: false, vertical: false) .padding(.horizontal, 4) + // TaskNotificationView doesn't have it's own padding + // Also this padding seems weird. However, we want the spinning circle to be padded with the same + // amount from both the top and bottom, as well as the trailing edge. So despite it not being exactly + // the same it *looks* correctly padded + .padding(.trailing, 8) + .clipShape(Capsule()) } else { content .fixedSize(horizontal: false, vertical: false) diff --git a/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift b/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift index 1b9c1d0a34..bb8c8c1345 100644 --- a/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift +++ b/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift @@ -17,48 +17,35 @@ struct TaskNotificationView: View { var body: some View { ZStack { - if let notification { - HStack { - Text(notification.title) - .font(.subheadline) - .transition( - .asymmetric(insertion: .move(edge: .top), removal: .move(edge: .bottom)) - .combined(with: .opacity) - ) - .id("NotificationTitle" + notification.title) - - if notification.isLoading { - CECircularProgressView( - progress: notification.percentage, - currentTaskCount: taskNotificationHandler.notifications.count - ) - .padding(.horizontal, -1) - .frame(height: 16) - } else { - if taskNotificationHandler.notifications.count > 1 { - Text("\(taskNotificationHandler.notifications.count)") - .font(.caption) - .padding(5) - .background( - Circle() - .foregroundStyle(.gray) - .opacity(0.2) - ) - .padding(-5) - } + HStack { + if let notification { + HStack { + Text(notification.title) + .font(.subheadline) + .transition( + .asymmetric(insertion: .move(edge: .top), removal: .move(edge: .bottom)) + .combined(with: .opacity) + ) + .id("NotificationTitle" + notification.title) } + .transition(.opacity.combined(with: .move(edge: .trailing))) + + loaderView(notification: notification) + .transition(.opacity) + .id("Loader") + } else { + Text("") + .id("Loader") } - .transition(.opacity.combined(with: .move(edge: .trailing))) - .opacity(activeState == .inactive ? 0.4 : 1.0) - .padding(3) - .padding(-3) - .padding(.trailing, 3) - .popover(isPresented: $isPresented, arrowEdge: .bottom) { - TaskNotificationsDetailView(taskNotificationHandler: taskNotificationHandler) - } - .onTapGesture { - self.isPresented.toggle() - } + } + .opacity(activeState == .inactive ? 0.4 : 1.0) + .padding(3) + .padding(-3) + .popover(isPresented: $isPresented, arrowEdge: .bottom) { + TaskNotificationsDetailView(taskNotificationHandler: taskNotificationHandler) + } + .onTapGesture { + self.isPresented.toggle() } } .animation(.easeInOut, value: notification) @@ -69,6 +56,29 @@ struct TaskNotificationView: View { } } + @ViewBuilder + private func loaderView(notification: TaskNotificationModel) -> some View { + if notification.isLoading { + CECircularProgressView( + progress: notification.percentage, + currentTaskCount: taskNotificationHandler.notifications.count + ) + .padding(.horizontal, -1) + .frame(height: 16) + } else { + if taskNotificationHandler.notifications.count > 1 { + Text("\(taskNotificationHandler.notifications.count)") + .font(.caption) + .padding(5) + .background( + Circle() + .foregroundStyle(.gray) + .opacity(0.2) + ) + .padding(-5) + } + } + } } #Preview { diff --git a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift index 4cd02f5c95..dbf9a0688e 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift @@ -80,7 +80,7 @@ struct SchemeDropDownView: View { .background { Color(nsColor: colorScheme == .dark ? .white : .black) .opacity(isHoveringScheme || isSchemePopOverPresented ? 0.05 : 0) - .clipShape(Capsule(style: .continuous)) + .clipShape(Capsule()) } } diff --git a/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift index 9ddca9aa3b..6ce8699311 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/TaskDropDownView.swift @@ -58,7 +58,7 @@ struct TaskDropDownView: View { .background { Color(nsColor: colorScheme == .dark ? .white : .black) .opacity(isHoveringTasks || isTaskPopOverPresented ? 0.05 : 0) - .clipShape(Capsule(style: .continuous)) + .clipShape(Capsule()) } } From 940857772ce3b655fd026254d6f6a68e8cba5e8f Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:36:26 -0500 Subject: [PATCH 10/15] Remove Unified Style (and fix the rabbit hole of bugs that caused) --- .../ActivityViewer/ActivityViewer.swift | 5 +- .../Notifications/TaskNotificationView.swift | 6 +- .../CodeEditSplitViewController.swift | 2 + .../CodeEditWindowController+Toolbar.swift | 107 +++++++++++------- .../WorkspaceDocument/WorkspaceDocument.swift | 3 +- .../NotificationPanelViewModel.swift | 66 +++++++++-- .../Views/NotificationToolbarItem.swift | 4 +- 7 files changed, 132 insertions(+), 61 deletions(-) diff --git a/CodeEdit/Features/ActivityViewer/ActivityViewer.swift b/CodeEdit/Features/ActivityViewer/ActivityViewer.swift index 82e4356526..8cd5053932 100644 --- a/CodeEdit/Features/ActivityViewer/ActivityViewer.swift +++ b/CodeEdit/Features/ActivityViewer/ActivityViewer.swift @@ -36,13 +36,14 @@ struct ActivityViewer: View { if #available(macOS 26, *) { content .fixedSize(horizontal: false, vertical: false) - .padding(.horizontal, 4) + .padding(5) // TaskNotificationView doesn't have it's own padding // Also this padding seems weird. However, we want the spinning circle to be padded with the same // amount from both the top and bottom, as well as the trailing edge. So despite it not being exactly // the same it *looks* correctly padded - .padding(.trailing, 8) + .padding(.trailing, 5) .clipShape(Capsule()) + .frame(minWidth: 200) } else { content .fixedSize(horizontal: false, vertical: false) diff --git a/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift b/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift index bb8c8c1345..bc6a2be2bf 100644 --- a/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift +++ b/CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationView.swift @@ -63,7 +63,11 @@ struct TaskNotificationView: View { progress: notification.percentage, currentTaskCount: taskNotificationHandler.notifications.count ) - .padding(.horizontal, -1) + .if(.tahoe) { + $0.padding(.leading, 1) + } else: { + $0.padding(.horizontal, -1) + } .frame(height: 16) } else { if taskNotificationHandler.notifications.count > 1 { diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift index 27d2b4f4fc..39735c8de1 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditSplitViewController.swift @@ -135,6 +135,8 @@ final class CodeEditSplitViewController: NSSplitViewController { .inspectorCollapsed ) as? Bool ?? true } + + workspace.notificationPanel.updateToolbarItem() } // MARK: - NSSplitViewDelegate diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift index 7a8a5368ab..4b3383892c 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift @@ -13,13 +13,15 @@ extension CodeEditWindowController { internal func setupToolbar() { let toolbar = NSToolbar(identifier: UUID().uuidString) toolbar.delegate = self - toolbar.displayMode = .labelOnly toolbar.showsBaselineSeparator = false - self.window?.titleVisibility = toolbarCollapsed ? .visible : .hidden + self.window?.titleVisibility = toolbarCollapsed ? .visible : .hidden if #available(macOS 26, *) { - self.window?.toolbarStyle = .unified + self.window?.toolbarStyle = .automatic + toolbar.centeredItemIdentifiers = [.activityViewer, .notificationItem] + toolbar.displayMode = .iconOnly } else { self.window?.toolbarStyle = .unifiedCompact + toolbar.displayMode = .labelOnly } self.window?.titlebarSeparatorStyle = .automatic self.window?.toolbar = toolbar @@ -32,9 +34,7 @@ extension CodeEditWindowController { ] if #available(macOS 26, *) { - items += [ - .taskSidebarItem - ] + items += [.taskSidebarItem] } else { items += [ .stopTaskSidebarItem, @@ -46,8 +46,22 @@ extension CodeEditWindowController { .sidebarTrackingSeparator, .branchPicker, .flexibleSpace, - .activityViewer, - .notificationItem, + ] + + if #available(macOS 26, *) { + items += [ + .activityViewer, + .space, + .notificationItem, + ] + } else { + items += [ + .activityViewer, + .notificationItem, + ] + } + + items += [ .flexibleSpace, .itemListTrackingSeparator, .flexibleSpace, @@ -156,43 +170,9 @@ extension CodeEditWindowController { toolbarItem.isBordered = false return toolbarItem case .activityViewer: - let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.activityViewer) - toolbarItem.visibilityPriority = .user - guard let workspaceSettingsManager = workspace?.workspaceSettingsManager, - let taskNotificationHandler = workspace?.taskNotificationHandler, - let taskManager = workspace?.taskManager - else { return nil } - - let view = NSHostingView( - rootView: ActivityViewer( - workspaceFileManager: workspace?.workspaceFileManager, - workspaceSettingsManager: workspaceSettingsManager, - taskNotificationHandler: taskNotificationHandler, - taskManager: taskManager - ) - ) - - let weakWidth = view.widthAnchor.constraint(equalToConstant: 650) - weakWidth.priority = .defaultLow - let strongWidth = view.widthAnchor.constraint(greaterThanOrEqualToConstant: 200) - strongWidth.priority = .defaultHigh - - NSLayoutConstraint.activate([ - weakWidth, - strongWidth - ]) - - toolbarItem.view = view - return toolbarItem + return activityViewerItem() case .notificationItem: - let toolbarItem = NSToolbarItem(itemIdentifier: .notificationItem) - guard let workspace = workspace else { return nil } - let view = NSHostingView( - rootView: NotificationToolbarItem() - .environmentObject(workspace) - ) - toolbarItem.view = view - return toolbarItem + return notificationItem() case .taskSidebarItem: guard #available(macOS 26, *) else { fatalError("Unified task sidebar item used on pre-tahoe platform.") @@ -242,4 +222,43 @@ extension CodeEditWindowController { return toolbarItem } + + private func notificationItem() -> NSToolbarItem? { + let toolbarItem = NSToolbarItem(itemIdentifier: .notificationItem) + guard let workspace = workspace else { return nil } + let view = NSHostingView(rootView: NotificationToolbarItem().environmentObject(workspace)) + toolbarItem.view = view + return toolbarItem + } + + private func activityViewerItem() -> NSToolbarItem? { + let toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier.activityViewer) + toolbarItem.visibilityPriority = .user + guard let workspaceSettingsManager = workspace?.workspaceSettingsManager, + let taskNotificationHandler = workspace?.taskNotificationHandler, + let taskManager = workspace?.taskManager + else { return nil } + + let view = NSHostingView( + rootView: ActivityViewer( + workspaceFileManager: workspace?.workspaceFileManager, + workspaceSettingsManager: workspaceSettingsManager, + taskNotificationHandler: taskNotificationHandler, + taskManager: taskManager + ) + ) + + let weakWidth = view.widthAnchor.constraint(equalToConstant: 650) + weakWidth.priority = .defaultLow + let strongWidth = view.widthAnchor.constraint(greaterThanOrEqualToConstant: 200) + strongWidth.priority = .defaultHigh + + NSLayoutConstraint.activate([ + weakWidth, + strongWidth + ]) + + toolbarItem.view = view + return toolbarItem + } } diff --git a/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift index 9d20cb57d2..4671b57f4f 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift @@ -47,11 +47,12 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { var undoRegistration: UndoManagerRegistration = UndoManagerRegistration() - @Published var notificationPanel = NotificationPanelViewModel() + var notificationPanel = NotificationPanelViewModel() private var cancellables = Set() override init() { super.init() + notificationPanel.workspace = self // Observe changes to notification panel notificationPanel.objectWillChange diff --git a/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift b/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift index 9343856b92..dab6933ff7 100644 --- a/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift +++ b/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift @@ -30,6 +30,13 @@ final class NotificationPanelViewModel: ObservableObject { @Published var scrolledToTop: Bool = true + /// A filtered list of active notifications. + var visibleNotifications: [CENotification] { + activeNotifications.filter { !hiddenNotificationIds.contains($0.id) } + } + + weak var workspace: WorkspaceDocument? + /// Whether a notification should be visible in the panel func isNotificationVisible(_ notification: CENotification) -> Bool { if notification.isBeingDismissed { @@ -171,12 +178,20 @@ final class NotificationPanelViewModel: ObservableObject { /// Handles a new notification being added func handleNewNotification(_ notification: CENotification) { - withAnimation(.easeInOut(duration: 0.3)) { - insertNotification(notification) - hiddenNotificationIds.remove(notification.id) - if !isPresented && !notification.isSticky { - startHideTimer(for: notification) + let operation = { + self.insertNotification(notification) + self.hiddenNotificationIds.remove(notification.id) + if !self.isPresented && !notification.isSticky { + self.startHideTimer(for: notification) + } + } + + if #available(macOS 26, *) { + withAnimation(.easeInOut(duration: 0.3), operation) { + self.updateToolbarItem() } + } else { + withAnimation(.easeInOut(duration: 0.3), operation) } } @@ -215,6 +230,29 @@ final class NotificationPanelViewModel: ObservableObject { } } + func updateToolbarItem() { + if #available(macOS 15.0, *) { + self.workspace?.windowControllers.forEach { controller in + guard let toolbar = controller.window?.toolbar else { + return + } + let shouldShow = !self.visibleNotifications.isEmpty || NotificationManager.shared.unreadCount > 0 + if shouldShow && toolbar.items.filter({ $0.itemIdentifier == .notificationItem }).first == nil { + guard let activityItemIdx = toolbar.items.firstIndex(where: { $0.itemIdentifier == .activityViewer }) else { + return + } + toolbar.insertItem(withItemIdentifier: .space, at: activityItemIdx + 1) + toolbar.insertItem(withItemIdentifier: .notificationItem, at: activityItemIdx + 2) + } + + if !shouldShow, let index = toolbar.items.firstIndex(where: { $0.itemIdentifier == .notificationItem }) { + toolbar.removeItem(at: index) + toolbar.removeItem(at: index) + } + } + } + } + init() { // Observe new notifications NotificationCenter.default.addObserver( @@ -252,14 +290,22 @@ final class NotificationPanelViewModel: ObservableObject { private func handleNotificationRemoved(_ notification: Notification) { guard let ceNotification = notification.object as? CENotification else { return } - // Just remove from active notifications without triggering global state changes - withAnimation(.easeOut(duration: 0.2)) { - activeNotifications.removeAll(where: { $0.id == ceNotification.id }) + let operation: () -> Void = { + self.activeNotifications.removeAll(where: { $0.id == ceNotification.id }) // If this was the last notification and they were manually shown, hide the panel - if activeNotifications.isEmpty && isPresented { - isPresented = false + if self.activeNotifications.isEmpty && self.isPresented { + self.isPresented = false } } + + // Just remove from active notifications without triggering global state changes + if #available(macOS 26, *) { + withAnimation(.easeOut(duration: 0.2), operation) { + self.updateToolbarItem() + } + } else { + withAnimation(.easeOut(duration: 0.2), operation) + } } } diff --git a/CodeEdit/Features/Notifications/Views/NotificationToolbarItem.swift b/CodeEdit/Features/Notifications/Views/NotificationToolbarItem.swift index 9729330ddd..ecf8ea94a5 100644 --- a/CodeEdit/Features/Notifications/Views/NotificationToolbarItem.swift +++ b/CodeEdit/Features/Notifications/Views/NotificationToolbarItem.swift @@ -14,9 +14,7 @@ struct NotificationToolbarItem: View { private var controlActiveState var body: some View { - let visibleNotifications = workspace.notificationPanel.activeNotifications.filter { - !workspace.notificationPanel.hiddenNotificationIds.contains($0.id) - } + let visibleNotifications = workspace.notificationPanel.visibleNotifications if notificationManager.unreadCount > 0 || !visibleNotifications.isEmpty { Button { From c2e7e7034098f12ff8e47d39252b7c32ce276270 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:37:39 -0500 Subject: [PATCH 11/15] fix:lint --- .../ViewModels/NotificationPanelViewModel.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift b/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift index dab6933ff7..6fdcc89143 100644 --- a/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift +++ b/CodeEdit/Features/Notifications/ViewModels/NotificationPanelViewModel.swift @@ -238,14 +238,16 @@ final class NotificationPanelViewModel: ObservableObject { } let shouldShow = !self.visibleNotifications.isEmpty || NotificationManager.shared.unreadCount > 0 if shouldShow && toolbar.items.filter({ $0.itemIdentifier == .notificationItem }).first == nil { - guard let activityItemIdx = toolbar.items.firstIndex(where: { $0.itemIdentifier == .activityViewer }) else { + guard let activityItemIdx = toolbar.items + .firstIndex(where: { $0.itemIdentifier == .activityViewer }) else { return } toolbar.insertItem(withItemIdentifier: .space, at: activityItemIdx + 1) toolbar.insertItem(withItemIdentifier: .notificationItem, at: activityItemIdx + 2) } - if !shouldShow, let index = toolbar.items.firstIndex(where: { $0.itemIdentifier == .notificationItem }) { + if !shouldShow, let index = toolbar.items + .firstIndex(where: { $0.itemIdentifier == .notificationItem }) { toolbar.removeItem(at: index) toolbar.removeItem(at: index) } From 79b49b39bc3a956bcadf0e4747f990b2049667db Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:45:12 -0500 Subject: [PATCH 12/15] Correct Arrow Edge in Scheme Popover --- CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift index dbf9a0688e..5067871f69 100644 --- a/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift +++ b/CodeEdit/Features/ActivityViewer/Tasks/SchemeDropDownView.swift @@ -42,7 +42,7 @@ struct SchemeDropDownView: View { .onHover(perform: { hovering in self.isHoveringScheme = hovering }) - .instantPopover(isPresented: $isSchemePopOverPresented, arrowEdge: .bottom) { + .instantPopover(isPresented: $isSchemePopOverPresented, arrowEdge: .top) { popoverContent } .onTapGesture { From 46f4e364ca869bfbf178875ad10fdceff08479a5 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:41:03 -0500 Subject: [PATCH 13/15] Toolbar Opacity --- .../xcshareddata/swiftpm/Package.resolved | 6 +++--- .../Controllers/CodeEditWindowController+Toolbar.swift | 1 + CodeEdit/Features/Editor/Views/EditorAreaView.swift | 8 +++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d340ac124a..835319d36b 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "f457e734c292c01026823cb77c71fe712b1475f93229e48d3c14554bd650f9cd", + "originHash" : "01191ca9685501db65981a6fd21ab2d11c32196633d4cb776b5bb25908ed212f", "pins" : [ { "identity" : "aboutwindow", @@ -285,8 +285,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/tree-sitter/tree-sitter", "state" : { - "revision" : "bf655c0beaf4943573543fa77c58e8006ff34971", - "version" : "0.25.6" + "revision" : "f2f197b6b27ce75c280c20f131d4f71e906b86f7", + "version" : "0.25.8" } }, { diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift index 4b3383892c..e9730abc55 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift @@ -19,6 +19,7 @@ extension CodeEditWindowController { self.window?.toolbarStyle = .automatic toolbar.centeredItemIdentifiers = [.activityViewer, .notificationItem] toolbar.displayMode = .iconOnly + self.window?.titlebarAppearsTransparent = true } else { self.window?.toolbarStyle = .unifiedCompact toolbar.displayMode = .labelOnly diff --git a/CodeEdit/Features/Editor/Views/EditorAreaView.swift b/CodeEdit/Features/Editor/Views/EditorAreaView.swift index 544aed54e5..4795d7119a 100644 --- a/CodeEdit/Features/Editor/Views/EditorAreaView.swift +++ b/CodeEdit/Features/Editor/Views/EditorAreaView.swift @@ -129,7 +129,13 @@ struct EditorAreaView: View { } } .environment(\.isActiveEditor, editor == editorManager.activeEditor) - .background(EffectView(.headerView)) + .if(.tahoe) { + // FB20047271: Glass toolbar effect ignores floating scroll view views. + // https://openradar.appspot.com/radar?id=EhAKBVJhZGFyEICAgKbGmesJ + $0.background(EffectView(.headerView).ignoresSafeArea(.all)) + } else: { + $0.background(EffectView(.headerView)) + } } } .focused($focus, equals: editor) From 6218d89ea8af4b007ddb1e2c62d3cc82b64f14e1 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 4 Sep 2025 10:09:23 -0500 Subject: [PATCH 14/15] Revert Project File Changes --- CodeEdit.xcodeproj/project.pbxproj | 68 ++++++++---------------------- 1 file changed, 18 insertions(+), 50 deletions(-) diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 7b6eb5c3fe..ff63c4974c 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -18,11 +18,11 @@ 58F2EB03292FB2B0004A9BDE /* Documentation.docc in Sources */ = {isa = PBXBuildFile; fileRef = 58F2EACE292FB2B0004A9BDE /* Documentation.docc */; }; 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 58F2EB1D292FB954004A9BDE /* Sparkle */; }; 5E4485612DF600D9008BBE69 /* AboutWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 5E4485602DF600D9008BBE69 /* AboutWindow */; }; + 5EACE6222DF4BF08005E08B8 /* WelcomeWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 5EACE6212DF4BF08005E08B8 /* WelcomeWindow */; }; 6C0617D62BDB4432008C9C42 /* LogStream in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0617D52BDB4432008C9C42 /* LogStream */; }; 6C0824A12C5C0C9700A0751E /* SwiftTerm in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0824A02C5C0C9700A0751E /* SwiftTerm */; }; 6C147C4529A329350089B630 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 6C147C4429A329350089B630 /* OrderedCollections */; }; 6C315FC82E05E33D0011BFC5 /* CodeEditSourceEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 6C315FC72E05E33D0011BFC5 /* CodeEditSourceEditor */; }; - 6C33D9FB2E5F9184007782E7 /* WelcomeWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */; }; 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = 6C66C31229D05CDC00DE9ED2 /* GRDB */; }; 6C6BD6F429CD142C00235D17 /* CollectionConcurrencyKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C6BD6F329CD142C00235D17 /* CollectionConcurrencyKit */; }; 6C6BD6F829CD14D100235D17 /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C6BD6F729CD14D100235D17 /* CodeEditKit */; }; @@ -32,7 +32,6 @@ 6C81916B29B41DD300B75C92 /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = 6C81916A29B41DD300B75C92 /* DequeModule */; }; 6C85BB402C2105ED00EB5DEF /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C85BB3F2C2105ED00EB5DEF /* CodeEditKit */; }; 6C85BB442C210EFD00EB5DEF /* SwiftUIIntrospect in Frameworks */ = {isa = PBXBuildFile; productRef = 6C85BB432C210EFD00EB5DEF /* SwiftUIIntrospect */; }; - 6C883FD42E620E2B005BCFE8 /* WelcomeWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 6C883FD32E620E2B005BCFE8 /* WelcomeWindow */; }; 6C9DB9E42D55656300ACD86E /* CodeEditSourceEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 6C9DB9E32D55656300ACD86E /* CodeEditSourceEditor */; }; 6CAAF68A29BC9C2300A1F48A /* (null) in Sources */ = {isa = PBXBuildFile; }; 6CAAF69229BCC71C00A1F48A /* (null) in Sources */ = {isa = PBXBuildFile; }; @@ -172,7 +171,6 @@ buildActionMask = 2147483647; files = ( 302AD7FF2D8054D500231E16 /* ZIPFoundation in Frameworks */, - 6C883FD42E620E2B005BCFE8 /* WelcomeWindow in Frameworks */, 6C85BB402C2105ED00EB5DEF /* CodeEditKit in Frameworks */, 6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */, 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */, @@ -189,12 +187,12 @@ 30CB64912C16CA8100CC8A9E /* LanguageServerProtocol in Frameworks */, 5E4485612DF600D9008BBE69 /* AboutWindow in Frameworks */, 6C6BD6F429CD142C00235D17 /* CollectionConcurrencyKit in Frameworks */, - 6C33D9FB2E5F9184007782E7 /* WelcomeWindow in Frameworks */, 6C85BB442C210EFD00EB5DEF /* SwiftUIIntrospect in Frameworks */, 6CB446402B6DFF3A00539ED0 /* CodeEditSourceEditor in Frameworks */, 6C73A6D32D4F1E550012D95C /* CodeEditSourceEditor in Frameworks */, 2816F594280CF50500DD548B /* CodeEditSymbols in Frameworks */, 30CB64942C16CA9100CC8A9E /* LanguageClient in Frameworks */, + 5EACE6222DF4BF08005E08B8 /* WelcomeWindow in Frameworks */, 6C6BD6F829CD14D100235D17 /* CodeEditKit in Frameworks */, 6C0824A12C5C0C9700A0751E /* SwiftTerm in Frameworks */, 6C81916B29B41DD300B75C92 /* DequeModule in Frameworks */, @@ -333,13 +331,12 @@ 6CC00A8A2CBEF150004E8134 /* CodeEditSourceEditor */, 30818CB42D4E563900967860 /* ZIPFoundation */, 6C73A6D22D4F1E550012D95C /* CodeEditSourceEditor */, + 5EACE6212DF4BF08005E08B8 /* WelcomeWindow */, 5E4485602DF600D9008BBE69 /* AboutWindow */, 6C315FC72E05E33D0011BFC5 /* CodeEditSourceEditor */, 6C76D6D32E15B91E00EF52C3 /* CodeEditSourceEditor */, 6CCF6DD22E26D48F00B94F75 /* SwiftTerm */, 6CCF73CF2E26DE3200B94F75 /* SwiftTerm */, - 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */, - 6C883FD32E620E2B005BCFE8 /* WelcomeWindow */, ); productName = CodeEdit; productReference = B658FB2C27DA9E0F00EA4DBD /* CodeEdit.app */; @@ -400,7 +397,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1330; - LastUpgradeCheck = 2600; + LastUpgradeCheck = 1640; TargetAttributes = { 2BE487EB28245162003F3F64 = { CreatedOnToolsVersion = 13.3.1; @@ -442,10 +439,10 @@ 303E88462C276FD600EEA8D9 /* XCRemoteSwiftPackageReference "LanguageServerProtocol" */, 6CB94D012CA1205100E8651C /* XCRemoteSwiftPackageReference "swift-async-algorithms" */, 30ED7B722DD299E600ACC922 /* XCRemoteSwiftPackageReference "ZIPFoundation" */, + 5EACE6202DF4BF08005E08B8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */, 5E44855F2DF600D9008BBE69 /* XCRemoteSwiftPackageReference "AboutWindow" */, 6C76D6D22E15B91E00EF52C3 /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */, 6CCF73CE2E26DE3200B94F75 /* XCRemoteSwiftPackageReference "SwiftTerm" */, - 6C883FD22E620E2A005BCFE8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */, ); preferredProjectObjectVersion = 55; productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */; @@ -653,7 +650,6 @@ OTHER_SWIFT_FLAGS = "-D ALPHA"; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -677,7 +673,6 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -695,8 +690,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -773,7 +766,6 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -855,7 +847,6 @@ OTHER_SWIFT_FLAGS = "-D BETA"; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -879,7 +870,6 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -897,8 +887,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -975,7 +963,6 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1011,7 +998,6 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1047,7 +1033,6 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1130,7 +1115,6 @@ OTHER_SWIFT_FLAGS = "-D ALPHA"; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -1155,7 +1139,6 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -1173,8 +1156,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1251,7 +1232,6 @@ CURRENT_PROJECT_VERSION = 47; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OpenWithCodeEdit/Info.plist; @@ -1339,7 +1319,6 @@ ONLY_ACTIVE_ARCH = YES; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -1405,7 +1384,6 @@ MTL_FAST_MATH = YES; RUN_DOCUMENTATION_COMPILER = YES; SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SYSTEM_FRAMEWORK_SEARCH_PATHS = ""; @@ -1429,7 +1407,6 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -1447,8 +1424,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1473,7 +1448,6 @@ DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"CodeEdit/Preview Content\""; DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = NO; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = NO; @@ -1491,8 +1465,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = YES; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = YES; RUN_DOCUMENTATION_COMPILER = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1766,6 +1738,14 @@ minimumVersion = 1.0.0; }; }; + 5EACE6202DF4BF08005E08B8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/CodeEditApp/WelcomeWindow"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; 6C0617D42BDB4432008C9C42 /* XCRemoteSwiftPackageReference "LogStream" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Wouter01/LogStream"; @@ -1822,14 +1802,6 @@ minimumVersion = 1.2.0; }; }; - 6C883FD22E620E2A005BCFE8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/CodeEditApp/WelcomeWindow"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.0.0; - }; - }; 6C9DB9E22D55656300ACD86E /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/CodeEditApp/CodeEditSourceEditor"; @@ -1892,6 +1864,11 @@ package = 5E44855F2DF600D9008BBE69 /* XCRemoteSwiftPackageReference "AboutWindow" */; productName = AboutWindow; }; + 5EACE6212DF4BF08005E08B8 /* WelcomeWindow */ = { + isa = XCSwiftPackageProductDependency; + package = 5EACE6202DF4BF08005E08B8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */; + productName = WelcomeWindow; + }; 6C0617D52BDB4432008C9C42 /* LogStream */ = { isa = XCSwiftPackageProductDependency; package = 6C0617D42BDB4432008C9C42 /* XCRemoteSwiftPackageReference "LogStream" */; @@ -1910,10 +1887,6 @@ isa = XCSwiftPackageProductDependency; productName = CodeEditSourceEditor; }; - 6C33D9FA2E5F9184007782E7 /* WelcomeWindow */ = { - isa = XCSwiftPackageProductDependency; - productName = WelcomeWindow; - }; 6C66C31229D05CDC00DE9ED2 /* GRDB */ = { isa = XCSwiftPackageProductDependency; package = 6C66C31129D05CC800DE9ED2 /* XCRemoteSwiftPackageReference "GRDB.swift" */; @@ -1957,11 +1930,6 @@ package = 6C85BB422C210EFD00EB5DEF /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; productName = SwiftUIIntrospect; }; - 6C883FD32E620E2B005BCFE8 /* WelcomeWindow */ = { - isa = XCSwiftPackageProductDependency; - package = 6C883FD22E620E2A005BCFE8 /* XCRemoteSwiftPackageReference "WelcomeWindow" */; - productName = WelcomeWindow; - }; 6C9DB9E32D55656300ACD86E /* CodeEditSourceEditor */ = { isa = XCSwiftPackageProductDependency; package = 6C9DB9E22D55656300ACD86E /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */; From b0b24c963193eee32732c59ae2d7da71de859705 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Mon, 15 Sep 2025 09:26:53 -0500 Subject: [PATCH 15/15] Fix Toolbar Spacing on Sequoia --- .../Documents/Controllers/CodeEditWindowController+Toolbar.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift index e9730abc55..fbb536a074 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController+Toolbar.swift @@ -59,6 +59,7 @@ extension CodeEditWindowController { items += [ .activityViewer, .notificationItem, + .flexibleSpace, ] }