From b13876e758f2934c90cd73c16678e2de8c827d2e Mon Sep 17 00:00:00 2001 From: Ying Zhong <0x00eeee@gmail.com> Date: Fri, 12 Jun 2026 11:03:16 +0800 Subject: [PATCH 1/2] MACOSX_DEPLOYMENT_TARGET = 26.0 --- MarkEdit.xcodeproj/project.pbxproj | 16 +-- MarkEditCore/Package.swift | 6 +- MarkEditKit/Package.swift | 6 +- .../EditorModuleFoundationModels.swift | 22 +-- .../Modules/EditorModuleTranslation.swift | 5 - MarkEditMac/Modules/Package.swift | 4 +- .../Buttons/AquaFocusRingButton.swift | 34 ----- .../Buttons/NonBezelButton.swift | 30 ++-- .../AppKitControls/LabeledSearchField.swift | 32 ++--- .../AppKitControls/RoundedButtonGroup.swift | 22 +-- .../RoundedNavigateButtons.swift | 3 +- .../Foundation/NSPasteboard+Extension.swift | 8 -- .../UI/NSColor+Extension.swift | 4 - .../FileVersion/FileVersionPicker.swift | 6 +- .../Sources/FontPicker/FontPicker.swift | 2 +- .../FontPicker/FontPickerConfiguration.swift | 3 - .../Extensions/View+Extension.swift | 14 +- .../Statistics/StatisticsController.swift | 4 - .../Statistics/Views/StatisticsView.swift | 7 +- .../Internal/TextCompletionPanel.swift | 8 +- .../Internal/TextCompletionView.swift | 9 +- .../TextCompletionContext.swift | 4 - .../EditorViewController+Menu.swift | 1 - .../EditorViewController+Statistics.swift | 1 - .../EditorViewController+Toolbar.swift | 22 +-- .../Controllers/EditorViewController+UI.swift | 135 ++++++++---------- .../Controllers/EditorViewController.swift | 15 +- MarkEditMac/Sources/Editor/EditorWindow.swift | 34 +++-- .../Editor/Models/EditorDocument.swift | 1 - .../Editor/Models/EditorToolbarItems.swift | 25 +--- .../Editor/Views/EditorStatusView.swift | 37 +---- .../Sources/Editor/Views/EditorWebView.swift | 23 ++- MarkEditMac/Sources/Main/AppDesign.swift | 42 +----- MarkEditMac/Sources/Main/AppPreferences.swift | 4 +- .../Sources/Main/AppRuntimeConfig.swift | 14 +- .../Sources/Main/AppWritingTools.swift | 2 - .../Main/Application/Application.swift | 2 +- .../Sources/Panels/Find/EditorFindPanel.swift | 8 +- .../Panels/Replace/EditorReplaceButtons.swift | 2 +- .../Sources/Settings/EditorSettingsView.swift | 1 - MarkEditTools/Package.swift | 6 +- README.md | 4 +- 42 files changed, 185 insertions(+), 443 deletions(-) delete mode 100644 MarkEditMac/Modules/Sources/AppKitControls/Buttons/AquaFocusRingButton.swift diff --git a/MarkEdit.xcodeproj/project.pbxproj b/MarkEdit.xcodeproj/project.pbxproj index 308ec0281..546329a55 100644 --- a/MarkEdit.xcodeproj/project.pbxproj +++ b/MarkEdit.xcodeproj/project.pbxproj @@ -1046,7 +1046,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1112,7 +1112,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -1151,7 +1151,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "$(inherited)"; PRODUCT_NAME = MarkEdit; @@ -1188,7 +1188,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "$(inherited)"; PRODUCT_NAME = MarkEdit; @@ -1230,7 +1230,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).finder-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1276,7 +1276,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).finder-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1309,7 +1309,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).preview-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1340,7 +1340,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).preview-extension"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/MarkEditCore/Package.swift b/MarkEditCore/Package.swift index 6a8cd77fa..cb0cae1cc 100644 --- a/MarkEditCore/Package.swift +++ b/MarkEditCore/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -6,8 +6,8 @@ import PackageDescription let package = Package( name: "MarkEditCore", platforms: [ - .iOS(.v18), - .macOS(.v15), + .iOS(.v26), + .macOS(.v26), ], products: [ .library( diff --git a/MarkEditKit/Package.swift b/MarkEditKit/Package.swift index dcd27a773..557bee755 100644 --- a/MarkEditKit/Package.swift +++ b/MarkEditKit/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -6,8 +6,8 @@ import PackageDescription let package = Package( name: "MarkEditKit", platforms: [ - .iOS(.v18), - .macOS(.v15), + .iOS(.v26), + .macOS(.v26), ], products: [ .library( diff --git a/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleFoundationModels.swift b/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleFoundationModels.swift index 8cf019eb1..19c5594ef 100644 --- a/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleFoundationModels.swift +++ b/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleFoundationModels.swift @@ -29,10 +29,6 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { } public func createSession(instructions: String?) async -> String? { - guard #available(macOS 26.0, *) else { - return nil - } - let identifier = UUID().uuidString let session = LanguageModelSession(instructions: instructions) @@ -41,7 +37,7 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { } public func isResponding(sessionID: String?) async -> Bool { - guard #available(macOS 26.0, *), let session = session(with: sessionID) else { + guard let session = session(with: sessionID) else { return false } @@ -61,7 +57,7 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { ).jsonEncoded } - guard #available(macOS 26.0, *), let session = session(with: sessionID) else { + guard let session = session(with: sessionID) else { return encode(nil, "Model Unavailable", true) } @@ -103,7 +99,7 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { } } - guard #available(macOS 26.0, *), let session = session(with: sessionID) else { + guard let session = session(with: sessionID) else { return didReceive(nil, "Model Unavailable", true) } @@ -129,10 +125,6 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { // MARK: - Private private var defaultModelAvailability: LanguageModelAvailability { - guard #available(macOS 26.0, *) else { - return LanguageModelAvailability(isAvailable: false, unavailableReason: "Unsupported OS Version") - } - switch SystemLanguageModel.default.availability { case .available: return LanguageModelAvailability(isAvailable: true, unavailableReason: nil) @@ -147,12 +139,10 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { } } - // [macOS 26] Change the value type to LanguageModelSession - private var sessionPool = [String: AnyObject]() + private var sessionPool = [String: LanguageModelSession]() - @available(macOS 26.0, *) private func session(with sessionID: String?) -> LanguageModelSession? { - guard let sessionID, let session = (sessionPool[sessionID] as? LanguageModelSession) else { + guard let sessionID, let session = sessionPool[sessionID] else { return nil } @@ -162,7 +152,6 @@ public final class EditorModuleFoundationModels: NativeModuleFoundationModels { // MARK: - Private -@available(macOS 26.0, *) private extension GenerationOptions { init(_ options: LanguageModelGenerationOptions?) { #if canImport(FoundationModels, _version: 2) @@ -181,7 +170,6 @@ private extension GenerationOptions { } } -@available(macOS 26.0, *) private extension GenerationOptions.SamplingMode { init?(_ sampling: LanguageModelSampling?) { if sampling?.greedy == true { diff --git a/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleTranslation.swift b/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleTranslation.swift index e8f86c369..b59f49d58 100644 --- a/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleTranslation.swift +++ b/MarkEditKit/Sources/Bridge/Native/Modules/EditorModuleTranslation.swift @@ -13,10 +13,6 @@ public final class EditorModuleTranslation: NativeModuleTranslation { public init() {} public func translate(text: String, from: String?, to: String?) async -> String { - guard #available(macOS 26.0, *) else { - return TranslationResponse(error: "Unsupported OS Version").jsonEncoded - } - do { let from = from ?? NLLanguageRecognizer.dominantLanguage(for: text)?.rawValue ?? "en-US" let session = TranslationSession(from: from, to: to) @@ -41,7 +37,6 @@ private struct TranslationResponse: Encodable { } } -@available(macOS 26.0, *) private extension TranslationSession { convenience init(from: String, to: String?) { self.init( diff --git a/MarkEditMac/Modules/Package.swift b/MarkEditMac/Modules/Package.swift index 1630aaa6f..6135add3e 100644 --- a/MarkEditMac/Modules/Package.swift +++ b/MarkEditMac/Modules/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "Modules", platforms: [ - .macOS(.v15), + .macOS(.v26), ], products: [ .library( diff --git a/MarkEditMac/Modules/Sources/AppKitControls/Buttons/AquaFocusRingButton.swift b/MarkEditMac/Modules/Sources/AppKitControls/Buttons/AquaFocusRingButton.swift deleted file mode 100644 index 01a38ebb9..000000000 --- a/MarkEditMac/Modules/Sources/AppKitControls/Buttons/AquaFocusRingButton.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// AquaFocusRingButton.swift -// -// Created by cyan on 8/13/25. -// - -import AppKit - -/** - Custom drawing to make the focus ring stronger. - - This is needed for legacy OS only. - */ -public final class AquaFocusRingButton: NSButton { - override init(frame: CGRect) { - super.init(frame: frame) - focusRingType = .exterior - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func drawFocusRingMask() { - if #available(macOS 26.0, *) { - return super.drawFocusRingMask() - } - - var frame = bounds - frame.size.height -= 1 // The bezel shadow height - NSBezierPath(roundedRect: frame, radius: 5).fill() - } -} diff --git a/MarkEditMac/Modules/Sources/AppKitControls/Buttons/NonBezelButton.swift b/MarkEditMac/Modules/Sources/AppKitControls/Buttons/NonBezelButton.swift index b00be446e..84be613c6 100644 --- a/MarkEditMac/Modules/Sources/AppKitControls/Buttons/NonBezelButton.swift +++ b/MarkEditMac/Modules/Sources/AppKitControls/Buttons/NonBezelButton.swift @@ -10,7 +10,6 @@ import AppKitExtensions public class NonBezelButton: NSButton { public var focusRingRadius: Double? public var focusRingCorners: NSBezierPath.Corners? - public var modernStyle = false public var modernCornerRadius: Double = 0 public var modernStateChanged: ((_ isHighlighted: Bool) -> Void)? @@ -31,31 +30,18 @@ public class NonBezelButton: NSButton { let rectPath = NSBezierPath(rect: bounds) rectPath.fill() - // Classic style: - // - Default: clear background - // - Highlighted: light gray background - // - // Modern style: // - Default: light gray background // - Highlighted: slightly darker light gray, rounded corner - - if modernStyle { - modernStateChanged?(isHighlighted) - NSColor.modernButtonBackground.setFill() - rectPath.fill() - } + modernStateChanged?(isHighlighted) + NSColor.modernButtonBackground.setFill() + rectPath.fill() if isHighlighted { - if modernStyle { - NSBezierPath( - roundedRect: bounds, - xRadius: modernCornerRadius, - yRadius: modernCornerRadius - ).fill() - } else { - NSColor.plainButtonHighlighted.setFill() - rectPath.fill() - } + NSBezierPath( + roundedRect: bounds, + xRadius: modernCornerRadius, + yRadius: modernCornerRadius + ).fill() } } diff --git a/MarkEditMac/Modules/Sources/AppKitControls/LabeledSearchField.swift b/MarkEditMac/Modules/Sources/AppKitControls/LabeledSearchField.swift index 635399864..e488d1444 100644 --- a/MarkEditMac/Modules/Sources/AppKitControls/LabeledSearchField.swift +++ b/MarkEditMac/Modules/Sources/AppKitControls/LabeledSearchField.swift @@ -8,7 +8,6 @@ import AppKit import AppKitExtensions public final class LabeledSearchField: NSSearchField { - private let modernStyle: Bool private let bezelView = BezelView(cornerRadius: Constants.bezelCornerRadius) // To render custom icons in modern style due to the unwanted bezel added by Apple @@ -27,8 +26,7 @@ public final class LabeledSearchField: NSSearchField { return label }() - public init(modernStyle: Bool) { - self.modernStyle = modernStyle + public init() { super.init(frame: .zero) usesSingleLineMode = false @@ -64,16 +62,14 @@ public final class LabeledSearchField: NSSearchField { ) } - if modernStyle { - // To completely remove the unnecessary capsule-style border - if let view = modernBezelView { - renderCustomIcons(modernBezel: view) - } else if #unavailable(macOS 27.0) { - // [macOS 27] Revisit this later - #if DEBUG - assertionFailure("Missing AppKitSearchField in NSSearchField") - #endif - } + // To completely remove the unnecessary capsule-style border + if let view = modernBezelView { + renderCustomIcons(modernBezel: view) + } else if #unavailable(macOS 27.0) { + // [macOS 27] Revisit this later + #if DEBUG + assertionFailure("Missing AppKitSearchField in NSSearchField") + #endif } } @@ -121,10 +117,8 @@ public final class LabeledSearchField: NSSearchField { buttonCell?.image = nil buttonCell?.image = iconImage - if modernStyle { - searchIconView.image = nil - searchIconView.image = iconImage - } + searchIconView.image = nil + searchIconView.image = iconImage needsDisplay = true } @@ -159,10 +153,6 @@ private extension LabeledSearchField { } func updateCustomCancelIcon() { - guard modernStyle else { - return - } - cancelIconView.isHidden = stringValue.isEmpty } diff --git a/MarkEditMac/Modules/Sources/AppKitControls/RoundedButtonGroup.swift b/MarkEditMac/Modules/Sources/AppKitControls/RoundedButtonGroup.swift index 8dd8c4566..09e755ddf 100644 --- a/MarkEditMac/Modules/Sources/AppKitControls/RoundedButtonGroup.swift +++ b/MarkEditMac/Modules/Sources/AppKitControls/RoundedButtonGroup.swift @@ -16,20 +16,17 @@ open class RoundedButtonGroup: NSView { } } - private let modernStyle: Bool private let leftButton: NSButton private let rightButton: NSButton private let dividerView = DividerView(color: .plainButtonBorder) - public init(modernStyle: Bool, leftButton: NonBezelButton, rightButton: NonBezelButton) { - self.modernStyle = modernStyle + public init(leftButton: NonBezelButton, rightButton: NonBezelButton) { self.leftButton = leftButton self.rightButton = rightButton super.init(frame: .zero) wantsLayer = true layer?.masksToBounds = true - layer?.borderWidth = modernStyle ? 0 : 1 layer?.cornerRadius = Constants.cornerRadius addSubview(leftButton) @@ -37,13 +34,10 @@ open class RoundedButtonGroup: NSView { addSubview(dividerView) // Create a "segmented control"-like highlighted state - if modernStyle { - for button in [leftButton, rightButton] { - button.modernStyle = true - button.modernCornerRadius = Constants.cornerRadius - button.modernStateChanged = { [weak self] isHighlighted in - self?.dividerView.isHidden = isHighlighted - } + for button in [leftButton, rightButton] { + button.modernCornerRadius = Constants.cornerRadius + button.modernStateChanged = { [weak self] isHighlighted in + self?.dividerView.isHidden = isHighlighted } } @@ -83,7 +77,7 @@ open class RoundedButtonGroup: NSView { height: frame.height ) - let margin: Double = modernStyle ? 4 : 1 + let margin: Double = 4 dividerView.frame = CGRect( x: (frame.width - dividerView.length) * 0.5, y: margin, @@ -92,10 +86,6 @@ open class RoundedButtonGroup: NSView { ) } - override public func updateLayer() { - layer?.borderColor = NSColor.plainButtonBorder.cgColor - } - override public func hitTest(_ point: NSPoint) -> NSView? { isEnabled ? super.hitTest(point) : nil } diff --git a/MarkEditMac/Modules/Sources/AppKitControls/RoundedNavigateButtons.swift b/MarkEditMac/Modules/Sources/AppKitControls/RoundedNavigateButtons.swift index cc11b5909..ad1e6315f 100644 --- a/MarkEditMac/Modules/Sources/AppKitControls/RoundedNavigateButtons.swift +++ b/MarkEditMac/Modules/Sources/AppKitControls/RoundedNavigateButtons.swift @@ -15,7 +15,6 @@ public final class RoundedNavigateButtons: RoundedButtonGroup { } public init( - modernStyle: Bool, leftAction: @escaping (() -> Void), rightAction: @escaping (() -> Void), leftAccessibilityLabel: String, @@ -27,7 +26,7 @@ public final class RoundedNavigateButtons: RoundedButtonGroup { let rightButton = IconOnlyButton(symbolName: Constants.chevronRight, iconWidth: Constants.iconWidth, iconHeight: Constants.iconHeight, accessibilityLabel: rightAccessibilityLabel) rightButton.addAction(rightAction) - super.init(modernStyle: modernStyle, leftButton: leftButton, rightButton: rightButton) + super.init(leftButton: leftButton, rightButton: rightButton) self.frame = CGRect(x: 0, y: 0, width: 72, height: 0) } } diff --git a/MarkEditMac/Modules/Sources/AppKitExtensions/Foundation/NSPasteboard+Extension.swift b/MarkEditMac/Modules/Sources/AppKitExtensions/Foundation/NSPasteboard+Extension.swift index 17438c2e5..1277faec7 100644 --- a/MarkEditMac/Modules/Sources/AppKitExtensions/Foundation/NSPasteboard+Extension.swift +++ b/MarkEditMac/Modules/Sources/AppKitExtensions/Foundation/NSPasteboard+Extension.swift @@ -38,14 +38,6 @@ public extension NSPasteboard { } func url() async -> String? { - guard #available(macOS 15.4, *) else { - guard let string else { - return string(forType: .URL) - } - - return NSDataDetector.extractURL(from: string) - } - // This alerts the user only when the pasteboard really contains links let values = try? await NSPasteboard.general.detectedValues(for: [\.links]) return values?.links.first?.url.absoluteString diff --git a/MarkEditMac/Modules/Sources/AppKitExtensions/UI/NSColor+Extension.swift b/MarkEditMac/Modules/Sources/AppKitExtensions/UI/NSColor+Extension.swift index daf2e1f6b..0391dd69d 100644 --- a/MarkEditMac/Modules/Sources/AppKitExtensions/UI/NSColor+Extension.swift +++ b/MarkEditMac/Modules/Sources/AppKitExtensions/UI/NSColor+Extension.swift @@ -13,10 +13,6 @@ public extension NSColor { .theme(light: NSColor(white: 0, alpha: 0.3), dark: NSColor(white: 1, alpha: 0.3)) } - static var plainButtonHighlighted: NSColor { - .theme(light: NSColor(white: 0, alpha: 0.1), dark: NSColor(white: 1, alpha: 0.1)) - } - static var pushButtonBackground: NSColor { .theme(light: .white, dark: NSColor(hexCode: 0x565a61)) } diff --git a/MarkEditMac/Modules/Sources/FileVersion/FileVersionPicker.swift b/MarkEditMac/Modules/Sources/FileVersion/FileVersionPicker.swift index 0bb819c1c..f126e960e 100644 --- a/MarkEditMac/Modules/Sources/FileVersion/FileVersionPicker.swift +++ b/MarkEditMac/Modules/Sources/FileVersion/FileVersionPicker.swift @@ -18,7 +18,6 @@ public protocol FileVersionPickerDelegate: AnyObject { A custom file version picker to replace Time Machine due to its performance issues. */ public final class FileVersionPicker: NSViewController { - private let modernStyle: Bool private let fileURL: URL private let currentText: String private let localizable: FileVersionLocalizable @@ -94,7 +93,6 @@ public final class FileVersionPicker: NSViewController { }() private lazy var navigateButtons = RoundedNavigateButtons( - modernStyle: modernStyle, leftAction: { [weak self] in self?.goBack() }, @@ -127,14 +125,12 @@ public final class FileVersionPicker: NSViewController { private weak var delegate: FileVersionPickerDelegate? public init( - modernStyle: Bool, fileURL: URL, currentText: String, localVersions: [NSFileVersion], localizable: FileVersionLocalizable, delegate: FileVersionPickerDelegate ) { - self.modernStyle = modernStyle self.fileURL = fileURL self.currentText = currentText self.allVersions = localVersions @@ -280,7 +276,7 @@ private extension FileVersionPicker { navigateButtons.trailingAnchor.constraint(equalTo: topGuide.trailingAnchor, constant: -Constants.layoutPadding), navigateButtons.centerYAnchor.constraint(equalTo: topGuide.centerYAnchor), navigateButtons.widthAnchor.constraint(equalToConstant: navigateButtons.frame.width), - navigateButtons.heightAnchor.constraint(equalTo: versionMenuButton.heightAnchor, constant: modernStyle ? 0 : -2), + navigateButtons.heightAnchor.constraint(equalTo: versionMenuButton.heightAnchor), modeMenuButton.trailingAnchor.constraint(equalTo: navigateButtons.leadingAnchor, constant: -Constants.layoutPadding), modeMenuButton.centerYAnchor.constraint(equalTo: topGuide.centerYAnchor), diff --git a/MarkEditMac/Modules/Sources/FontPicker/FontPicker.swift b/MarkEditMac/Modules/Sources/FontPicker/FontPicker.swift index 29bb68bc5..c192f3d59 100644 --- a/MarkEditMac/Modules/Sources/FontPicker/FontPicker.swift +++ b/MarkEditMac/Modules/Sources/FontPicker/FontPicker.swift @@ -173,7 +173,7 @@ private extension FontPicker { ) } - let location = CGPoint(x: configuration.modernStyle ? -4 : 0, y: sourceView.frame.height - 10) + let location = CGPoint(x: -4, y: sourceView.frame.height - 10) menu.popUp(positioning: nil, at: location, in: sourceView) } } diff --git a/MarkEditMac/Modules/Sources/FontPicker/FontPickerConfiguration.swift b/MarkEditMac/Modules/Sources/FontPicker/FontPickerConfiguration.swift index cb9518f68..197d7db51 100644 --- a/MarkEditMac/Modules/Sources/FontPicker/FontPickerConfiguration.swift +++ b/MarkEditMac/Modules/Sources/FontPicker/FontPickerConfiguration.swift @@ -8,7 +8,6 @@ import AppKit import CoreText public struct FontPickerConfiguration { - let modernStyle: Bool let selectedFontStyle: FontStyle let selectedFontSize: Double let selectButtonTitle: String @@ -20,7 +19,6 @@ public struct FontPickerConfiguration { let serifFontName: String public init( - modernStyle: Bool, selectedFontStyle: FontStyle, selectedFontSize: Double, selectButtonTitle: String, @@ -31,7 +29,6 @@ public struct FontPickerConfiguration { roundedFontName: String, serifFontName: String ) { - self.modernStyle = modernStyle self.selectedFontStyle = selectedFontStyle self.selectedFontSize = selectedFontSize self.selectButtonTitle = selectButtonTitle diff --git a/MarkEditMac/Modules/Sources/SettingsUI/Extensions/View+Extension.swift b/MarkEditMac/Modules/Sources/SettingsUI/Extensions/View+Extension.swift index a21f635ee..d570de9dd 100644 --- a/MarkEditMac/Modules/Sources/SettingsUI/Extensions/View+Extension.swift +++ b/MarkEditMac/Modules/Sources/SettingsUI/Extensions/View+Extension.swift @@ -38,12 +38,8 @@ public extension View { } func formBreathingInset() -> some View { - if #available(macOS 26.0, *) { - // For unknown reasons, this is required to prevent extreme tight spacing - return padding(.top, .ulpOfOne) - } - - return self + // For unknown reasons, this is required to prevent extreme tight spacing + padding(.top, .ulpOfOne) } } @@ -61,10 +57,6 @@ private extension HorizontalAlignment { private struct FlexibleButtonSize: ViewModifier { func body(content: Content) -> some View { - if #available(macOS 26.0, *) { - content.buttonSizing(.flexible) - } else { - content - } + content.buttonSizing(.flexible) } } diff --git a/MarkEditMac/Modules/Sources/Statistics/StatisticsController.swift b/MarkEditMac/Modules/Sources/Statistics/StatisticsController.swift index c8666c982..4638cbccf 100644 --- a/MarkEditMac/Modules/Sources/Statistics/StatisticsController.swift +++ b/MarkEditMac/Modules/Sources/Statistics/StatisticsController.swift @@ -18,7 +18,6 @@ public final class StatisticsController: NSViewController { static let maxExtraRows: Int = 3 } - private let modernStyle: Bool private let content: ReadableContentPair private let fileURL: URL? private let localizable: StatisticsLocalizable @@ -26,13 +25,11 @@ public final class StatisticsController: NSViewController { private var contentView: NSView? public init( - modernStyle: Bool, content: ReadableContentPair, fileURL: URL?, localizable: StatisticsLocalizable, customRules: [StatisticsRule] = [] ) { - self.modernStyle = modernStyle self.content = content self.fileURL = fileURL self.localizable = localizable @@ -101,7 +98,6 @@ public final class StatisticsController: NSViewController { ) let contentView = NSHostingView(rootView: StatisticsView( - modernStyle: self.modernStyle, fullResult: fullResult, selectionResult: selectionResult, fullRuleResults: fullRuleResults, diff --git a/MarkEditMac/Modules/Sources/Statistics/Views/StatisticsView.swift b/MarkEditMac/Modules/Sources/Statistics/Views/StatisticsView.swift index 1230da124..252d27d03 100644 --- a/MarkEditMac/Modules/Sources/Statistics/Views/StatisticsView.swift +++ b/MarkEditMac/Modules/Sources/Statistics/Views/StatisticsView.swift @@ -9,7 +9,6 @@ import AppKitExtensions import SwiftUI struct StatisticsView: View { - private let modernStyle: Bool private let fullResult: StatisticsResult private let selectionResult: StatisticsResult? private let fullRuleResults: [StatisticsRuleResult] @@ -21,7 +20,6 @@ struct StatisticsView: View { @State private var localMonitor: Any? init( - modernStyle: Bool, fullResult: StatisticsResult, selectionResult: StatisticsResult?, fullRuleResults: [StatisticsRuleResult] = [], @@ -29,7 +27,6 @@ struct StatisticsView: View { fileURL: URL?, localizable: StatisticsLocalizable ) { - self.modernStyle = modernStyle self.fullResult = fullResult self.selectionResult = selectionResult self.fullRuleResults = fullRuleResults @@ -71,10 +68,10 @@ struct StatisticsView: View { } } else { Text(localizable.mainTitle) - .font(.system(size: modernStyle ? 14 : 13, weight: .semibold)) + .font(.system(size: 14, weight: .semibold)) } } - .frame(height: modernStyle ? 40 : 36) + .frame(height: 40) Divider() diff --git a/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionPanel.swift b/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionPanel.swift index 4ea0e5dd4..3b77b7bf2 100644 --- a/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionPanel.swift +++ b/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionPanel.swift @@ -13,7 +13,6 @@ final class TextCompletionPanel: NSPanel, TextCompletionPanelProtocol { private var mainView: NSHostingView? init( - modernStyle: Bool, effectViewType: NSView.Type, localizable: TextCompletionLocalizable, commitCompletion: @escaping () -> Void @@ -26,13 +25,12 @@ final class TextCompletionPanel: NSPanel, TextCompletionPanelProtocol { ) let mainView = NSHostingView(rootView: TextCompletionView( - modernStyle: modernStyle, state: state, localizable: localizable, commitCompletion: commitCompletion )) - let contentView = ContentView(modernStyle: modernStyle, effectViewType: effectViewType, frame: .zero) + let contentView = ContentView(effectViewType: effectViewType, frame: .zero) contentView.addSubview(mainView) self.mainView = mainView @@ -95,11 +93,11 @@ final class TextCompletionPanel: NSPanel, TextCompletionPanelProtocol { // MARK: - Private private final class ContentView: NSView { - init(modernStyle: Bool, effectViewType: NSView.Type, frame: CGRect) { + init(effectViewType: NSView.Type, frame: CGRect) { super.init(frame: frame) wantsLayer = true layer?.cornerCurve = .continuous - layer?.cornerRadius = modernStyle ? 8 : 5 + layer?.cornerRadius = 8 let effectView = effectViewType.init() effectView.translatesAutoresizingMaskIntoConstraints = false diff --git a/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionView.swift b/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionView.swift index acc09796c..2cc817cb6 100644 --- a/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionView.swift +++ b/MarkEditMac/Modules/Sources/TextCompletion/Internal/TextCompletionView.swift @@ -9,7 +9,6 @@ import SwiftUI struct TextCompletionView: View { private var state: TextCompletionState - private let modernStyle: Bool private let localizable: TextCompletionLocalizable private let commitCompletion: () -> Void @@ -22,12 +21,10 @@ struct TextCompletionView: View { } init( - modernStyle: Bool, state: TextCompletionState, localizable: TextCompletionLocalizable, commitCompletion: @escaping () -> Void ) { - self.modernStyle = modernStyle self.state = state self.localizable = localizable self.commitCompletion = commitCompletion @@ -42,7 +39,7 @@ struct TextCompletionView: View { ZStack(alignment: .leading) { if index == state.selectedIndex { Color.accent.clipShape(RoundedRectangle( - cornerRadius: modernStyle ? 5.5 : 3.5, + cornerRadius: 5.5, style: .continuous )) } @@ -61,7 +58,7 @@ struct TextCompletionView: View { }()) .font(.system(size: Constants.fontSize)) .foregroundColor(index == state.selectedIndex ? .white : .label.opacity(0.75)) - .padding([.leading, .trailing], Constants.itemPadding + (modernStyle ? 2 : 0)) + .padding([.leading, .trailing], Constants.itemPadding + 2) } .frame( maxWidth: .infinity, @@ -78,7 +75,7 @@ struct TextCompletionView: View { let bounds = CGRect( x: 0, y: 0, - width: Constants.minimumItemWidth + (modernStyle ? 4 : 0), + width: Constants.minimumItemWidth + 4, height: Constants.itemHeight ) diff --git a/MarkEditMac/Modules/Sources/TextCompletion/TextCompletionContext.swift b/MarkEditMac/Modules/Sources/TextCompletion/TextCompletionContext.swift index 708225427..b74d9e803 100644 --- a/MarkEditMac/Modules/Sources/TextCompletion/TextCompletionContext.swift +++ b/MarkEditMac/Modules/Sources/TextCompletion/TextCompletionContext.swift @@ -39,12 +39,10 @@ public final class TextCompletionContext { public var selectedText: String { panel.selectedCompletion() } public init( - modernStyle: Bool, effectViewType: NSView.Type, localizable: TextCompletionLocalizable, commitCompletion: @escaping @Sendable () -> Void ) { - self.modernStyle = modernStyle self.effectViewType = effectViewType self.localizable = localizable self.commitCompletion = commitCompletion @@ -116,7 +114,6 @@ public final class TextCompletionContext { // MARK: - Private private lazy var panel = TextCompletionPanel( - modernStyle: modernStyle, effectViewType: effectViewType, localizable: localizable, commitCompletion: commitCompletion @@ -127,7 +124,6 @@ public final class TextCompletionContext { // we don't want the panel to suddenly flip in this case. private var wasFlipped = false - private let modernStyle: Bool private let effectViewType: NSView.Type private let localizable: TextCompletionLocalizable private let commitCompletion: @Sendable () -> Void diff --git a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Menu.swift b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Menu.swift index 515c12c7b..ca52f2933 100644 --- a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Menu.swift +++ b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Menu.swift @@ -45,7 +45,6 @@ extension EditorViewController { return item } - @available(macOS 15.1, *) var systemWritingToolsMenu: NSMenu? { NSApp.appDelegate?.mainEditMenu?.items.first { $0.identifier?.rawValue == "__NSTextViewContextSubmenuIdentifierWritingTools" diff --git a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Statistics.swift b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Statistics.swift index f88f69c88..365d29640 100644 --- a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Statistics.swift +++ b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Statistics.swift @@ -26,7 +26,6 @@ extension EditorViewController { } let statisticsController = StatisticsController( - modernStyle: AppDesign.modernStyle, content: content, fileURL: document?.fileURL, localizable: StatisticsLocalizable( diff --git a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Toolbar.swift b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Toolbar.swift index 561f6a974..3340f1f09 100644 --- a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Toolbar.swift +++ b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+Toolbar.swift @@ -23,16 +23,6 @@ extension EditorViewController { private enum Constants { static let tableOfContentsMenuIdentifier = NSUserInterfaceItemIdentifier("tableOfContentsMenu") static let tableOfContentsMinimumWidth: Double = 160 - - @MainActor static let normalizedButtonSize: Double? = { - if AppDesign.modernStyle { - // The issue seems fixed with the Liquid Glass design - return nil - } - - // "bold" icon looks bigger than expected, fix it - return 15 - }() } func updateToolbarItemMenus(_ menu: NSMenu) { @@ -169,19 +159,19 @@ private extension EditorViewController { } var toggleBoldItem: NSToolbarItem { - .with(identifier: .toggleBold, iconSize: Constants.normalizedButtonSize) { [weak self] in + .with(identifier: .toggleBold) { [weak self] in self?.toggleBold(nil) } } var toggleItalicItem: NSToolbarItem { - .with(identifier: .toggleItalic, iconSize: Constants.normalizedButtonSize) { [weak self] in + .with(identifier: .toggleItalic) { [weak self] in self?.toggleItalic(nil) } } var toggleStrikethroughItem: NSToolbarItem { - .with(identifier: .toggleStrikethrough, iconSize: Constants.normalizedButtonSize) { [weak self] in + .with(identifier: .toggleStrikethrough) { [weak self] in self?.toggleStrikethrough(nil) } } @@ -262,11 +252,11 @@ private extension EditorViewController { } var writingToolsItem: NSToolbarItem? { - if #available(macOS 15.1, *), let menu = systemWritingToolsMenu { - return .with(identifier: .writingTools, menu: menu.copiedMenu) - } else { + guard let menu = systemWritingToolsMenu else { return nil } + + return .with(identifier: .writingTools, menu: menu.copiedMenu) } func updateTableOfContentsMenu(_ menu: NSMenu) { diff --git a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+UI.swift b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+UI.swift index a268136d5..2971085a7 100644 --- a/MarkEditMac/Sources/Editor/Controllers/EditorViewController+UI.swift +++ b/MarkEditMac/Sources/Editor/Controllers/EditorViewController+UI.swift @@ -21,20 +21,16 @@ extension EditorViewController { let wrapper = NSView(frame: CGRect(x: 0, y: 0, width: 720, height: 480)) self.view = wrapper - if AppDesign.modernTitleBar { - wrapper.addSubview(modernBackgroundView) - } - + wrapper.addSubview(modernBackgroundView) wrapper.addSubview(findPanel) wrapper.addSubview(replacePanel) wrapper.addSubview(webView) wrapper.addSubview(statusView) - if AppDesign.modernTitleBar { - wrapper.addSubview(modernEffectView) - wrapper.addSubview(modernTintedView) - wrapper.addSubview(modernDividerView) - } + // View order matters + wrapper.addSubview(modernEffectView) + wrapper.addSubview(modernTintedView) + wrapper.addSubview(modernDividerView) // The divider must be on very top panelDivider.alphaValue = AppDesign.dividerAlpha @@ -44,36 +40,35 @@ extension EditorViewController { layoutWebView() layoutStatusView() - if AppDesign.modernTitleBar { - modernBackgroundView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - modernBackgroundView.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor), - modernBackgroundView.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor), - modernBackgroundView.bottomAnchor.constraint(equalTo: wrapper.bottomAnchor), - modernBackgroundView.topAnchor.constraint(equalTo: modernEffectView.bottomAnchor), - ]) - - modernEffectView.material = .titlebar - modernEffectView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - modernEffectView.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor), - modernEffectView.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor), - modernEffectView.topAnchor.constraint(equalTo: wrapper.topAnchor), - modernEffectHeight, - ]) - - // It covers precisely to provide a tinted color - modernTintedView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - modernTintedView.leadingAnchor.constraint(equalTo: modernEffectView.leadingAnchor), - modernTintedView.trailingAnchor.constraint(equalTo: modernEffectView.trailingAnchor), - modernTintedView.topAnchor.constraint(equalTo: modernEffectView.topAnchor), - modernTintedView.bottomAnchor.constraint(equalTo: modernEffectView.bottomAnchor), - ]) - - // To avoid duplicate dividers - modernDividerView.alphaValue = 0 - } + // Initialize the customized modern titlebar + modernBackgroundView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + modernBackgroundView.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor), + modernBackgroundView.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor), + modernBackgroundView.bottomAnchor.constraint(equalTo: wrapper.bottomAnchor), + modernBackgroundView.topAnchor.constraint(equalTo: modernEffectView.bottomAnchor), + ]) + + modernEffectView.material = .titlebar + modernEffectView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + modernEffectView.leadingAnchor.constraint(equalTo: wrapper.leadingAnchor), + modernEffectView.trailingAnchor.constraint(equalTo: wrapper.trailingAnchor), + modernEffectView.topAnchor.constraint(equalTo: wrapper.topAnchor), + modernEffectHeight, + ]) + + // It covers precisely to provide a tinted color + modernTintedView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + modernTintedView.leadingAnchor.constraint(equalTo: modernEffectView.leadingAnchor), + modernTintedView.trailingAnchor.constraint(equalTo: modernEffectView.trailingAnchor), + modernTintedView.topAnchor.constraint(equalTo: modernEffectView.topAnchor), + modernTintedView.bottomAnchor.constraint(equalTo: modernEffectView.bottomAnchor), + ]) + + // To avoid duplicate dividers + modernDividerView.alphaValue = 0 // Initially hide panels to prevent being found by VoiceOver findPanel.isHidden = true @@ -136,27 +131,25 @@ extension EditorViewController { let prefersTintedToolbar = theme.prefersTintedToolbar || backgroundColor.isTintedColor (view.window as? EditorWindow)?.prefersTintedToolbar = prefersTintedToolbar - if AppDesign.modernTitleBar { - let isMainWindow = view.window?.isMainWindow ?? false - let isFullscreen = view.window?.styleMask.contains(.fullScreen) ?? false - let reduceTransparency = !isMainWindow || AppDesign.reduceTransparency || isFullscreen - let baseColor = backgroundColor.withAlphaComponent(reduceTransparency ? 1.0 : 0.01) + let isMainWindow = view.window?.isMainWindow ?? false + let isFullscreen = view.window?.styleMask.contains(.fullScreen) ?? false + let reduceTransparency = !isMainWindow || AppDesign.reduceTransparency || isFullscreen + let baseColor = backgroundColor.withAlphaComponent(reduceTransparency ? 1.0 : 0.01) - view.window?.backgroundColor = baseColor - view.window?.toolbarContainerView?.layerBackgroundColor = baseColor + view.window?.backgroundColor = baseColor + view.window?.toolbarContainerView?.layerBackgroundColor = baseColor - modernBackgroundView.layerBackgroundColor = backgroundColor - modernEffectView.isHidden = reduceTransparency + modernBackgroundView.layerBackgroundColor = backgroundColor + modernEffectView.isHidden = reduceTransparency - // Hide the effect view and remove the opacity of the title bar view - if reduceTransparency { - modernTintedView.layerBackgroundColor = backgroundColor - } else { - let (tintedAlpha, plainAlpha) = AppRuntimeConfig.toolbarTintAlphaValues - let alphaValue = prefersTintedToolbar ? tintedAlpha : plainAlpha - let tintColor = backgroundColor.withAlphaComponent(alphaValue).resolvedColor() - modernTintedView.layerBackgroundColor = tintColor - } + // Hide the effect view and remove the opacity of the title bar view + if reduceTransparency { + modernTintedView.layerBackgroundColor = backgroundColor + } else { + let (tintedAlpha, plainAlpha) = AppRuntimeConfig.toolbarTintAlphaValues + let alphaValue = prefersTintedToolbar ? tintedAlpha : plainAlpha + let tintColor = backgroundColor.withAlphaComponent(alphaValue).resolvedColor() + modernTintedView.layerBackgroundColor = tintColor } statusView.setBackgroundColor(backgroundColor) @@ -164,7 +157,6 @@ extension EditorViewController { replacePanel.setBackgroundColor(backgroundColor) } - @available(macOS 15.1, *) func updateWritingTools(isActive: Bool) { let performUpdate = { // Work around undo stack and selection range issues @@ -204,13 +196,8 @@ extension EditorViewController { findPanel.findButtons.frame.height ) - if AppDesign.modernTitleBar { - modernEffectHeight.constant = view.safeAreaInsets.top + panelDivider.frame.height - modernDividerView.update(animated).alphaValue = findPanel.mode == .hidden ? 0 : AppDesign.dividerAlpha - } else { - // To avoid duplicate dividers on legacy titlebar - panelDivider.isHidden = findPanel.mode == .hidden - } + modernEffectHeight.constant = view.safeAreaInsets.top + panelDivider.frame.height + modernDividerView.update(animated).alphaValue = findPanel.mode == .hidden ? 0 : AppDesign.dividerAlpha // The position of this divider should be fixed modernDividerView.frame = CGRect( @@ -237,14 +224,8 @@ extension EditorViewController { } func layoutStatusView() { - let margin: Double = { - if AppDesign.modernStyle { - // To fit better for the huge corner radius - return 16 - } - - return 6 - }() + // To fit better for the huge corner radius + let margin: Double = 16 statusView.frame = CGRect( x: view.bounds.width - statusView.frame.width - margin, @@ -573,9 +554,7 @@ private extension EditorViewController { return } - if AppDesign.modernStyle { - updateWindowColors(.current) - } + updateWindowColors(.current) if AppRuntimeConfig.nativeSearchQuerySync { updateNativeSearchQuery() @@ -587,9 +566,7 @@ private extension EditorViewController { return } - if AppDesign.modernStyle { - updateWindowColors(.current) - } + updateWindowColors(.current) } @objc func popoverDidShow(_ notification: Notification) { diff --git a/MarkEditMac/Sources/Editor/Controllers/EditorViewController.swift b/MarkEditMac/Sources/Editor/Controllers/EditorViewController.swift index 5a50834eb..2ecfa2964 100644 --- a/MarkEditMac/Sources/Editor/Controllers/EditorViewController.swift +++ b/MarkEditMac/Sources/Editor/Controllers/EditorViewController.swift @@ -171,7 +171,7 @@ final class EditorViewController: NSViewController { config.setURLSchemeHandler(imageLoader, forURLScheme: EditorImageLoader.scheme) // Respect user settings for Writing Tools behavior - if #available(macOS 15.1, *), let writingToolsBehavior = AppRuntimeConfig.writingToolsBehavior { + if let writingToolsBehavior = AppRuntimeConfig.writingToolsBehavior { config.writingToolsBehavior = writingToolsBehavior } @@ -200,14 +200,12 @@ final class EditorViewController: NSViewController { } // [macOS 15] Detect Writing Tools visibility to work around issues - if #available(macOS 15.1, *) { - writingToolsObservation = webView.observe(\.isWritingToolsActive) { [weak self] _, _ in - guard let self else { - return - } - - self.updateWritingTools(isActive: self.webView.isWritingToolsActive) + writingToolsObservation = webView.observe(\.isWritingToolsActive) { [weak self] _, _ in + guard let self else { + return } + + self.updateWritingTools(isActive: self.webView.isWritingToolsActive) } return webView @@ -215,7 +213,6 @@ final class EditorViewController: NSViewController { private(set) lazy var completionContext = { TextCompletionContext( - modernStyle: AppDesign.modernStyle, effectViewType: AppDesign.modernEffectView, localizable: TextCompletionLocalizable(selectedHint: Localized.General.selected) ) { [weak self] in diff --git a/MarkEditMac/Sources/Editor/EditorWindow.swift b/MarkEditMac/Sources/Editor/EditorWindow.swift index ee3312c1f..8e06e511d 100644 --- a/MarkEditMac/Sources/Editor/EditorWindow.swift +++ b/MarkEditMac/Sources/Editor/EditorWindow.swift @@ -76,30 +76,28 @@ final class EditorWindow: NSWindow { if let view = cachedToolbarEffectView { let needsOverlay = styleMask.contains(.fullScreen) && toolbarMode == .hidden view.alphaValue = needsOverlay ? 1 : (prefersTintedToolbar ? 0.3 : 0.7) - view.isHidden = !needsOverlay && (reduceTransparency == true || AppDesign.modernTitleBar) + view.isHidden = !needsOverlay // Blend the color of contents behind the window (view as? NSVisualEffectView)?.blendingMode = .behindWindow } - if AppDesign.modernTitleBar { - if cachedTitlebarDecorationView == nil { - cachedTitlebarDecorationView = titlebarDecorationView - } + if cachedTitlebarDecorationView == nil { + cachedTitlebarDecorationView = titlebarDecorationView + } - // Disable the separator instead of using `titlebarAppearsTransparent`, - // which breaks "Merge All Windows". - if let view = cachedTitlebarDecorationView { - let selector = sel_getUid("setDrawsBottomSeparator:") - if view.responds(to: selector) { - unsafeBitCast( - view.method(for: selector), - to: (@convention(c) (NSView, Selector, Bool) -> Void).self - )(view, selector, false) - } else { - Logger.assertFail("Missing setDrawsBottomSeparator: in _NSTitlebarDecorationView") - view.isHidden = true - } + // Disable the separator instead of using `titlebarAppearsTransparent`, + // which breaks "Merge All Windows". + if let view = cachedTitlebarDecorationView { + let selector = sel_getUid("setDrawsBottomSeparator:") + if view.responds(to: selector) { + unsafeBitCast( + view.method(for: selector), + to: (@convention(c) (NSView, Selector, Bool) -> Void).self + )(view, selector, false) + } else { + Logger.assertFail("Missing setDrawsBottomSeparator: in _NSTitlebarDecorationView") + view.isHidden = true } } } diff --git a/MarkEditMac/Sources/Editor/Models/EditorDocument.swift b/MarkEditMac/Sources/Editor/Models/EditorDocument.swift index 05bfbaa4b..776db5ad8 100644 --- a/MarkEditMac/Sources/Editor/Models/EditorDocument.swift +++ b/MarkEditMac/Sources/Editor/Models/EditorDocument.swift @@ -515,7 +515,6 @@ extension EditorDocument: FileVersionPickerDelegate { } let picker = FileVersionPicker( - modernStyle: AppDesign.modernStyle, fileURL: fileURL, currentText: stringValue, localVersions: localVersions, diff --git a/MarkEditMac/Sources/Editor/Models/EditorToolbarItems.swift b/MarkEditMac/Sources/Editor/Models/EditorToolbarItems.swift index 0936f453d..89dbdda14 100644 --- a/MarkEditMac/Sources/Editor/Models/EditorToolbarItems.swift +++ b/MarkEditMac/Sources/Editor/Models/EditorToolbarItems.swift @@ -15,7 +15,7 @@ extension NSToolbarItem { item.image = NSImage(systemSymbolName: identifier.itemIcon, accessibilityDescription: item.label) // Special icon for Writing Tools - if #available(macOS 15.1, *), identifier == .writingTools { + if identifier == .writingTools { item.image = AppWritingTools.affordanceIcon ?? item.image } @@ -29,19 +29,10 @@ extension NSToolbarItem { return item } - static func with(identifier: NSToolbarItem.Identifier, iconSize: Double? = nil, action: @escaping () -> Void) -> NSToolbarItem { + static func with(identifier: NSToolbarItem.Identifier, action: @escaping () -> Void) -> NSToolbarItem { let item = NSToolbarItem(itemIdentifier: identifier) item.label = identifier.itemLabel - - if let iconSize { - item.image = .with( - symbolName: identifier.itemIcon, - pointSize: iconSize, - accessibilityLabel: item.label - ) - } else { - item.image = NSImage(systemSymbolName: identifier.itemIcon, accessibilityDescription: item.label) - } + item.image = NSImage(systemSymbolName: identifier.itemIcon, accessibilityDescription: item.label) item.addAction(action) return item @@ -129,15 +120,7 @@ extension NSToolbarItem.Identifier { .statistics, .shareDocument, .copyPandocCommand, - ] - + { - if #available(macOS 15.1, *) { - return [.writingTools] - } - - return [] - }() - + [ + .writingTools, .space, .flexibleSpace, ] diff --git a/MarkEditMac/Sources/Editor/Views/EditorStatusView.swift b/MarkEditMac/Sources/Editor/Views/EditorStatusView.swift index b2513ace5..db73e6c4a 100644 --- a/MarkEditMac/Sources/Editor/Views/EditorStatusView.swift +++ b/MarkEditMac/Sources/Editor/Views/EditorStatusView.swift @@ -9,25 +9,11 @@ import AppKit import AppKitControls import MarkEditKit -// [macOS 26] Clean these up - -private protocol ButtonLabeling { - var labelView: LabelView { get } -} - -extension TitleOnlyButton: ButtonLabeling {} - /** To indicate the current line, column and length of selection. */ final class EditorStatusView: NSView, BackgroundTheming { - private let button: NSButton & ButtonLabeling = { - if AppDesign.modernStyle { - return GlassButton() - } - - return TitleOnlyButton(font: Constants.titleFont) - }() + private let button = GlassButton() init(handler: @escaping () -> Void) { super.init(frame: .zero) @@ -48,16 +34,8 @@ final class EditorStatusView: NSView, BackgroundTheming { } override func updateLayer() { - if button is GlassButton { - // Clear this, otherwise it appears as a rectangle over text selection - layer?.backgroundColor = .clear - return - } - - layer?.borderWidth = 1 - layer?.cornerRadius = 3 - layer?.cornerCurve = .continuous - layer?.borderColor = NSColor.plainButtonBorder.cgColor + // Clear this, otherwise it appears as a rectangle over text selection + layer?.backgroundColor = .clear } func updateLineColumn(_ info: LineColumnInfo) { @@ -75,7 +53,7 @@ final class EditorStatusView: NSView, BackgroundTheming { label.stringValue = title label.sizeToFit() - self.frame = label.bounds.insetBy(dx: -4, dy: AppDesign.modernStyle ? -3 : -2) + self.frame = label.bounds.insetBy(dx: -4, dy: -3) self.needsLayout = true } } @@ -115,11 +93,12 @@ private enum Constants { static let titleFont: NSFont = .monospacedDigitSystemFont(ofSize: 11, weight: .regular) } -private class GlassButton: NSButton, ButtonLabeling { +private class GlassButton: NSButton { fileprivate let labelView = LabelView() override init(frame frameRect: CGRect) { super.init(frame: frameRect) + bezelStyle = .glass font = .systemFont(ofSize: 7) // To make the button smaller title = "" // Clear the title and bezel @@ -130,10 +109,6 @@ private class GlassButton: NSButton, ButtonLabeling { labelView.centerXAnchor.constraint(equalTo: centerXAnchor), labelView.centerYAnchor.constraint(equalTo: centerYAnchor), ]) - - if #available(macOS 26.0, *) { - bezelStyle = .glass - } } @available(*, unavailable) diff --git a/MarkEditMac/Sources/Editor/Views/EditorWebView.swift b/MarkEditMac/Sources/Editor/Views/EditorWebView.swift index 431d88cc8..54570cef2 100644 --- a/MarkEditMac/Sources/Editor/Views/EditorWebView.swift +++ b/MarkEditMac/Sources/Editor/Views/EditorWebView.swift @@ -126,21 +126,23 @@ final class EditorWebView: WKWebView { action: #selector(selectAllOccurrences(_:)) ) - if AppDesign.menuIconEvolution { - findSelectionItem.image = NSImage(systemSymbolName: "text.page.badge.magnifyingglass", accessibilityDescription: nil) - selectAllOccurrencesItem.image = NSImage(systemSymbolName: "selection.pin.in.out", accessibilityDescription: nil) - } + findSelectionItem.image = NSImage( + systemSymbolName: "text.page.badge.magnifyingglass", + accessibilityDescription: nil + ) + + selectAllOccurrencesItem.image = NSImage( + systemSymbolName: "selection.pin.in.out", + accessibilityDescription: nil + ) // Only add text format items when it's not read-only if !(actionDelegate?.editorWebViewIsReadOnlyMode(self) ?? false) { let item = NSMenuItem() + item.image = NSImage(systemSymbolName: "bold.italic.underline", accessibilityDescription: nil) item.title = Localized.Toolbar.textFormat item.submenu = NSApp.appDelegate?.textFormatMenu?.copiedMenu - if AppDesign.menuIconEvolution { - item.image = NSImage(systemSymbolName: "bold.italic.underline", accessibilityDescription: nil) - } - menu.addItem(item) } @@ -207,12 +209,9 @@ private extension EditorWebView { // // WKWebView.showInspector() in WKWebView+Extension.swift does the heavy lifting if item.identifier == NSUserInterfaceItemIdentifier.inspectElement { + item.image = NSImage(systemSymbolName: "ladybug", accessibilityDescription: nil) item.keyEquivalent = "i" item.keyEquivalentModifierMask = [.option, .command] - - if AppDesign.menuIconEvolution { - item.image = NSImage(systemSymbolName: "ladybug", accessibilityDescription: nil) - } } // Disable copy, cut for empty selection (always enable on editor blur) diff --git a/MarkEditMac/Sources/Main/AppDesign.swift b/MarkEditMac/Sources/Main/AppDesign.swift index cad2781fa..f85770b4c 100644 --- a/MarkEditMac/Sources/Main/AppDesign.swift +++ b/MarkEditMac/Sources/Main/AppDesign.swift @@ -9,37 +9,8 @@ import AppKit @MainActor enum AppDesign { - /** - Returns `true` to adopt the new design language in macOS Tahoe. - */ - static var modernStyle: Bool { - guard #available(macOS 26.0, *) else { - return false - } - - return true - } - - /** - Returns `true` to use a customized title bar for the editor. - - It will be enabled in macOS Tahoe and later. - */ - static var modernTitleBar: Bool { - modernStyle - } - - /** - Returns `true` to gradually add icons to the menu bar. - - It will be enabled in macOS Tahoe and later. - */ - static var menuIconEvolution: Bool { - modernStyle - } - static var dividerAlpha: Double { - modernStyle ? 0.7 : 1.0 + 0.7 } static var reduceTransparency: Bool { @@ -50,16 +21,7 @@ enum AppDesign { NSWorkspace.shared.accessibilityDisplayShouldReduceMotion } - /** - Returns either an `NSGlassEffectView`, or an `NSVisualEffectView` as fallback. - - `NSGlassEffectView` is used when it is available and `modernStyle` is true. - */ static var modernEffectView: NSView.Type { - guard #available(macOS 26.0, *), modernStyle else { - return NSVisualEffectView.self - } - - return NSGlassEffectView.self + NSGlassEffectView.self } } diff --git a/MarkEditMac/Sources/Main/AppPreferences.swift b/MarkEditMac/Sources/Main/AppPreferences.swift index 2111da72f..d44d5a742 100644 --- a/MarkEditMac/Sources/Main/AppPreferences.swift +++ b/MarkEditMac/Sources/Main/AppPreferences.swift @@ -233,9 +233,7 @@ enum AppPreferences { performUpdates { editor in Task { @MainActor in // Modern title bar is implemented in the view controller layer - if AppDesign.modernTitleBar { - editor.updateWindowColors(AppTheme.current) - } + editor.updateWindowColors(AppTheme.current) } (editor.view.window as? EditorWindow)?.reduceTransparency = reduceTransparency diff --git a/MarkEditMac/Sources/Main/AppRuntimeConfig.swift b/MarkEditMac/Sources/Main/AppRuntimeConfig.swift index 7546c4c16..6264b84bb 100644 --- a/MarkEditMac/Sources/Main/AppRuntimeConfig.swift +++ b/MarkEditMac/Sources/Main/AppRuntimeConfig.swift @@ -191,15 +191,13 @@ enum AppRuntimeConfig { } static var disableOpenPanelOptions: Bool { - currentDefinition?.disableOpenPanelOptions ?? ({ - // [macOS 26] Revisit this later, - // NSOpenPanel.accessoryView can significantly slow down the file opening process. - if #available(macOS 26.0, *) { - return true - } + if let option = currentDefinition?.disableOpenPanelOptions { + return option + } - return false - })() + // [macOS 26] Revisit this later, + // NSOpenPanel.accessoryView can significantly slow down the file opening process. + return true } static var disableCorsRestrictions: Bool { diff --git a/MarkEditMac/Sources/Main/AppWritingTools.swift b/MarkEditMac/Sources/Main/AppWritingTools.swift index dca3aad2b..77e09da59 100644 --- a/MarkEditMac/Sources/Main/AppWritingTools.swift +++ b/MarkEditMac/Sources/Main/AppWritingTools.swift @@ -8,7 +8,6 @@ import AppKit import MarkEditKit -@available(macOS 15.1, *) enum AppWritingTools { enum Tool: Int { case panel = 0 @@ -81,7 +80,6 @@ enum AppWritingTools { // MARK: - Private -@available(macOS 15.1, *) private extension AppWritingTools { /// Invokes a selector on a target and returns the result as `NSObject?`. static func invokeObject(_ target: NSObject, selector name: String) -> NSObject? { diff --git a/MarkEditMac/Sources/Main/Application/Application.swift b/MarkEditMac/Sources/Main/Application/Application.swift index c547c4a1f..30bc9ce51 100644 --- a/MarkEditMac/Sources/Main/Application/Application.swift +++ b/MarkEditMac/Sources/Main/Application/Application.swift @@ -35,7 +35,7 @@ final class Application: NSApplication { } // Ensure lines are fully selected for a better Writing Tools experience - if #available(macOS 15.1, *), action == sel_getUid("showWritingTools:") { + if action == sel_getUid("showWritingTools:") { Logger.assert(sender is NSMenuItem, "Invalid sender was found") Logger.assert(target == nil || (target as? AnyObject)?.className == "WKMenuTarget", "Invalid target was found") diff --git a/MarkEditMac/Sources/Panels/Find/EditorFindPanel.swift b/MarkEditMac/Sources/Panels/Find/EditorFindPanel.swift index 597909e3d..95f2c9c92 100644 --- a/MarkEditMac/Sources/Panels/Find/EditorFindPanel.swift +++ b/MarkEditMac/Sources/Panels/Find/EditorFindPanel.swift @@ -34,10 +34,9 @@ final class EditorFindPanel: EditorPanelView { var mode: EditorFindMode = .hidden var numberOfItems: Int = 0 var recentSearchesCursor: Int? - let searchField = LabeledSearchField(modernStyle: AppDesign.modernStyle) + let searchField = LabeledSearchField() private(set) lazy var findButtons = RoundedNavigateButtons( - modernStyle: AppDesign.modernStyle, leftAction: { [weak self] in guard let self else { return } self.delegate?.editorFindPanelDidClickPrevious(self) @@ -51,8 +50,9 @@ final class EditorFindPanel: EditorPanelView { ) private(set) lazy var doneButton = { - let button = AquaFocusRingButton() - button.bezelStyle = AppDesign.modernStyle ? .accessoryBar : .accessoryBarAction + let button = NSButton() + button.bezelStyle = .accessoryBar + button.focusRingType = .exterior button.attributedTitle = NSAttributedString( string: Localized.General.done, diff --git a/MarkEditMac/Sources/Panels/Replace/EditorReplaceButtons.swift b/MarkEditMac/Sources/Panels/Replace/EditorReplaceButtons.swift index 98b61a2b9..7dccc71d8 100644 --- a/MarkEditMac/Sources/Panels/Replace/EditorReplaceButtons.swift +++ b/MarkEditMac/Sources/Panels/Replace/EditorReplaceButtons.swift @@ -20,6 +20,6 @@ final class EditorReplaceButtons: RoundedButtonGroup { let rightButton = TitleOnlyButton(title: Localized.General.all, font: Constants.font) rightButton.addAction(rightAction) - super.init(modernStyle: AppDesign.modernStyle, leftButton: leftButton, rightButton: rightButton) + super.init(leftButton: leftButton, rightButton: rightButton) } } diff --git a/MarkEditMac/Sources/Settings/EditorSettingsView.swift b/MarkEditMac/Sources/Settings/EditorSettingsView.swift index 28e89d09f..13b6e3b5a 100644 --- a/MarkEditMac/Sources/Settings/EditorSettingsView.swift +++ b/MarkEditMac/Sources/Settings/EditorSettingsView.swift @@ -177,7 +177,6 @@ private extension EditorSettingsView { var fontPickerConfiguration: FontPickerConfiguration { FontPickerConfiguration( - modernStyle: AppDesign.modernStyle, selectedFontStyle: AppPreferences.Editor.fontStyle, selectedFontSize: AppPreferences.Editor.fontSize, selectButtonTitle: Localized.Settings.selectFont, diff --git a/MarkEditTools/Package.swift b/MarkEditTools/Package.swift index 4b1fb5628..a42bfddd9 100644 --- a/MarkEditTools/Package.swift +++ b/MarkEditTools/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -6,8 +6,8 @@ import PackageDescription let package = Package( name: "MarkEditTools", platforms: [ - .iOS(.v18), - .macOS(.v15), + .iOS(.v26), + .macOS(.v26), ], products: [ .plugin(name: "SwiftLint", targets: ["SwiftLint"]), diff --git a/README.md b/README.md index 4be8ecb0a..832b4eace 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # MarkEdit -[![](https://img.shields.io/badge/Platform-macOS_15.0+-blue?color=007bff)](https://github.com/MarkEdit-app/MarkEdit?tab=readme-ov-file#installation) [![](https://github.com/MarkEdit-app/MarkEdit/actions/workflows/build-and-test.yml/badge.svg?branch=main)](https://github.com/MarkEdit-app/MarkEdit/actions/workflows/build-and-test.yml) +[![](https://img.shields.io/badge/Platform-macOS_26.0+-blue?color=007bff)](https://github.com/MarkEdit-app/MarkEdit?tab=readme-ov-file#installation) [![](https://github.com/MarkEdit-app/MarkEdit/actions/workflows/build-and-test.yml/badge.svg?branch=main)](https://github.com/MarkEdit-app/MarkEdit/actions/workflows/build-and-test.yml) MarkEdit is a free and **open-source** Markdown editor, for macOS. It's just like _TextEdit_ on Mac but dedicated to `Markdown`. @@ -53,7 +53,7 @@ Get `MarkEdit.dmg` from the