Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2103,7 +2103,7 @@
}
})

view = AnyView(view.onChange(of: tabManager.selectedTabId) { newValue in

Check notice on line 2106 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2106

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
#if DEBUG
if let snapshot = tabManager.debugCurrentWorkspaceSwitchSnapshot() {
let dtMs = (CACurrentMediaTime() - snapshot.startedAt) * 1000
Expand All @@ -2125,7 +2125,7 @@
updateTitlebarText()
})

view = AnyView(view.onChange(of: tabManager.isWorkspaceCycleHot) { _ in

Check notice on line 2128 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2128

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
#if DEBUG
if let snapshot = tabManager.debugCurrentWorkspaceSwitchSnapshot() {
let dtMs = (CACurrentMediaTime() - snapshot.startedAt) * 1000
Expand All @@ -2139,7 +2139,7 @@
reconcileMountedWorkspaceIds()
})

view = AnyView(view.onChange(of: retiringWorkspaceId) { _ in

Check notice on line 2142 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2142

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
reconcileMountedWorkspaceIds()
})

Expand Down Expand Up @@ -2330,11 +2330,11 @@
}
}))

view = AnyView(view.onChange(of: bgGlassTintHex) { _ in

Check notice on line 2333 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2333

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
updateWindowGlassTint()
})

view = AnyView(view.onChange(of: bgGlassTintOpacity) { _ in

Check notice on line 2337 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2337

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
updateWindowGlassTint()
})

Expand All @@ -2361,7 +2361,7 @@
updateSidebarResizerBandState()
})

view = AnyView(view.onChange(of: sidebarWidth) { _ in

Check notice on line 2364 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2364

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
let sanitized = normalizedSidebarWidth(sidebarWidth)
if abs(sidebarWidth - sanitized) > 0.5 {
sidebarWidth = sanitized
Expand All @@ -2373,11 +2373,11 @@
updateSidebarResizerBandState()
})

view = AnyView(view.onChange(of: sidebarState.isVisible) { _ in

Check notice on line 2376 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2376

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
updateSidebarResizerBandState()
})

view = AnyView(view.onChange(of: sidebarState.persistedWidth) { newValue in

Check notice on line 2380 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2380

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
let sanitized = normalizedSidebarWidth(newValue)
if abs(newValue - sanitized) > 0.5 {
sidebarState.persistedWidth = sanitized
Expand Down Expand Up @@ -2781,7 +2781,7 @@
),
anchor: commandPaletteScrollTargetAnchor
)
.onChange(of: commandPaletteSelectedResultIndex) { _ in

Check notice on line 2784 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2784

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
updateCommandPaletteScrollTarget(resultCount: visibleResults.count, animated: true)
}

Expand All @@ -2800,14 +2800,14 @@
updateCommandPaletteScrollTarget(resultCount: visibleResults.count, animated: false)
resetCommandPaletteSearchFocus()
}
.onChange(of: commandPaletteQuery) { _ in

Check notice on line 2803 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2803

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
commandPaletteSelectedResultIndex = 0
commandPaletteHoveredResultIndex = nil
commandPaletteScrollTargetIndex = nil
commandPaletteScrollTargetAnchor = nil
syncCommandPaletteDebugStateForObservedWindow()
}
.onChange(of: visibleResults.count) { _ in

Check notice on line 2810 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2810

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
commandPaletteSelectedResultIndex = commandPaletteSelectedIndex(resultCount: visibleResults.count)
updateCommandPaletteScrollTarget(resultCount: visibleResults.count, animated: false)
if let hoveredIndex = commandPaletteHoveredResultIndex, hoveredIndex >= visibleResults.count {
Expand All @@ -2815,7 +2815,7 @@
}
syncCommandPaletteDebugStateForObservedWindow()
}
.onChange(of: commandPaletteSelectedResultIndex) { _ in

Check notice on line 2818 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L2818

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
syncCommandPaletteDebugStateForObservedWindow()
}
}
Expand Down Expand Up @@ -4214,8 +4214,9 @@
tabManager.selectPreviousSurface()
}
registry.register(commandId: "palette.openWorkspacePullRequests") {
let modifierFlags = NSEvent.modifierFlags
DispatchQueue.main.async {
if !openWorkspacePullRequestsInConfiguredBrowser() {
if !openWorkspacePullRequestsInConfiguredBrowser(modifierFlags: modifierFlags) {
NSSound.beep()
}
}
Expand Down Expand Up @@ -4884,13 +4885,18 @@
return NSWorkspace.shared.open(url)
}

private func openWorkspacePullRequestsInConfiguredBrowser() -> Bool {
private func openWorkspacePullRequestsInConfiguredBrowser(
modifierFlags: NSEvent.ModifierFlags = NSEvent.modifierFlags
) -> Bool {
guard let workspace = tabManager.selectedWorkspace else { return false }
let pullRequests = workspace.sidebarPullRequestsInDisplayOrder()
guard !pullRequests.isEmpty else { return false }

let shouldOpenInCmuxBrowser = BrowserLinkOpenSettings.shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: modifierFlags
)
var openedCount = 0
if openSidebarPullRequestLinksInCmuxBrowser {
if shouldOpenInCmuxBrowser {
for pullRequest in pullRequests {
if tabManager.openBrowser(url: pullRequest.url, insertAtEnd: true) != nil {
openedCount += 1
Expand Down Expand Up @@ -5652,7 +5658,7 @@
reason: "sidebar_disappear"
)
}
.onChange(of: draggedTabId) { newDraggedTabId in

Check notice on line 5661 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L5661

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
SidebarDragLifecycleNotification.postStateDidChange(
tabId: newDraggedTabId,
reason: "drag_state_change"
Expand Down Expand Up @@ -6762,7 +6768,7 @@
.onAppear {
rowHeight = max(proxy.size.height, 1)
}
.onChange(of: proxy.size.height) { newHeight in

Check notice on line 6771 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L6771

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
rowHeight = max(newHeight, 1)
}
}
Expand Down Expand Up @@ -7054,17 +7060,17 @@
selection = .tabs
}

private func updateSelection() {
private func updateSelection(modifierFlags: NSEvent.ModifierFlags = NSEvent.modifierFlags) {
#if DEBUG
let mods = NSEvent.modifierFlags
let mods = modifierFlags
var modStr = ""
if mods.contains(.command) { modStr += "cmd " }
if mods.contains(.shift) { modStr += "shift " }
if mods.contains(.option) { modStr += "opt " }
if mods.contains(.control) { modStr += "ctrl " }
dlog("sidebar.select workspace=\(tab.id.uuidString.prefix(5)) modifiers=\(modStr.isEmpty ? "none" : modStr.trimmingCharacters(in: .whitespaces))")
#endif
let modifiers = NSEvent.modifierFlags
let modifiers = modifierFlags
let isCommand = modifiers.contains(.command)
let isShift = modifiers.contains(.shift)

Expand Down Expand Up @@ -7310,8 +7316,12 @@
}

private func openPullRequestLink(_ url: URL) {
updateSelection()
if openSidebarPullRequestLinksInCmuxBrowser {
let openModifierFlags = NSEvent.modifierFlags
updateSelection(modifierFlags: [])
let shouldOpenInCmuxBrowser = BrowserLinkOpenSettings.shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: openModifierFlags
)
if shouldOpenInCmuxBrowser {
if tabManager.openBrowser(
inWorkspace: tab.id,
url: url,
Expand Down Expand Up @@ -7748,7 +7758,7 @@
.contentShape(Rectangle())
.onTapGesture { onFocus() }
.onAppear(perform: renderMarkdown)
.onChange(of: block.markdown) { _ in

Check notice on line 7761 in Sources/ContentView.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/ContentView.swift#L7761

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
renderMarkdown()
}
}
Expand Down
72 changes: 72 additions & 0 deletions Sources/Panels/BrowserPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,43 @@
}
}

enum BrowserLinkModifierBehavior: String, CaseIterable, Identifiable {
case commandShiftOpensCmuxOptionShiftOpensDefault
case commandShiftOpensDefaultOptionShiftOpensCmux

var id: String { rawValue }

var displayName: String {
switch self {
case .commandShiftOpensCmuxOptionShiftOpensDefault:
return "Cmd+Shift -> cmux, Option+Shift -> Default"
case .commandShiftOpensDefaultOptionShiftOpensCmux:
return "Cmd+Shift -> Default, Option+Shift -> cmux"
}
}

var summary: String {
switch self {
case .commandShiftOpensCmuxOptionShiftOpensDefault:
return "Cmd+Shift forces cmux browser, Option+Shift forces your default browser."
case .commandShiftOpensDefaultOptionShiftOpensCmux:
return "Cmd+Shift forces your default browser, Option+Shift forces cmux browser."
}
}

func opensInCmuxBrowser(for modifierFlags: NSEvent.ModifierFlags) -> Bool? {
let normalizedFlags = modifierFlags.intersection([.command, .shift, .option, .control])
switch normalizedFlags {
case [.command, .shift]:
return self == .commandShiftOpensCmuxOptionShiftOpensDefault
case [.option, .shift]:
return self == .commandShiftOpensDefaultOptionShiftOpensCmux
default:
return nil
}
}
}

enum BrowserLinkOpenSettings {
static let openTerminalLinksInCmuxBrowserKey = "browserOpenTerminalLinksInCmuxBrowser"
static let defaultOpenTerminalLinksInCmuxBrowser: Bool = true
Expand All @@ -137,6 +174,9 @@
static let interceptTerminalOpenCommandInCmuxBrowserKey = "browserInterceptTerminalOpenCommandInCmuxBrowser"
static let defaultInterceptTerminalOpenCommandInCmuxBrowser: Bool = true

static let linkModifierBehaviorKey = "browserLinkModifierBehavior"
static let defaultLinkModifierBehavior: BrowserLinkModifierBehavior = .commandShiftOpensCmuxOptionShiftOpensDefault

static let browserHostWhitelistKey = "browserHostWhitelist"
static let defaultBrowserHostWhitelist: String = ""

Expand Down Expand Up @@ -171,6 +211,38 @@
interceptTerminalOpenCommandInCmuxBrowser(defaults: defaults)
}

static func linkModifierBehavior(for rawValue: String?) -> BrowserLinkModifierBehavior {
guard let rawValue,
let behavior = BrowserLinkModifierBehavior(rawValue: rawValue) else {
return defaultLinkModifierBehavior
}
return behavior
}

static func linkModifierBehavior(defaults: UserDefaults = .standard) -> BrowserLinkModifierBehavior {
linkModifierBehavior(for: defaults.string(forKey: linkModifierBehaviorKey))
}

static func linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: NSEvent.ModifierFlags,
defaults: UserDefaults = .standard
) -> Bool? {
linkModifierBehavior(defaults: defaults).opensInCmuxBrowser(for: modifierFlags)
}

static func shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: NSEvent.ModifierFlags,
defaults: UserDefaults = .standard
) -> Bool {
if let modifierOverride = linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: modifierFlags,
defaults: defaults
) {
return modifierOverride
}
return openSidebarPullRequestLinksInCmuxBrowser(defaults: defaults)
}

static func hostWhitelist(defaults: UserDefaults = .standard) -> [String] {
let raw = defaults.string(forKey: browserHostWhitelistKey) ?? defaultBrowserHostWhitelist
return raw
Expand Down Expand Up @@ -1117,7 +1189,7 @@
@MainActor
final class BrowserPanel: Panel, ObservableObject {
/// Shared process pool for cookie sharing across all browser panels
private static let sharedProcessPool = WKProcessPool()

Check notice on line 1192 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1192

'WKProcessPool' was deprecated in macOS 12.0: Creating and using multiple instances of WKProcessPool no longer has any effect.

static let telemetryHookBootstrapScriptSource = """
(() => {
Expand Down Expand Up @@ -1219,7 +1291,7 @@
}

private static func isDarkAppearance(
appAppearance: NSAppearance? = NSApp?.effectiveAppearance

Check notice on line 1294 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1294

Main actor-isolated property 'effectiveAppearance' can not be referenced from a nonisolated context

Check notice on line 1294 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1294

Main actor-isolated var 'NSApp' can not be referenced from a nonisolated context
) -> Bool {
guard let appAppearance else { return false }
return appAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua
Expand All @@ -1244,7 +1316,7 @@

private static func resolvedBrowserChromeBackgroundColor(
from notification: Notification? = nil,
appAppearance: NSAppearance? = NSApp?.effectiveAppearance

Check notice on line 1319 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1319

Main actor-isolated property 'effectiveAppearance' can not be referenced from a nonisolated context

Check notice on line 1319 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1319

Main actor-isolated var 'NSApp' can not be referenced from a nonisolated context
) -> NSColor {
if isDarkAppearance(appAppearance: appAppearance) {
return resolvedGhosttyBackgroundColor(from: notification)
Expand Down Expand Up @@ -1375,7 +1447,7 @@

// Configure web view
let config = WKWebViewConfiguration()
config.processPool = BrowserPanel.sharedProcessPool

Check notice on line 1450 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1450

'processPool' was deprecated in macOS 12.0: Creating and using multiple instances of WKProcessPool no longer has any effect.
// Ensure browser cookies/storage persist across navigations and launches.
// This reduces repeated consent/bot-challenge flows on sites like Google.
config.websiteDataStore = .default()
Expand Down Expand Up @@ -1500,7 +1572,7 @@
if Thread.isMainThread {
apply()
} else {
DispatchQueue.main.async(execute: apply)

Check notice on line 1575 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1575

Converting non-Sendable function value to '@mainactor @sendable @convention(block) () -> Void' may introduce data races
}
}

Expand All @@ -1512,7 +1584,7 @@
if Thread.isMainThread {
apply()
} else {
DispatchQueue.main.async(execute: apply)

Check notice on line 1587 in Sources/Panels/BrowserPanel.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/Panels/BrowserPanel.swift#L1587

Converting non-Sendable function value to '@mainactor @sendable @convention(block) () -> Void' may introduce data races
}
}

Expand Down
33 changes: 33 additions & 0 deletions Sources/cmuxApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,10 @@
}
}
}
.onChange(of: appearanceMode) { _ in

Check notice on line 205 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L205

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
applyAppearance()
}
.onChange(of: socketControlMode) { _ in

Check notice on line 208 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L208

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
updateSocketController()
}
}
Expand Down Expand Up @@ -1941,7 +1941,7 @@
Text(option.title).tag(option.rawValue)
}
}
.onChange(of: sidebarPreset) { _ in

Check notice on line 1944 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L1944

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
applyPreset()
}
.padding(.top, 2)
Expand Down Expand Up @@ -2297,19 +2297,19 @@
.frame(maxWidth: .infinity, alignment: .topLeading)
}
.onAppear { applyLiveUpdate() }
.onChange(of: previewEnabled) { _ in applyLiveUpdate() }

Check notice on line 2300 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2300

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: previewCount) { _ in applyLiveUpdate() }

Check notice on line 2301 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2301

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: badgeRectX) { _ in applyLiveUpdate() }

Check notice on line 2302 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2302

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: badgeRectY) { _ in applyLiveUpdate() }

Check notice on line 2303 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2303

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: badgeRectWidth) { _ in applyLiveUpdate() }

Check notice on line 2304 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2304

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: badgeRectHeight) { _ in applyLiveUpdate() }

Check notice on line 2305 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2305

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: singleDigitFontSize) { _ in applyLiveUpdate() }

Check notice on line 2306 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2306

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: multiDigitFontSize) { _ in applyLiveUpdate() }

Check notice on line 2307 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2307

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: singleDigitXAdjust) { _ in applyLiveUpdate() }

Check notice on line 2308 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2308

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: multiDigitXAdjust) { _ in applyLiveUpdate() }

Check notice on line 2309 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2309

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: singleDigitYOffset) { _ in applyLiveUpdate() }

Check notice on line 2310 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2310

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: multiDigitYOffset) { _ in applyLiveUpdate() }

Check notice on line 2311 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2311

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: textRectWidthAdjust) { _ in applyLiveUpdate() }

Check notice on line 2312 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2312

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
}

private func sliderRow(
Expand Down Expand Up @@ -2437,8 +2437,8 @@
.padding(16)
.frame(maxWidth: .infinity, alignment: .topLeading)
}
.onChange(of: bgGlassTintHex) { _ in updateWindowGlassTint() }

Check notice on line 2440 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2440

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
.onChange(of: bgGlassTintOpacity) { _ in updateWindowGlassTint() }

Check notice on line 2441 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L2441

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
}

private func updateWindowGlassTint() {
Expand Down Expand Up @@ -2674,6 +2674,8 @@
@AppStorage(BrowserLinkOpenSettings.openTerminalLinksInCmuxBrowserKey) private var openTerminalLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenTerminalLinksInCmuxBrowser
@AppStorage(BrowserLinkOpenSettings.interceptTerminalOpenCommandInCmuxBrowserKey)
private var interceptTerminalOpenCommandInCmuxBrowser = BrowserLinkOpenSettings.initialInterceptTerminalOpenCommandInCmuxBrowserValue()
@AppStorage(BrowserLinkOpenSettings.linkModifierBehaviorKey)
private var linkModifierBehavior = BrowserLinkOpenSettings.defaultLinkModifierBehavior.rawValue
@AppStorage(BrowserLinkOpenSettings.browserHostWhitelistKey) private var browserHostWhitelist = BrowserLinkOpenSettings.defaultBrowserHostWhitelist
@AppStorage(BrowserInsecureHTTPSettings.allowlistKey) private var browserInsecureHTTPAllowlist = BrowserInsecureHTTPSettings.defaultAllowlistText
@AppStorage(NotificationBadgeSettings.dockBadgeEnabledKey) private var notificationDockBadgeEnabled = NotificationBadgeSettings.defaultDockBadgeEnabled
Expand Down Expand Up @@ -2741,6 +2743,19 @@
)
}

private var selectedLinkModifierBehavior: BrowserLinkModifierBehavior {
BrowserLinkOpenSettings.linkModifierBehavior(for: linkModifierBehavior)
}

private var linkModifierBehaviorSelection: Binding<String> {
Binding(
get: { selectedLinkModifierBehavior.rawValue },
set: { newValue in
linkModifierBehavior = BrowserLinkOpenSettings.linkModifierBehavior(for: newValue).rawValue
}
)
}

private var socketModeSelection: Binding<String> {
Binding(
get: { socketControlMode },
Expand Down Expand Up @@ -2962,6 +2977,22 @@

SettingsCardDivider()

SettingsCardRow(
"Sidebar PR Link Modifier Override",
subtitle: selectedLinkModifierBehavior.summary,
controlWidth: pickerColumnWidth
) {
Picker("", selection: linkModifierBehaviorSelection) {
ForEach(BrowserLinkModifierBehavior.allCases) { behavior in
Text(behavior.displayName).tag(behavior.rawValue)
}
}
.labelsHidden()
.pickerStyle(.menu)
}

SettingsCardDivider()

SettingsCardRow(
"Show Listening Ports in Sidebar",
subtitle: "Display detected listening ports for the active workspace."
Expand Down Expand Up @@ -3479,6 +3510,7 @@
.onAppear {
BrowserHistoryStore.shared.loadIfNeeded()
browserThemeMode = BrowserThemeSettings.mode(defaults: .standard).rawValue
linkModifierBehavior = BrowserLinkOpenSettings.linkModifierBehavior(defaults: .standard).rawValue
browserHistoryEntryCount = BrowserHistoryStore.shared.entries.count
browserInsecureHTTPAllowlistDraft = browserInsecureHTTPAllowlist
reloadWorkspaceTabColorSettings()
Expand Down Expand Up @@ -3534,6 +3566,7 @@
browserThemeMode = BrowserThemeSettings.defaultMode.rawValue
openTerminalLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenTerminalLinksInCmuxBrowser
interceptTerminalOpenCommandInCmuxBrowser = BrowserLinkOpenSettings.defaultInterceptTerminalOpenCommandInCmuxBrowser
linkModifierBehavior = BrowserLinkOpenSettings.defaultLinkModifierBehavior.rawValue
browserHostWhitelist = BrowserLinkOpenSettings.defaultBrowserHostWhitelist
browserInsecureHTTPAllowlist = BrowserInsecureHTTPSettings.defaultAllowlistText
browserInsecureHTTPAllowlistDraft = BrowserInsecureHTTPSettings.defaultAllowlistText
Expand Down Expand Up @@ -3751,7 +3784,7 @@

var body: some View {
KeyboardShortcutRecorder(label: action.label, shortcut: $shortcut)
.onChange(of: shortcut) { newValue in

Check notice on line 3787 in Sources/cmuxApp.swift

View check run for this annotation

Xcode Cloud / cmux | UI tests | Test - macOS

Sources/cmuxApp.swift#L3787

'onChange(of:perform:)' was deprecated in macOS 14.0: Use `onChange` with a two or zero parameter action closure instead.
KeyboardShortcutSettings.setShortcut(newValue, for: action)
}
.onReceive(NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification)) { _ in
Expand Down
123 changes: 123 additions & 0 deletions cmuxTests/CmuxWebViewKeyEquivalentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7636,6 +7636,129 @@ final class BrowserLinkOpenSettingsTests: XCTestCase {
defaults.set(true, forKey: BrowserLinkOpenSettings.openTerminalLinksInCmuxBrowserKey)
XCTAssertTrue(BrowserLinkOpenSettings.initialInterceptTerminalOpenCommandInCmuxBrowserValue(defaults: defaults))
}

func testLinkModifierBehaviorDefaultsToCommandShiftCmux() {
XCTAssertEqual(
BrowserLinkOpenSettings.linkModifierBehavior(defaults: defaults),
.commandShiftOpensCmuxOptionShiftOpensDefault
)
}

func testLinkModifierBehaviorUsesStoredValue() {
defaults.set(
BrowserLinkModifierBehavior.commandShiftOpensDefaultOptionShiftOpensCmux.rawValue,
forKey: BrowserLinkOpenSettings.linkModifierBehaviorKey
)
XCTAssertEqual(
BrowserLinkOpenSettings.linkModifierBehavior(defaults: defaults),
.commandShiftOpensDefaultOptionShiftOpensCmux
)
}

func testLinkModifierOverrideMatchesConfiguredBehavior() {
defaults.set(
BrowserLinkModifierBehavior.commandShiftOpensCmuxOptionShiftOpensDefault.rawValue,
forKey: BrowserLinkOpenSettings.linkModifierBehaviorKey
)
XCTAssertEqual(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.command, .shift],
defaults: defaults
),
true
)
XCTAssertEqual(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.option, .shift],
defaults: defaults
),
false
)

defaults.set(
BrowserLinkModifierBehavior.commandShiftOpensDefaultOptionShiftOpensCmux.rawValue,
forKey: BrowserLinkOpenSettings.linkModifierBehaviorKey
)
XCTAssertEqual(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.command, .shift],
defaults: defaults
),
false
)
XCTAssertEqual(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.option, .shift],
defaults: defaults
),
true
)
}

func testLinkModifierOverrideIgnoresUnconfiguredModifierSets() {
XCTAssertNil(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.shift],
defaults: defaults
)
)
XCTAssertNil(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.command],
defaults: defaults
)
)
XCTAssertNil(
BrowserLinkOpenSettings.linkModifierOverrideOpensInCmuxBrowser(
modifierFlags: [.command, .shift, .control],
defaults: defaults
)
)
}

func testShouldOpenSidebarPullRequestLinkInCmuxBrowserFallsBackToToggleWhenNoOverrideModifier() {
defaults.set(false, forKey: BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
XCTAssertFalse(
BrowserLinkOpenSettings.shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: [],
defaults: defaults
)
)

defaults.set(true, forKey: BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
XCTAssertTrue(
BrowserLinkOpenSettings.shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: [],
defaults: defaults
)
)
}

func testShouldOpenSidebarPullRequestLinkInCmuxBrowserUsesModifierOverride() {
defaults.set(false, forKey: BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
defaults.set(
BrowserLinkModifierBehavior.commandShiftOpensCmuxOptionShiftOpensDefault.rawValue,
forKey: BrowserLinkOpenSettings.linkModifierBehaviorKey
)
XCTAssertTrue(
BrowserLinkOpenSettings.shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: [.command, .shift],
defaults: defaults
)
)

defaults.set(true, forKey: BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
defaults.set(
BrowserLinkModifierBehavior.commandShiftOpensDefaultOptionShiftOpensCmux.rawValue,
forKey: BrowserLinkOpenSettings.linkModifierBehaviorKey
)
XCTAssertFalse(
BrowserLinkOpenSettings.shouldOpenSidebarPullRequestLinkInCmuxBrowser(
modifierFlags: [.command, .shift],
defaults: defaults
)
)
}
}

final class TerminalOpenURLTargetResolutionTests: XCTestCase {
Expand Down