fix(sidebar): use dedicated setting for port link browser preference (#2219)

Port links were reusing the PR-link preference
(openSidebarPullRequestLinksInCmuxBrowser), causing inconsistent
behavior when users toggled that setting. Adds a dedicated
openSidebarPortLinksInCmuxBrowser setting with its own toggle in
Settings so port and PR link behavior can be controlled independently.

Addresses review feedback from https://github.com/manaflow-ai/cmux/pull/1844

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
Lawrence Chen 2026-03-26 17:12:37 -07:00 committed by GitHub
parent 84af32c56e
commit 1b03d23fee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 369 additions and 1 deletions

View file

@ -44923,6 +44923,345 @@
}
}
},
"settings.app.openSidebarPortLinks": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Open Sidebar Port Links in cmux Browser"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "サイドバーのポートリンクをcmuxブラウザで開く"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "在 cmux 浏览器中打开侧边栏端口链接"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "在 cmux 瀏覽器中開啟側邊欄連接埠連結"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "사이드바 포트 링크를 cmux 브라우저에서 열기"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Seitenleisten-Port-Links im cmux-Browser öffnen"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Abrir enlaces de puerto de la barra lateral en el navegador de cmux"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Ouvrir les liens de port de la barre latérale dans le navigateur cmux"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "Apri link delle porte della barra laterale nel browser cmux"
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "Åbn sidebjælkens portlinks i cmux-browser"
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Otwieraj linki portów z paska bocznego w przeglądarce cmux"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Открывать ссылки портов боковой панели в браузере cmux"
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "Otvori port linkove iz bočne trake u cmux pregledniku"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "فتح روابط المنافذ في متصفح cmux"
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "Åpne sidepanel-portlenker i cmux-nettleser"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Abrir Links de Porta da Barra Lateral no Navegador do cmux"
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "เปิดลิงก์พอร์ตในแถบด้านข้างด้วยเบราว์เซอร์ cmux"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "Kenar Çubuğu Port Bağlantılarını cmux Tarayıcısında Aç"
}
}
}
},
"settings.app.openSidebarPortLinks.subtitleOff": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Port clicks open in your default browser."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ポートをクリックするとデフォルトブラウザで開きます。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "端口点击在默认浏览器中打开。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "連接埠點擊會在您的預設瀏覽器中開啟。"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "포트를 클릭하면 기본 브라우저에서 열립니다."
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Port-Klicks öffnen in Ihrem Standardbrowser."
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Los clics en puertos abren en tu navegador predeterminado."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Les clics de port ouvrent dans votre navigateur par défaut."
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "I clic sulle porte aprono nel browser predefinito."
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "Portklik åbner i din standardbrowser."
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Kliknięcia portów otwierają w domyślnej przeglądarce."
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Ссылки портов открываются в браузере по умолчанию."
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "Klikovi na portove se otvaraju u podrazumijevanom pregledniku."
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "نقرات المنافذ تفتح في متصفحك الافتراضي."
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "Portklikk åpner i standard nettleser."
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Cliques em portas abrem no seu navegador padrão."
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "คลิกพอร์ตจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "Port tıklamaları varsayılan tarayıcınızda açılır."
}
}
}
},
"settings.app.openSidebarPortLinks.subtitleOn": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Port clicks open inside cmux browser."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ポートをクリックするとcmuxブラウザ内で開きます。"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "端口点击在 cmux 浏览器中打开。"
}
},
"zh-Hant": {
"stringUnit": {
"state": "translated",
"value": "連接埠點擊會在 cmux 瀏覽器中開啟。"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "포트를 클릭하면 cmux 브라우저에서 열립니다."
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "Port-Klicks öffnen im cmux-Browser."
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Los clics en puertos abren dentro del navegador de cmux."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Les clics de port ouvrent dans le navigateur cmux."
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "I clic sulle porte aprono nel browser cmux."
}
},
"da": {
"stringUnit": {
"state": "translated",
"value": "Portklik åbner i cmux-browseren."
}
},
"pl": {
"stringUnit": {
"state": "translated",
"value": "Kliknięcia portów otwierają w przeglądarce cmux."
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "Ссылки портов открываются во встроенном браузере cmux."
}
},
"bs": {
"stringUnit": {
"state": "translated",
"value": "Klikovi na portove se otvaraju unutar cmux preglednika."
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "نقرات المنافذ تفتح داخل متصفح cmux."
}
},
"nb": {
"stringUnit": {
"state": "translated",
"value": "Portklikk åpner i cmux-nettleseren."
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "Cliques em portas abrem dentro do navegador do cmux."
}
},
"th": {
"stringUnit": {
"state": "translated",
"value": "คลิกพอร์ตจะเปิดในเบราว์เซอร์ cmux"
}
},
"tr": {
"stringUnit": {
"state": "translated",
"value": "Port tıklamaları cmux tarayıcısında açılır."
}
}
}
},
"settings.app.hideAllSidebarDetails": {
"extractionState": "manual",
"localizations": {

View file

@ -11015,6 +11015,8 @@ private struct TabItemView: View, Equatable {
@AppStorage("sidebarShowPullRequest") private var sidebarShowPullRequest = true
@AppStorage(BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
private var openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser
@AppStorage(BrowserLinkOpenSettings.openSidebarPortLinksInCmuxBrowserKey)
private var openSidebarPortLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPortLinksInCmuxBrowser
@AppStorage("sidebarShowSSH") private var sidebarShowSSH = true
@AppStorage("sidebarShowPorts") private var sidebarShowPorts = true
@AppStorage("sidebarShowLog") private var sidebarShowLog = true
@ -12220,7 +12222,7 @@ private struct TabItemView: View, Equatable {
private func openPortLink(_ port: Int) {
guard let url = URL(string: "http://localhost:\(port)") else { return }
updateSelection()
if openSidebarPullRequestLinksInCmuxBrowser {
if openSidebarPortLinksInCmuxBrowser {
if tabManager.openBrowser(
inWorkspace: tab.id,
url: url,

View file

@ -527,6 +527,9 @@ enum BrowserLinkOpenSettings {
static let openSidebarPullRequestLinksInCmuxBrowserKey = "browserOpenSidebarPullRequestLinksInCmuxBrowser"
static let defaultOpenSidebarPullRequestLinksInCmuxBrowser: Bool = true
static let openSidebarPortLinksInCmuxBrowserKey = "browserOpenSidebarPortLinksInCmuxBrowser"
static let defaultOpenSidebarPortLinksInCmuxBrowser: Bool = true
static let interceptTerminalOpenCommandInCmuxBrowserKey = "browserInterceptTerminalOpenCommandInCmuxBrowser"
static let defaultInterceptTerminalOpenCommandInCmuxBrowser: Bool = true
@ -549,6 +552,13 @@ enum BrowserLinkOpenSettings {
return defaults.bool(forKey: openSidebarPullRequestLinksInCmuxBrowserKey)
}
static func openSidebarPortLinksInCmuxBrowser(defaults: UserDefaults = .standard) -> Bool {
if defaults.object(forKey: openSidebarPortLinksInCmuxBrowserKey) == nil {
return defaultOpenSidebarPortLinksInCmuxBrowser
}
return defaults.bool(forKey: openSidebarPortLinksInCmuxBrowserKey)
}
static func interceptTerminalOpenCommandInCmuxBrowser(defaults: UserDefaults = .standard) -> Bool {
if defaults.object(forKey: interceptTerminalOpenCommandInCmuxBrowserKey) != nil {
return defaults.bool(forKey: interceptTerminalOpenCommandInCmuxBrowserKey)

View file

@ -3861,6 +3861,8 @@ struct SettingsView: View {
@AppStorage("sidebarShowPullRequest") private var sidebarShowPullRequest = true
@AppStorage(BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey)
private var openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser
@AppStorage(BrowserLinkOpenSettings.openSidebarPortLinksInCmuxBrowserKey)
private var openSidebarPortLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPortLinksInCmuxBrowser
@AppStorage(ShortcutHintDebugSettings.showHintsOnCommandHoldKey)
private var showShortcutHintsOnCommandHold = ShortcutHintDebugSettings.defaultShowHintsOnCommandHold
@AppStorage("sidebarShowSSH") private var sidebarShowSSH = true
@ -4748,6 +4750,20 @@ struct SettingsView: View {
SettingsCardDivider()
SettingsCardRow(
String(localized: "settings.app.openSidebarPortLinks", defaultValue: "Open Sidebar Port Links in cmux Browser"),
subtitle: openSidebarPortLinksInCmuxBrowser
? String(localized: "settings.app.openSidebarPortLinks.subtitleOn", defaultValue: "Port clicks open inside cmux browser.")
: String(localized: "settings.app.openSidebarPortLinks.subtitleOff", defaultValue: "Port clicks open in your default browser.")
) {
Toggle("", isOn: $openSidebarPortLinksInCmuxBrowser)
.labelsHidden()
.controlSize(.small)
}
.disabled(sidebarHideAllDetails)
SettingsCardDivider()
SettingsCardRow(
String(localized: "settings.app.showSSH", defaultValue: "Show SSH in Sidebar"),
subtitle: String(localized: "settings.app.showSSH.subtitle", defaultValue: "Display the SSH target for remote workspaces in its own row.")
@ -5647,6 +5663,7 @@ struct SettingsView: View {
sidebarShowBranchDirectory = true
sidebarShowPullRequest = true
openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser
openSidebarPortLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPortLinksInCmuxBrowser
showShortcutHintsOnCommandHold = ShortcutHintDebugSettings.defaultShowHintsOnCommandHold
sidebarShowSSH = true
sidebarShowPorts = true