Skip to content
Merged
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
102 changes: 102 additions & 0 deletions Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -87391,6 +87391,108 @@
}
}
}
},
"contextMenu.workspaceSettings": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Workspace Settings"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ワークスペース設定"
}
}
}
},
"contextMenu.workspaceSettings.hideTerminalScrollBar": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Hide Terminal Scroll Bar"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ターミナルのスクロールバーを隠す"
}
}
}
},
"settings.section.terminal": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Terminal"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ターミナル"
}
}
}
},
"settings.terminal.scrollBar": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Show Terminal Scroll Bar"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ターミナルのスクロールバーを表示"
}
}
}
},
"settings.terminal.scrollBar.subtitleOff": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Hides the right-edge terminal scroll bar everywhere. Changes apply immediately and persist across relaunches."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "右端のターミナルスクロールバーを全体で非表示にします。変更はすぐに反映され、再起動後も保持されます。"
}
}
}
},
"settings.terminal.scrollBar.subtitleOn": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Shows the right-edge terminal scroll bar in shell scrollback. cmux hides it automatically for alternate-screen style TUI surfaces and you can also disable it per workspace."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "シェルのスクロールバックでは右端のターミナルスクロールバーを表示します。cmux は代替画面系の TUI では自動的に隠し、ワークスペースごとにも無効化できます。"
}
}
}
}
}
}
1 change: 0 additions & 1 deletion Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5810,7 +5810,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
var refreshedCount = 0
forEachTerminalPanel { terminalPanel in
terminalPanel.hostedView.refreshHostBackgroundAfterGhosttyConfigReload()
terminalPanel.hostedView.reconcileGeometryNow()
terminalPanel.surface.forceRefresh(reason: "appDelegate.refreshAfterGhosttyConfigReload")
refreshedCount += 1
}
Expand Down
49 changes: 49 additions & 0 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9910,6 +9910,7 @@ struct VerticalTabsSidebar: View {
@State private var draggedTabId: UUID?
@State private var dropIndicator: SidebarDropIndicator?
@State private var frozenTabItemPresentation: SidebarTabItemPresentationSnapshot?
@State private var terminalScrollBarVisibilityGeneration: UInt64 = 0
@AppStorage(WorkspacePresentationModeSettings.modeKey)
private var workspacePresentationMode = WorkspacePresentationModeSettings.defaultMode.rawValue

Expand All @@ -9932,6 +9933,7 @@ struct VerticalTabsSidebar: View {
}

var body: some View {
let _ = terminalScrollBarVisibilityGeneration
let tabs = tabManager.tabs
let workspaceCount = tabs.count
let canCloseWorkspace = workspaceCount > 1
Expand All @@ -9944,6 +9946,9 @@ struct VerticalTabsSidebar: View {
let selectedContextTargetIds = orderedSelectedTabs.map(\.id)
let selectedRemoteContextMenuTargets = orderedSelectedTabs.filter { $0.isRemoteWorkspace }
let selectedRemoteContextMenuWorkspaceIds = selectedRemoteContextMenuTargets.map(\.id)
let workspaceTerminalScrollBarHiddenById = Dictionary(
uniqueKeysWithValues: tabs.map { ($0.id, $0.terminalScrollBarHidden) }
)
let allSelectedRemoteContextMenuTargetsConnecting = !selectedRemoteContextMenuTargets.isEmpty &&
selectedRemoteContextMenuTargets.allSatisfy { $0.remoteConnectionState == .connecting }
let allSelectedRemoteContextMenuTargetsDisconnected = !selectedRemoteContextMenuTargets.isEmpty &&
Expand Down Expand Up @@ -9975,6 +9980,10 @@ struct VerticalTabsSidebar: View {
let allRemoteContextMenuTargetsDisconnected = usesSelectedContextMenuTargets
? allSelectedRemoteContextMenuTargetsDisconnected
: (tab.isRemoteWorkspace && tab.remoteConnectionState == .disconnected)
let allContextMenuWorkspacesHideTerminalScrollBar = !contextMenuWorkspaceIds.isEmpty &&
contextMenuWorkspaceIds.allSatisfy { workspaceId in
workspaceTerminalScrollBarHiddenById[workspaceId] == true
}
let liveUnreadCount = notificationStore.unreadCount(forTabId: tab.id)
let liveLatestNotificationText: String? = {
guard showsSidebarNotificationMessage,
Expand Down Expand Up @@ -10022,6 +10031,7 @@ struct VerticalTabsSidebar: View {
remoteContextMenuWorkspaceIds: remoteContextMenuWorkspaceIds,
allRemoteContextMenuTargetsConnecting: allRemoteContextMenuTargetsConnecting,
allRemoteContextMenuTargetsDisconnected: allRemoteContextMenuTargetsDisconnected,
allContextMenuWorkspacesHideTerminalScrollBar: allContextMenuWorkspacesHideTerminalScrollBar,
settings: tabItemSettings,
livePresentation: livePresentation,
frozenPresentation: $frozenTabItemPresentation
Expand Down Expand Up @@ -10138,6 +10148,19 @@ struct VerticalTabsSidebar: View {
#endif
draggedTabId = nil
}
.onReceive(
NotificationCenter.default.publisher(for: Workspace.terminalScrollBarHiddenDidChangeNotification)
.receive(on: RunLoop.main)
) { notification in
guard let workspace = notification.object as? Workspace,
tabManager.tabs.contains(where: { $0 === workspace }) else {
return
}

// Workspace scrollbar visibility changes do not publish on TabManager.tabs,
// so bump a local generation to refresh the precomputed context-menu state.
terminalScrollBarVisibilityGeneration &+= 1
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
}

Expand Down Expand Up @@ -12430,6 +12453,7 @@ private struct TabItemView: View, Equatable {
lhs.remoteContextMenuWorkspaceIds == rhs.remoteContextMenuWorkspaceIds &&
lhs.allRemoteContextMenuTargetsConnecting == rhs.allRemoteContextMenuTargetsConnecting &&
lhs.allRemoteContextMenuTargetsDisconnected == rhs.allRemoteContextMenuTargetsDisconnected &&
lhs.allContextMenuWorkspacesHideTerminalScrollBar == rhs.allContextMenuWorkspacesHideTerminalScrollBar &&
lhs.settings == rhs.settings
}

Expand Down Expand Up @@ -12460,6 +12484,7 @@ private struct TabItemView: View, Equatable {
let remoteContextMenuWorkspaceIds: [UUID]
let allRemoteContextMenuTargetsConnecting: Bool
let allRemoteContextMenuTargetsDisconnected: Bool
let allContextMenuWorkspacesHideTerminalScrollBar: Bool
let settings: SidebarTabItemSettingsSnapshot
let livePresentation: SidebarTabItemPresentationSnapshot
@Binding var frozenPresentation: SidebarTabItemPresentationSnapshot?
Expand Down Expand Up @@ -13275,6 +13300,20 @@ private struct TabItemView: View, Equatable {
.disabled(allRemoteContextMenuTargetsDisconnected)
}

Menu(String(localized: "contextMenu.workspaceSettings", defaultValue: "Workspace Settings")) {
Button {
toggleWorkspaceTerminalScrollBarHidden(targetIds: targetIds)
} label: {
Label {
Text(String(localized: "contextMenu.workspaceSettings.hideTerminalScrollBar", defaultValue: "Hide Terminal Scroll Bar"))
} icon: {
if allContextMenuWorkspacesHideTerminalScrollBar {
Image(systemName: "checkmark")
}
}
}
}

Menu(String(localized: "contextMenu.workspaceColor", defaultValue: "Workspace Color")) {
if tab.customColor != nil {
Button {
Expand Down Expand Up @@ -13978,6 +14017,16 @@ private struct TabItemView: View, Equatable {
}
}

private func toggleWorkspaceTerminalScrollBarHidden(targetIds: [UUID]) {
let currentlyHidden = !targetIds.isEmpty && targetIds.allSatisfy { targetId in
tabManager.tabs.first(where: { $0.id == targetId })?.terminalScrollBarHidden == true
}
let hideScrollBar = !currentlyHidden
for targetId in targetIds {
tabManager.setWorkspaceTerminalScrollBarHidden(tabId: targetId, hidden: hideScrollBar)
}
}

private func promptCustomColor(targetIds: [UUID]) {
let alert = NSAlert()
alert.messageText = String(localized: "alert.customColor.title", defaultValue: "Custom Workspace Color")
Expand Down
Loading
Loading