Skip to content

Restore iOS workspace group row actions - #9182

Closed
azooz2003-bit wants to merge 31 commits into
mainfrom
feat-ios-workspace-group-actions
Closed

azooz2003-bit wants to merge 31 commits into
mainfrom
feat-ios-workspace-group-actions

Conversation

@azooz2003-bit

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

Copy link
Copy Markdown
Collaborator

Summary

  • Restore group context menus with group commands and the anchor workspace actions.
  • Apply workspace swipe actions to group rows and expose Rename beside Customize.
  • Carry custom group icons through mobile state sync so iOS matches macOS.
  • Present Rename Group as the compact text-field alert used before, not a sheet.
  • Defer a read-state row reload until UIKit finishes closing the active full swipe, preventing the group header from snapping at completion.
  • Consume destructive group requests atomically and test ungroup, delete, and cancellation routing.

Testing

  • WorkspaceGroupDestructiveActionTests and WorkspaceListScrollUpdateTests: 18 tests passed on isolated iOS 18.4 simulator 3B697F98-97BF-45EB-B9B5-6F44A78DC8F1.
  • WorkspaceListScrollUpdateTests: 16 tests passed on isolated iOS 26.5 simulator 9C943972-DB3E-474F-B65D-6200F2758913.
  • UI paths passed on isolated iOS 26.5: compact Rename Group alert, full-swipe Mark as Read, and the complete group context menu.
  • MobileStateSyncFrameCodingTests: 8 tests passed.
  • Workspace-group icon response tests: 2 tests passed.
  • Arm64 iOS build-for-testing passed.
  • git diff --check passed.

Video verification

  • Reproduced the supplied snap, recorded the fixed native full swipe, and inspected the result at 30 fps.
  • The swipe retracts continuously, the group header remains mounted, and the unread state changes after UIKit closes the swipe.

Review trigger

  • No manual review was requested or triggered.

Checklist

  • I tested the change locally.
  • I added or updated tests for behavior changes.
  • Docs and changelog do not need changes.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Workspace group icon propagation

Layer / File(s) Summary
Icon wire contract and rendering
Packages/Shared/..., Packages/iOS/..., Sources/Mobile/..., Sources/TerminalController+MobileWorkspaceList.swift, cmuxTests/...
Group icons are added to sync records and mobile payloads, propagated through iOS models, rendered in group headers, included in observer hashing, and covered by encoding, decoding, mapping, and fidelity tests.

Workspace group actions

Layer / File(s) Summary
Group menu and action flow
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/...
Group headers expose group and anchor-workspace actions and route rename, ungroup, and delete requests through sheets and confirmation dialogs.
Group row action and update routing
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTable.swift
Group-header actions use anchor workspaces, request availability participates in updates, and native payload changes route through reloads or reconfigurations.
Group action validation
Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/..., ios/cmuxUITests/cmuxUITests.swift
Tests cover grouped-row menus, swipe actions, simultaneous customize and rename actions, native reload behavior, destructive action state handling, and group rename presentation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TabManager
  participant MobileWorkspaceListObserver
  participant TerminalController
  participant MobileSyncWorkspaceListResponse
  participant WorkspaceGroupHeaderRow
  TabManager->>MobileWorkspaceListObserver: update group icon
  MobileWorkspaceListObserver->>MobileWorkspaceListObserver: include iconSymbol in summaryHash
  TerminalController->>TerminalController: serialize icon_symbol
  TerminalController->>MobileSyncWorkspaceListResponse: provide group payload
  MobileSyncWorkspaceListResponse->>WorkspaceGroupHeaderRow: decode and render iconSymbol
Loading
sequenceDiagram
  participant WorkspaceListTableCoordinator
  participant WorkspaceListView
  participant WorkspaceGroupRenameSheet
  participant ConfirmationDialog
  WorkspaceListTableCoordinator->>WorkspaceListView: request group action
  WorkspaceListView->>WorkspaceGroupRenameSheet: present rename UI
  WorkspaceGroupRenameSheet->>WorkspaceListView: submit rename
  WorkspaceListView->>WorkspaceListView: dispatch renameWorkspaceGroup
  WorkspaceListView->>ConfirmationDialog: present destructive confirmation
  ConfirmationDialog->>WorkspaceListView: dispatch ungroupWorkspaceGroup or deleteWorkspaceGroup
Loading

Possibly related PRs

Suggested reviewers: austinywang, lawrencecchen


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux No Ambient Global State ❌ Error Adds file-scope enum WorkspaceListLayoutPreviewFixture as a static namespace with one static var, which the rule forbids. Move the preview accessor onto an owning type or use a private file-scope helper/constant; avoid a standalone namespace enum.
Docstring Coverage ⚠️ Warning Docstring coverage is 13.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
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 No new actor-isolation debt: added models are plain Sendable value structs, and the new observable request state stays inside SwiftUI/MainActor UI code.
Cmux Swift Blocking Runtime ✅ Passed Diff adds state/UI routing only; changed Swift files contain no semaphores, sleeps, sync waits, main-thread sync, or manual locks.
Cmux Browser Automation Off-Main ✅ Passed Diff only touches mobile group/icon state and iOS UI; no browser.* routing, WebKit-wait commands, or policy tests changed.
Cmux Expensive Synchronous Load ✅ Passed No expensive agent-history loader or large-file parse was added; touched code only threads icon/group action data and linear in-memory payload shaping.
Cmux Cache Substitution Correctness ✅ Passed No fresh-read-to-cache swap: snapshots read live model/state-sync records, and the mobile mirror is event-driven with cold-start fetch/reset handling.
Cmux No Hacky Sleeps ✅ Passed No changed files fall under the rule: the PR only touches Swift sources/tests, and no non-Swift runtime/script diffs introduce sleeps/timers.
Cmux Algorithmic Complexity ✅ Passed Changes are linear-time and mostly dict/set lookups; no new nested scans, per-target rescans, or repeated sort/filter loops in hot paths.
Cmux Swift Concurrency ✅ Passed The only actual diff just reorders a preview closure; it adds no DispatchQueue, new Combine app state, or fire-and-forget Task patterns.
Cmux Swift @Concurrent ✅ Passed No changed Swift code adds invalid @concurrent/nonisolated async; the new async paths are UI-bound @MainActor refresh/title-picker tasks.
Cmux Swift Package Boundaries ✅ Passed App-target changes are app-lifecycle glue (state sync host, observer hash, RPC payload wiring); reusable models/decoders moved into SwiftPM packages.
Cmux Swiftpm Lockfiles ✅ Passed Diff vs origin/main touches only source/test files; no .gitignore, Package.swift, .xcodeproj, workflow, or Package.resolved files changed, so the lockfile policy isn’t violated.
Cmux Swift Logging ✅ Passed No logging violations: the diff adds no print/debugPrint/dump/NSLog or new Logger statements; the existing mobileWorkspaceObserverLog is unchanged.
Cmux User-Facing Error Privacy ✅ Passed Touched production alerts/messages are generic and sanitized; no vendor, internal provider, payload, or secret details are exposed.
Cmux Full Internationalization ✅ Passed New group UI copy uses L10n.localized APIs, and the app catalog has en/ja translations for every new key including placeholder and confirm text.
Cmux Swiftui State Layout ✅ Passed No forbidden SwiftUI patterns: new state uses @Observable + @State, rows consume snapshots/closures, and there’s no GeometryReader/@Published/@StateObject in the diff.
Cmux Architecture Rethink ✅ Passed The new group request state is list-owned bridge code with clear invariants; I found no sleeps, polling, locks, or split ownership hacks.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed No changed Swift file adds NSWindow/WindowGroup or cmuxAuxiliaryWindowIdentifiers; the PR only changes views, sheets, dialogs, previews, and tests.
Cmux Source Artifacts ✅ Passed All 24 changed paths are intentional source/test files; none match the rule’s artifact denylist (logs, screenshots, build output, temp, caches, DerivedData).
Cmux No Test Or Debug Seam In Production Source ✅ Passed No added test/debug seam in production Sources; added code is product behavior, and the preview file remains a dedicated DEBUG fixture.
Title check ✅ Passed The title is concise and accurately summarizes the main change: restoring iOS workspace group row actions.
Description check ✅ Passed The description matches the template well and includes summary, testing, and review info, though the Demo Video URL and some checklist items are incomplete.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-ios-workspace-group-actions

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.

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator+Actions.swift (1)

1-1: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add Localizable.xcstrings entries for the new mobile group strings.

The group action and confirmation strings are wired through L10n.string(key, defaultValue:), but their mobile.workspaceGroup.* keys are not present in the mobile catalog. Add the matching entries so non-English locales can be translated instead of falling back to the English default.

🤖 Prompt for 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.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator`+Actions.swift
at line 1, Add the missing mobile catalog entries for every
`mobile.workspaceGroup.*` key used by the group action and confirmation strings
through `L10n.string(key, defaultValue:)`, preserving each key’s English default
value so non-English locales can translate them without fallback.

Source: Path instructions

🤖 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
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView`+Actions.swift:
- Around line 197-215: Add focused unit tests for
confirmWorkspaceGroupDestructiveAction() and
clearWorkspaceGroupDestructiveRequest(), covering both .ungroup and .delete
actions. Assert that the matching backend closure receives the pending group ID,
the other closure is not invoked, and pending destructive state is cleared after
confirmation; also verify the explicit clear method resets both pending
properties.

---

Outside diff comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator`+Actions.swift:
- Line 1: Add the missing mobile catalog entries for every
`mobile.workspaceGroup.*` key used by the group action and confirmation strings
through `L10n.string(key, defaultValue:)`, preserving each key’s English default
value so non-English locales can translate them without fallback.
🪄 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 Plus

Run ID: c416385d-1f9b-4206-ae09-e301d089ca6e

📥 Commits

Reviewing files that changed from the base of the PR and between 93bfd5e and dcbe222.

📒 Files selected for processing (20)
  • Packages/Shared/CMUXMobileCore/Sources/CMUXMobileCore/MobileStateSyncRecords.swift
  • Packages/Shared/CMUXMobileCore/Tests/CMUXMobileCoreTests/MobileStateSyncFrameCodingTests.swift
  • Packages/iOS/CmuxMobileRPC/Sources/CmuxMobileRPC/MobileSyncWorkspaceListResponse.swift
  • Packages/iOS/CmuxMobileRPC/Sources/CmuxMobileRPC/MobileWorkspacePreview+RemoteMapping.swift
  • Packages/iOS/CmuxMobileRPC/Tests/CmuxMobileRPCTests/MobileCoreRPCClientTests.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+StateSync.swift
  • Packages/iOS/CmuxMobileShellModel/Sources/CmuxMobileShellModel/MobileWorkspaceGroupPreview.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceGroupHeaderRow.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTable.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator+Actions.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView+Actions.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView+Table.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceNavigationRow.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceListScrollUpdateTests.swift
  • Sources/Mobile/MobileStateSync.swift
  • Sources/Mobile/MobileWorkspaceListObserver.swift
  • Sources/TerminalController+MobileWorkspaceList.swift
  • cmuxTests/MobileWorkspaceListFidelityTests.swift

@cursor

cursor Bot commented Jul 30, 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: 2

🤖 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
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceGroupDestructiveRequestState.swift`:
- Around line 6-7: Make pending destructive requests atomic by replacing the
independently writable groupID and action properties in
WorkspaceGroupDestructiveRequestState with one private request value containing
both fields, plus enqueue, consume, and clear operations. In WorkspaceListView,
remove the writable proxies and derive reads and bindings from that canonical
request. Update the three specified WorkspaceGroupDestructiveActionTests sites
to enqueue ungroup, delete, and clear-path requests atomically; apply these
changes respectively in
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceGroupDestructiveRequestState.swift#L6-L7,
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift#L147-L153,
and
Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceGroupDestructiveActionTests.swift#L15-L16,
`#L34-L35`, and `#L47-L48`.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator.swift`:
- Around line 387-398: The native action reload predicate must track all
group-header action inputs, not only anchor identity and unread state. In
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator.swift
lines 387-398, update nativeActionPayloadChanged to compare read/close
capability and callback availability; in lines 789-797, include anchor
workspace-action callback availability in the group-header payload so the
predicate executes. In
Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceListScrollUpdateTests.swift
lines 217-245, add transitions for read/close capability changes and callback
removal, asserting that native reload is requested.
🪄 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 Plus

Run ID: 0a1e64aa-fc20-4af5-a012-d4402098ba0b

📥 Commits

Reviewing files that changed from the base of the PR and between dcbe222 and 6495e8b.

📒 Files selected for processing (6)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceGroupDestructiveRequestState.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListTableCoordinator.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView+Actions.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceGroupDestructiveActionTests.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceListScrollUpdateTests.swift

@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
`@Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceListScrollUpdateTests.swift`:
- Around line 354-377: Update the read and unread configurations used by the
group-header swipe test to enable supportsReadStateActions and provide the
setUnread callback (or equivalent close action) in both fixtures. Keep the
existing willBeginEditingRowAt invocation and coordinator.update flow so UIKit
exercises the reachable swipe-completion path.
🪄 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 Plus

Run ID: 40046840-951c-492b-8076-6a677cd84692

📥 Commits

Reviewing files that changed from the base of the PR and between 1cd33d2 and 98d8202.

📒 Files selected for processing (3)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListLayoutPreviewView.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceListScrollUpdateTests.swift
  • ios/cmuxUITests/cmuxUITests.swift

@cursor

cursor Bot commented Jul 30, 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.

@cursor

cursor Bot commented Jul 30, 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.

@cursor

cursor Bot commented Jul 31, 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants