Skip to content

feat(ios): add full thread row menu - #5753

Draft
saphid wants to merge 1 commit into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:t3code/add-mobile-thread-menus
Draft

feat(ios): add full thread row menu#5753
saphid wants to merge 1 commit into
pingdotgg:t3code/rebuild-mobile-app-swiftfrom
saphid:t3code/add-mobile-thread-menus

Conversation

@saphid

@saphid saphid commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Replaces the SwiftUI thread row's limited six-action menu with the full applicable thread action set: new thread on the same branch/worktree, pin/unpin, settle/reopen, snooze/wake, rename, regenerate title, archive/restore, copy path, copy branch, copy thread ID, and delete.
  • Adds local-calendar snooze presets for one hour, this evening, tomorrow morning, and next week.
  • Gates actions from the environment capabilities and current thread state, including a disabled Regenerating… state while title generation is pending.
  • Preserves an explicit branch/worktree when the new-task composer is opened from an existing thread, including branches that are no longer returned by branch discovery.

This is limited to the native SwiftUI mobile client. It does not change the React Native mobile, web, desktop, server, or wire schemas.

Why

The Electron/web thread menu already exposes the complete thread workflow, while the SwiftUI row menu only offered Rename, Archive, Pin, Settle, a fixed one-hour Snooze, and Delete. Users could not start related work on the same branch, regenerate a title, copy thread metadata, choose useful snooze times, or wake a snoozed thread from the same menu.

The shared menu model keeps capability and reverse-state rules testable, while the UIKit collection view remains responsible only for rendering UIMenuElement values. This follows the existing SwiftUI client boundary and the product direction established by #5592.

Mark unread is intentionally excluded because the SwiftUI client does not yet have a thread-read model. That depends on the separate server read-status work in #5652.

UI Changes

Before:

Before: limited SwiftUI thread menu

After:

After: complete SwiftUI thread menu

Snooze presets:

Date-aware snooze presets

Interaction video: open the menu and inspect snooze presets

Verification

  • Focused Xcode tests: ThreadContextMenuTests plus CoreContractTests/testCommandBuildersMatchOrchestrationContract — 12 passed, 0 failed, 0 skipped.
  • node scripts/generate-swift-wire-fixtures.ts --check — exit 0.
  • git diff --check — exit 0.
  • Clean signed Debug build installed and launched on an iPhone 17 Pro simulator running iOS 26.5.
  • Integrated SwiftUI pass against isolated disposable T3 state: paired successfully, loaded a seeded thread with branch/worktree metadata, exposed all applicable actions, and exposed all four snooze presets.
  • Claude Opus 5 high previously reviewed the byte-identical diff (05c8028b895a8a4529468d7b35e2c0011beb79754c09b463505217b462efb9a1) with no actionable findings. A fresh post-rebase review attempt exited 1 without output because the Claude session quota was exhausted; the rebase range-diff was unchanged.

Risks and limitations

  • The menu is intentionally capability-gated for older or limited environments.
  • Verified on one representative iPhone simulator in direct local connection mode; iPad layout and relay/tunnel transport were not separately exercised.
  • Existing repository Swift 6 and Ghostty warnings remain; no new build error was introduced.
  • Effective non-test diff size is expected to be size:XL, so the small-PR checklist item remains unchecked even though this is one SwiftUI-only outcome.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Implemented with GPT-5.6 Sol in the Codex harness.

Note

Add full thread row context menu with title regeneration, branch seeding, and copy actions

  • Adds a shared ThreadContextMenuModel in ThreadContextMenu.swift that drives context menus with consistent, capability-gated items: new thread on branch, regenerate title, snooze presets, wake, and copy path/branch/thread ID.
  • Wires up WorkspaceView to handle all new menu actions, including optimistic UI tracking for in-progress title regeneration (item disabled while running) with a polling loop to clear state when the server finishes.
  • Adds regenerateTitle WebSocket command and supporting model fields (ThreadTitleRegeneration, isRegeneratingTitle) through the client and protocol stack.
  • Allows new thread creation to be pre-seeded with a branch/worktree from an existing thread; uses SeededWorkspaceDraftPersistence to avoid persisting drafts that contain only a seed with no user content.
  • Adds ThreadContextMenuTests and contract test assertions for the new regenerateTitle command payload.
📊 Macroscope summarized f6d7154. 11 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5582dd0a-bda9-4a9c-89b4-c6bf71bc655d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 8, 2026
case .worktree: worktreeBase(in: branches)
}
}
return branches.first { $0.name == selection.name } ?? selection

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.

🟠 High Workspace/NewTaskWorkspaceModels.swift:83

refreshedSelection returns the stale selection when it's no longer found in branches, so after a refresh the caller retains a branch that was deleted or renamed. canSubmit still accepts it and the request goes out with a branch no longer present, instead of falling back to localBranch/worktreeBase. The fallback ?? selection discards the resolved default even when the branch genuinely disappeared. Consider returning the mode-appropriate default when the branch is missing, or restricting the retain-original behavior to the initial seeded selection only.

Suggested change
return branches.first { $0.name == selection.name } ?? selection
return branches.first { $0.name == selection.name } ?? defaultBranch(in: branches, mode: mode)
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/swift-ios/Features/Workspace/NewTaskWorkspaceModels.swift around line 83:

`refreshedSelection` returns the stale `selection` when it's no longer found in `branches`, so after a refresh the caller retains a branch that was deleted or renamed. `canSubmit` still accepts it and the request goes out with a branch no longer present, instead of falling back to `localBranch`/`worktreeBase`. The fallback `?? selection` discards the resolved default even when the branch genuinely disappeared. Consider returning the mode-appropriate default when the branch is missing, or restricting the retain-original behavior to the initial seeded selection only.

@t3dotgg
t3dotgg force-pushed the t3code/rebuild-mobile-app-swift branch from 65e66ee to 4df1e9b Compare August 9, 2026 02:26
@saphid
saphid force-pushed the t3code/add-mobile-thread-menus branch from f6d7154 to cc44c81 Compare August 9, 2026 03:26
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 9, 2026
@saphid

saphid commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Rebased this draft onto the signed SwiftUI base rewrite at 4df1e9b. The only conflict was in NewThreadView; the repair keeps the new activePicker flow and preserves workspaceSelectionIsSeeded = false when a branch is chosen. GitHub now reports the intended 13-file diff (865 additions, 72 deletions), not the rewritten base history. Verification: 12 focused Xcode tests passed, 0 failed; git diff --check passed. New tip: cc44c81.

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

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant