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
4 changes: 2 additions & 2 deletions .github/swift-file-length-budget.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@
756 Sources/Panels/AgentSessionWebRendererCoordinator.swift
754 Sources/TerminalController+ControlWorkspaceContext.swift
752 cmuxUITests/CloseWorkspaceCmdDUITests.swift
743 Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift
739 cmuxTests/CLICodexHookTimeoutRegressionTests.swift
738 Packages/macOS/CMUXProjectModel/Sources/CMUXProjectModel/XcodeProjectAdapter.swift
734 Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift
718 Packages/Shared/CmuxAuthRuntime/Sources/CmuxAuthRuntime/Coordinator/AuthCoordinator.swift
716 Sources/TaskManagerSnapshot.swift
715 Sources/AppleScriptSupport.swift
Expand Down Expand Up @@ -228,10 +228,10 @@
519 Sources/CmuxConfigExecutor.swift
518 Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/CMUXMobileRootView.swift
518 Packages/macOS/CmuxSwiftRender/Tests/CmuxSwiftRenderTests/Corpus/stress-git-review-queue-command-deck.swift
516 Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Transcript/ChatTranscriptTableView.swift
516 Sources/TerminalImageTransfer.swift
514 Packages/macOS/CmuxSwiftRender/Sources/CmuxSwiftRender/ExpressionEvaluator.swift
514 cmuxUITests/UpdatePillUITests.swift
513 Packages/iOS/CmuxAgentChatUI/Sources/CmuxAgentChatUI/Transcript/ChatTranscriptTableView.swift
509 Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizerAdditionalPolicies.swift
507 Sources/TerminalControllerTopSupport.swift
506 Sources/App/MainWindowVisibilityController.swift
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#if DEBUG
import CmuxAgentChat
import CmuxAgentChatUI
import CmuxMobileShellModel
import CmuxMobileSupport
import Foundation
import SwiftUI
Expand Down Expand Up @@ -72,26 +73,13 @@ struct AgentChatDemoScreen: View {
ToolbarSpacer(.fixed, placement: .topBarLeading)
}
ToolbarItem(placement: .topBarLeading) {
Menu {
Button(L10n.string("mobile.workspace.rename.title", defaultValue: "Rename Workspace")) {}
.accessibilityIdentifier("MobileWorkspaceTitleRenameMenuItem")
Button(L10n.string("mobile.workspace.markRead", defaultValue: "Mark as Read")) {}
.accessibilityIdentifier("MobileWorkspaceTitleMarkReadMenuItem")
} label: {
WorkspaceToolbarTitleControl(
contentWidth: contentWidth,
hasBackButton: true,
hasChatToggle: true
) {
header(for: stack)
.frame(
minWidth: MobileNavTitleWidth.floor,
maxWidth: MobileNavTitleWidth(
contentWidth: contentWidth,
hasBackButton: true,
hasChatToggle: true
).leadingCap,
alignment: .leading
)
.layoutPriority(1)
}
.mobileGlassCompactToolbarControl()
.accessibilityIdentifier("MobileWorkspaceTitleMenu")
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
Expand All @@ -103,9 +91,32 @@ struct AgentChatDemoScreen: View {
Image(systemName: "bubble.left.and.bubble.right.fill")
}
.accessibilityIdentifier("AgentChatInlinePreviewChatToggle")
Button(action: {}) {
Image(systemName: "rectangle.stack")
Menu {
WorkspaceTitleMenuContent(
workspace: inlinePreviewWorkspace,
canCloseWorkspace: true,
presentRename: {},
toggleReadState: {},
requestClose: {}
)

Section {
Button {} label: {
Label(
L10n.string("mobile.terminal.new", defaultValue: "New Terminal"),
systemImage: "plus"
)
}
.accessibilityIdentifier("MobileNewTerminalMenuItem")
}
} label: {
Label(
L10n.string("mobile.terminal.picker.menuTitle", defaultValue: "Workspace and Terminals"),
systemImage: "rectangle.stack"
)
.labelStyle(.iconOnly)
}
.accessibilityLabel(L10n.string("mobile.terminal.picker.menuTitle", defaultValue: "Workspace and Terminals"))
.accessibilityIdentifier("AgentChatInlinePreviewTerminalPicker")
}
}
Expand Down Expand Up @@ -139,6 +150,28 @@ struct AgentChatDemoScreen: View {
) ?? "cmux"
}

private var inlinePreviewWorkspace: MobileWorkspacePreview {
var workspace = MobileWorkspacePreview(
id: "inline-preview-workspace",
name: inlineWorkspaceTitle ?? "cmux",
hasUnread: true,
terminals: [
MobileTerminalPreview(
id: "inline-preview-terminal",
name: inlineWorkspaceSubtitle
?? L10n.string("mobile.terminal.select", defaultValue: "Terminal"),
isFocused: true
),
]
)
workspace.actionCapabilities = MobileWorkspaceActionCapabilities(
supportsWorkspaceActions: true,
supportsReadStateActions: true,
supportsCloseActions: true
)
return workspace
}

private var inlineWorkspaceSubtitle: String? {
guard style == .inlineWorkspace else { return nil }
return UITestConfig.value(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import UIKit
/// The agent chat rendered inline in the workspace detail, in place of the
/// terminal, when chat mode is toggled on. There is no cover and no Done
/// button: the same toolbar toggle flips back to the terminal.
struct WorkspaceChatPane<TitleMenuContent: View>: View {
struct WorkspaceChatPane: View {
let session: ChatSessionDescriptor
let conversation: ChatConversationStore
let store: CMUXMobileShellStore
Expand All @@ -28,8 +28,6 @@ struct WorkspaceChatPane<TitleMenuContent: View>: View {
/// Compact-stack back button owned by the workspace toolbar, colocated with
/// the leading title so their order is deterministic.
let backButtonConfiguration: WorkspaceBackButtonConfiguration?
/// Workspace-scoped actions exposed from the title pill.
let titleMenuContent: () -> TitleMenuContent
/// Flips chat mode off (the toggle's "back to terminal" path).
let onExitChat: () -> Void

Expand Down Expand Up @@ -60,9 +58,11 @@ struct WorkspaceChatPane<TitleMenuContent: View>: View {
ToolbarItem(placement: .topBarLeading) {
HStack(spacing: 8) {
workspaceBackToolbarButton
Menu {
titleMenuContent()
} label: {
WorkspaceToolbarTitleControl(
contentWidth: contentWidth,
hasBackButton: backButtonConfiguration != nil,
hasChatToggle: true
) {
ChatSessionHeaderView(
descriptor: conversation.descriptor,
agentState: conversation.agentState,
Expand All @@ -71,19 +71,7 @@ struct WorkspaceChatPane<TitleMenuContent: View>: View {
subtitle: tabName,
style: .toolbarCompact
)
.frame(
minWidth: MobileNavTitleWidth.floor,
maxWidth: MobileNavTitleWidth(
contentWidth: contentWidth,
hasBackButton: backButtonConfiguration != nil,
hasChatToggle: true
).leadingCap,
alignment: .leading
)
.layoutPriority(1)
}
.mobileGlassCompactToolbarControl()
.accessibilityIdentifier("MobileWorkspaceTitleMenu")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ extension WorkspaceDetailView {
set: { chatDrafts[session.id] = $0 }
),
backButtonConfiguration: backButtonConfiguration,
titleMenuContent: { titleMenuContent },
onExitChat: {
withAnimation(.snappy(duration: 0.28)) {
isChatMode = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,10 @@ struct WorkspaceDetailView: View {
ToolbarItem(placement: .topBarLeading) {
HStack(spacing: 8) {
workspaceBackToolbarButton
WorkspaceTitleMenu(
WorkspaceToolbarTitleControl(
contentWidth: contentWidth,
hasBackButton: backButtonConfiguration != nil,
hasChatToggle: shouldShowChatToggle,
menuContent: { titleMenuContent }
hasChatToggle: shouldShowChatToggle
) {
Text(browser.title ?? workspace.name)
.font(.headline)
Expand Down Expand Up @@ -308,11 +307,10 @@ struct WorkspaceDetailView: View {
ToolbarItem(placement: .topBarLeading) {
HStack(spacing: 8) {
workspaceBackToolbarButton
WorkspaceTitleMenu(
WorkspaceToolbarTitleControl(
contentWidth: contentWidth,
hasBackButton: backButtonConfiguration != nil,
hasChatToggle: shouldShowChatToggle,
menuContent: { titleMenuContent }
hasChatToggle: shouldShowChatToggle
) {
WorkspaceToolbarTitleView(title: workspace.name, subtitle: selectedToolbarSubtitle)
}
Expand Down Expand Up @@ -403,13 +401,13 @@ struct WorkspaceDetailView: View {
terminalPickerMenuContent
} label: {
Label(
selectedTerminal?.name ?? L10n.string("mobile.terminal.select", defaultValue: "Terminal"),
L10n.string("mobile.terminal.picker.menuTitle", defaultValue: "Workspace and Terminals"),
systemImage: "rectangle.stack"
)
.labelStyle(.iconOnly)
}
.foregroundStyle(TerminalPalette.foreground)
.accessibilityLabel(L10n.string("mobile.terminal.picker.title", defaultValue: "Terminals"))
.accessibilityLabel(L10n.string("mobile.terminal.picker.menuTitle", defaultValue: "Workspace and Terminals"))
.accessibilityIdentifier("MobileTerminalDropdown")
.accessibilityValue(host)
}
Expand All @@ -432,6 +430,8 @@ struct WorkspaceDetailView: View {
}
}

titleMenuContent

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Section {
Button(action: createWorkspaceFromToolbar) {
Label(L10n.string("mobile.workspace.new", defaultValue: "New Workspace"), systemImage: "plus.square.on.square")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import CmuxMobileSupport
import SwiftUI

/// Rename-workspace dialog (an alert with an inline text field) shared by the
/// workspace detail view's title menu across the terminal / chat /
/// browser panes. Reuses the same strings as the workspace list's rename sheet so
/// both entrypoints read identically.
/// workspace detail view's picker menu across the terminal / chat / browser panes.
/// Reuses the same strings as the workspace list's rename sheet so both
/// entrypoints read identically.
extension View {
func workspaceRenameDialog(
isPresented: Binding<Bool>,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import CmuxMobileSupport
import SwiftUI

struct WorkspaceToolbarTitleControl<Label: View>: View {
let contentWidth: CGFloat
let hasBackButton: Bool
let hasChatToggle: Bool
@ViewBuilder let label: () -> Label

var body: some View {
fittedLabel
.mobileGlassCompactNavigationTitle()
.accessibilityIdentifier("MobileWorkspaceTitleMenu")
}

private var fittedLabel: some View {
label()
.frame(
minWidth: MobileNavTitleWidth.floor,
maxWidth: MobileNavTitleWidth(
contentWidth: contentWidth,
hasBackButton: hasBackButton,
hasChatToggle: hasChatToggle
).leadingCap,
alignment: .leading
)
.layoutPriority(1)
}
}
17 changes: 17 additions & 0 deletions ios/cmux/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -5917,6 +5917,23 @@
}
}
},
"mobile.terminal.picker.menuTitle": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Workspace and Terminals"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "ワークスペースとターミナル"
}
}
}
},
"mobile.terminal.select": {
"extractionState": "manual",
"localizations": {
Expand Down
Loading
Loading