fix(swift-ios): select across response blocks and copy as Markdown - #11297
mackinleysmith wants to merge 301 commits into
Conversation
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Theo Browne <me@t3.gg>
5193d2f to
1b25f08
Compare
Bugbot is paused — on-demand spend limit reachedBugbot 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. |
|
|
||
| func makeUIView(context: Context) -> UITextView { | ||
| let textView = FeatureInlineSkillTextView() | ||
| let textView = MarkdownSelectionTextView(frame: .zero, textContainer: nil) |
There was a problem hiding this comment.
🟡 Medium Chat/MarkdownMessageView.swift:890
Copying a completed message selection no longer preserves context or attachment metadata, so pasting it into the composer cannot restore the referenced context or retained attachment. makeUIView now creates MarkdownSelectionTextView, which bypasses the FeatureInlineSkillTextView.onCopySelection callback configured in updateUIView; its copy(_:) path writes reconstructed Markdown directly to UIPasteboard instead of calling FeatureContextClipboard.write with clipboardSource and messageContext. Preserve that callback path for MarkdownSelectionTextView (or forward its copy override through it).
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/swift-ios/Features/Chat/MarkdownMessageView.swift around line 890:
Copying a completed message selection no longer preserves context or attachment metadata, so pasting it into the composer cannot restore the referenced context or retained attachment. `makeUIView` now creates `MarkdownSelectionTextView`, which bypasses the `FeatureInlineSkillTextView.onCopySelection` callback configured in `updateUIView`; its `copy(_:)` path writes reconstructed Markdown directly to `UIPasteboard` instead of calling `FeatureContextClipboard.write` with `clipboardSource` and `messageContext`. Preserve that callback path for `MarkdownSelectionTextView` (or forward its copy override through it).
157476f to
285d2ab
Compare
What Changed
Text selection in SwiftUI responses stops at each rendered block, so users cannot copy a passage spanning paragraphs and code. Completed responses now render adjacent paragraphs, headings, ordinary lists, and code in one native selectable text view. Copying a selection produces Markdown for only the selected portion, preserving inline formatting, links, list markers, and code fences.
Code wraps within the response and retains its language label and Copy button. Streaming retains the existing per-block rendering. Tables, images, blockquotes, task lists, and other specialized blocks still form selection boundaries. Clipboard output is reconstructed Markdown, rather than a byte-for-byte slice of the original source.
Why
This is the more ambitious change compared with the targeted full-response Copy button in #11252, but it is the approach we believe is correct. Users should be able to select the passage they want, cross paragraph and code boundaries naturally, and paste usable Markdown. A full-response button is useful, but it does not solve copying part of a response.
This PR is independent of #11252 and excludes its footer button change. It applies only to the native SwiftUI client; there are no server, protocol, provider, web, desktop, or React Native changes.
UI Changes
Before: paragraphs and code are separate selection regions.
After: a physical iPhone recording shows selection across prose and code, copying, and pasting the resulting Markdown. The demo build includes the separate footer Copy button from #11252.
Validation
MarkdownDocumentTestsandMarkdownSelectionCopyTests, covering rendering boundaries, nested lists, partial formatting, links, Unicode, code fences, and native clipboard behavior.git diff --check.Checklist
Model: GPT-6. Harness: Codex in T3 Code.