Skip to content

Attach workspace rename and color alerts to their window - #8544

Merged
azooz2003-bit merged 3 commits into
mainfrom
feat-rename-alert-sheet
Jul 21, 2026
Merged

azooz2003-bit merged 3 commits into
mainfrom
feat-rename-alert-sheet

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jul 21, 2026 •

Copy link
Copy Markdown
Collaborator

The Rename Workspace alert always appeared on a different monitor than the cmux window on multi-monitor setups. It was presented with bare NSAlert.runModal(), which creates a detached alert window that macOS centers on whichever screen it considers main rather than the screen showing cmux.

All affected alerts now go through the existing runCmuxModal(presentingWindow:) presenter, resolving the host window with mainWindowContainingWorkspace, so each alert attaches as a sheet to the window that owns the workspace (also correct with multiple cmux windows open). Migrated call sites:

  • SidebarWorkspaceRowCommands.promptRename (AppKit sidebar context menu, the reported path)
  • TabItemView.promptRename (SwiftUI sidebar parity path)
  • AppDelegate.promptRenameSelectedWorkspace (rename keyboard shortcut)
  • Custom workspace color prompt + invalid-color alert in both sidebar paths
  • Workspace.promptRenamePanel (Rename Tab alert)

No new user-facing strings; all localization keys unchanged. No automated regression test: sheet-vs-detached presentation of a blocking modal has no practical unit-level assertion, verification is via tagged-build dogfood.

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Attach workspace rename and color alerts to their owning window as sheets so they appear on the correct monitor. Also focus and select the input on open using the modal’s willPresent hook.

  • Bug Fixes
    • Applies to: workspace rename (sidebar, SwiftUI tab row, keyboard shortcut), custom color prompt, invalid-color alert, and Rename Tab alert.
    • Uses runCmuxModal(presentingWindow:) to attach to the workspace’s window across multiple cmux windows/monitors, and sets input focus in willPresent (replacing the async main hop); no string or behavior changes beyond presentation.

Written for commit 495b05f. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved alert and confirmation dialog presentation by attaching modals to the relevant workspace’s main window across the app.
    • Preserved existing response handling for rename and custom color prompts, including the first-button outcome logic.
    • Improved consistency of user interaction behavior by reliably focusing the input field and selecting its text when the modal opens in Content, the sidebar, and workspace rename flows.

The Rename Workspace alert (sidebar context menu, SwiftUI tab row, and
the keyboard-shortcut path), the custom workspace color prompt, and the
Rename Tab alert all presented via bare NSAlert.runModal(), which shows
a detached alert window that macOS places on whichever screen it deems
main - on multi-monitor setups that is often not the screen showing
cmux. Present them through runCmuxModal(presentingWindow:) instead,
resolving the host via mainWindowContainingWorkspace so each alert
attaches as a sheet to the window that owns the workspace.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Alert presentation across application, content, sidebar, and workspace flows now uses runCmuxModal, passing the relevant workspace main window while preserving existing response handling. Text-entry alerts also configure and select their input fields during modal presentation.

Changes

Workspace alert presentation

Layer / File(s) Summary
Workspace-aware alert calls
Sources/AppDelegate.swift, Sources/ContentView.swift, Sources/Workspace.swift, Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift
Alert flows use runCmuxModal(presentingWindow:) with the workspace’s main window, while existing response checks, validation, and dismissal behavior remain unchanged.
Alert input focus
Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift
Rename and custom color prompts configure the initial responder and focus and select the text field inside the modal callback.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • manaflow-ai/cmux#8296: Refactors the runCmuxModal(...presentingWindow:) presentation API used by these alert call sites.

Suggested reviewers: lawrencecchen, austinywang


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Concurrency ❓ Inconclusive Pending code inspection of changed Swift files and concurrency rules. Need to verify whether the PR introduces any prohibited async patterns in the actual diff.
✅ Passed checks (24 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed Touched alert code stays inside @MainActor UI types, and helper APIs are @MainActor too; the diff only changes presentation, not isolation boundaries.
Cmux Swift Blocking Runtime ✅ Passed The patch removes DispatchQueue.main.async focus hops and uses the synchronous runCmuxModal willPresent hook; no new waits, sleeps, syncs, or locks were introduced.
Cmux Browser Automation Off-Main ✅ Passed HEAD only changes alert presentation in four non-browser files; no browser.* socket commands or policy files were touched.
Cmux Expensive Synchronous Load ✅ Passed The diff only changes alert presentation/focus handling; no agent-history load, JSON parsing, or other expensive synchronous work was added to these interactive paths.
Cmux Cache Substitution Correctness ✅ Passed UI alert presentation only; no persistence/history/undo/snapshot cache substitution or stale/cold-cache risk is present.
Cmux No Hacky Sleeps ✅ Passed PASS — The patch only changes Swift alert presentation; it removes a DispatchQueue.main.async hop and adds no sleeps, timers, polling, or waits.
Cmux Algorithmic Complexity ✅ Passed Only modal presentation changed; no new scalable scans/sorts were added, and the existing workspace lookup scan wasn’t worsened.
Cmux Swift @Concurrent ✅ Passed Diff only swaps modal presentation and moves focus work into runCmuxModal’s @MainActor willPresent closure; no @concurrent/nonisolated async changes.
Cmux Swift Package Boundaries ✅ Passed The diff only changes alert presentation/focus wiring in AppDelegate, ContentView, SidebarWorkspaceRowCommands, and Workspace—allowed UI/AppKit/app-lifecycle glue, not reusable domain logic.
Cmux Swiftpm Lockfiles ✅ Passed HEAD only changes four Swift source files; no .gitignore, workflow, Xcode project, or Package.resolved diffs are present.
Cmux Swift Logging ✅ Passed The diff only changes alert presentation/focus handling; no print/debugPrint/dump/NSLog, ad hoc logging, or Logger changes were added.
Cmux User-Facing Error Privacy ✅ Passed The PR only changes alert presentation/focus wiring; the user-visible alert copy remains generic and exposes no vendor, provider, secret, or raw upstream details.
Cmux Full Internationalization ✅ Passed Diff only changes alert presentation; no user-facing copy, catalogs, or locale files changed, so full-i18n rules aren’t violated.
Cmux Swiftui State Layout ✅ Passed Touched code only changes NSAlert presentation in action handlers; no new SwiftUI state/layout patterns or render-time writes were introduced.
Cmux Architecture Rethink ✅ Passed Uses existing runCmuxModal bridge with synchronous willPresent; no new async/timer/observer/state ownership was introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR only switches NSAlert flows to runCmuxModal sheets; no standalone NSWindow/WindowGroup/controller changes or new identifiers were introduced.
Cmux Source Artifacts ✅ Passed All changed paths are hand-written Swift source files; no logs, caches, builds, temp dirs, or other source-control artifacts appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Diff only switches alerts to runCmuxModal/presentingWindow; no new #if DEBUG, *ForTesting, or test/debug-only accessors were added in Sources/.
Cmux No Ambient Global State ✅ Passed Diff only rewires alert presentation inside existing methods; no new file-scope func/var, namespace bag, or singleton/state surface was added.
Title check ✅ Passed The title clearly summarizes the main change: attaching workspace rename and color alerts to their owning window.
Description check ✅ Passed The description covers the summary, testing, review trigger, and change scope, though the demo video and checklist sections are not filled out.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-rename-alert-sheet

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR attaches workspace rename and color alerts to the window that owns the workspace. The main changes are:

  • Routes sidebar, SwiftUI, and shortcut rename alerts through runCmuxModal.
  • Attaches custom-color and invalid-color alerts to the workspace window.
  • Attaches Rename Tab alerts to the workspace window.
  • Focuses and selects text input when rename and color sheets open.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the updated code.
  • No separate incomplete or unsafe fix remains within the follow-up scope.

Important Files Changed

Filename Overview
Sources/AppDelegate.swift Attaches the shortcut-driven workspace rename alert to the workspace window.
Sources/ContentView.swift Attaches SwiftUI workspace rename and color alerts to the workspace window.
Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift Attaches AppKit sidebar rename and color alerts to the workspace window.
Sources/Workspace.swift Attaches the Rename Tab alert to the workspace window.

Reviews (3): Last reviewed commit: "Set alert input focus via willPresent in..." | Re-trigger Greptile

Comment thread Sources/ContentView.swift
Comment on lines +15695 to +15697
_ = alert.runCmuxModal(
presentingWindow: AppDelegate.shared?.mainWindowContainingWorkspace(workspaceId)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Outgoing Sheet Forces Detached Alert

When an invalid color such as ZZZZZZ is submitted, this alert is requested immediately after the color sheet's modal loop returns. If the outgoing sheet is still attached during dismissal, runCmuxModal sees an occupied host and falls back to runModal(), so the validation alert can appear detached on another monitor.

Rule Used: Flag Swift fixes that patch symptoms while leaving... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The invalid-color alert presents after NSApp.runModal returns, which is strictly after the first sheet's didEnd completion ran; AppKit detaches the sheet before that completion (the shipped pattern in AppDelegate+WorkspaceActionSave.swift presents a second sheet directly inside the first's completion). If AppKit ever left attachedSheet set at that instant, runCmuxModal falls back to app-modal, which is the pre-fix behavior, so the alert stays functional.

— Claude Code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. NSApp.runModal returns only after the sheet's didEnd completion has fully run and AppKit has already detached the sheet — the window's attachedSheet is nil by the time the invalid-color alert is requested. My concern about a race with an occupied host was unfounded. The existing pattern in AppDelegate+WorkspaceActionSave.swift confirms this is the established idiom. I'll withdraw the comment.

Comment on lines +221 to +223
_ = alert.runCmuxModal(
presentingWindow: AppDelegate.shared?.mainWindowContainingWorkspace(tab.id)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Outgoing Sheet Forces Detached Alert

When the AppKit sidebar color prompt receives an invalid value, it requests this alert immediately after the first sheet's modal loop returns. If that sheet remains attached during dismissal, runCmuxModal takes its bare runModal() fallback and the validation alert can appear on the wrong monitor.

Rule Used: Flag Swift fixes that patch symptoms while leaving... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same rationale as the ContentView thread: the second alert presents after runModal returns (post-didEnd, sheet already detached, matching the production second-sheet pattern in AppDelegate+WorkspaceActionSave.swift), and the appModal fallback keeps the alert functional in the worst case.

— Claude Code

Match the sidebar group-rename prompt's focus dance: initialFirstResponder
alone was reliable under app-modal runModal, but sheet presentation keys
the sheet on the host window's schedule, so also make the field first
responder and select its text on the next main-loop turn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift`:
- Around line 163-171: Replace the DispatchQueue.main.async focus workaround in
promptRename with the runCmuxModal willPresent callback, moving
makeFirstResponder and selectText into that closure. Apply the same change in
promptCustomColor; update both affected locations in
Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift (lines
163-171 and 203-211) while preserving the existing modal behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a617a099-1361-48de-acb8-7f494130e94a

📥 Commits

Reviewing files that changed from the base of the PR and between 545ba77 and 0d22027.

📒 Files selected for processing (1)
  • Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift

Comment thread Sources/Sidebar/AppKitList/Cells/SidebarWorkspaceRowCommands.swift Outdated
CodeRabbit and the cmux pre-merge checks flagged the
DispatchQueue.main.async focus dance as a banned timing-repair pattern.
runCmuxModal already exposes a synchronous willPresent hook that fires
just before the modal session begins, so set makeFirstResponder and
selectText there in all six touched alert sites (including the four
pre-existing async hops in the functions this PR already changes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@azooz2003-bit
azooz2003-bit merged commit fca2a2d into main Jul 21, 2026
16 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-rename-alert-sheet branch July 21, 2026 03:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant