Skip to content

fix(mobile): terminal Paste says why when nothing is pasted - #31640

Merged
AmoabaKelvin merged 1 commit into
mainfrom
terminal-image-paste
Oct 21, 2026
Merged

AmoabaKelvin merged 1 commit into
mainfrom
terminal-image-paste

Conversation

@AmoabaKelvin

@AmoabaKelvin AmoabaKelvin commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​126 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​126
Prod 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​14 $\color{#cf222e}{\Huge{\mathbf{−}}}$​4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​10

Refs #20686

What users saw

In a mobile terminal, tapping Paste with only an image on the clipboard could do nothing. The iOS paste prompt closed and nothing was pasted. There was no toast and no error haptic.

Now

When the paste can't send anything, the user is told why:

  • The clipboard image read comes back empty: "Couldn't read the clipboard".
  • The connection drops while the image uploads: "Paste failed (disconnected)".
  • The user switches terminal or tab during the upload: "Paste canceled (terminal changed)".
  • Typed input queued ahead of the paste fails to send: "Paste failed".

Root cause

useMobileTerminalPaste treated a null image read as an empty clipboard and returned quietly. On iOS, null also covers:

  • Don't Allow Paste. This is the blue default button in the iOS 26 prompt.
  • A read iOS refuses without asking. On the iOS 27 simulator, stock and slim, every programmatic read is denied in about 35 ms with no visible prompt (PBErrorDomain 13 "Operation not authorized").
  • An image UIPasteboard.image can't decode. A WebP or HEIC copied on its own counts as no image at all (hasImages false).

On an iOS 26 simulator, a probe app making expo-clipboard's exact reads got the image back after Allow every time: a PNG copied from another app, a 6016×6016 Photos copy, and an image offered lazily through an item provider. So "Allow, then null" didn't reproduce here and needs a real device to pin.

The paste also had a second quiet exit, after the upload finished. It returned without a word when the connection, terminal or pending typed input changed underneath it. Those checks now run before the false-flush return, so each case gets a message.

The change is in the shared hook, so both the OTA page and the native screen get it. The host side is unchanged. Android's getImageAsync returns null only when there's no image/* clip and throws on a failed read (which already toasts), so the same message covers it.

Not in this PR: reading the clipboard without the consent prompt, using the system paste control (UIPasteControl). On iOS 27 that's the only way the Paste button gets the image. It needs a native shell change and a store build.

How verified

  • A focused test covers each quiet exit; all four fail on main.
  • Real OTA page route on the iOS 27 simulator, against a headless serve built from this branch, with an image copied from another app. Before, with the main page bundle, tapping Paste does nothing. After, the toast shows.

Visual Proof

Before (main): Paste does nothing.

before.mp4

After: Paste says it couldn't read the clipboard.

after.mp4

iOS answers null for a clipboard image after Don't Allow Paste, when the read is not authorized, or for a format it cannot decode, and the paste stopped without a word. A paste dropped after its upload, because the connection went away, the terminal changed, or typed input queued ahead of it failed to send, was dropped quietly too.
@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

The mobile terminal paste handler now reports errors and shows toasts when it cannot read a clipboard image, the client disconnects, the terminal target changes, or pending input fails to flush. New tests cover these four failure paths and verify that no paste request is sent.

Priority: ⬇️ Low

Merge Risk: 🔵 Low · up to 1c7b6

A disconnect during image upload may show the generic paste error instead of the disconnected message. This is a bounded feedback issue, not a blocker to pasting on a connected session.

Pre-merge checks: Passed 3 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Description check Warning The description provides a detailed user impact, root cause, implementation scope, testing summary, and visual proof. It does not follow the required template fully: it lacks the required headings and… Add the missing template sections. Include a clear ELI5 summary, an explicit Why section, testing steps and platform details, review notes, compatibility notes, and the checklist. Replace “Refs #20686” with the required issue link format, s…
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly identifies the mobile terminal paste behavior change and explains that the action now reports why nothing was pasted.
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.
Full details: Description check

Explanation

The description provides a detailed user impact, root cause, implementation scope, testing summary, and visual proof. It does not follow the required template fully: it lacks the required headings and content for ELI5, Why, Testing, Review, Notes, and Checklist, and it uses “Refs #20686” instead of the required linked issue format.

Resolution

Add the missing template sections. Include a clear ELI5 summary, an explicit Why section, testing steps and platform details, review notes, compatibility notes, and the checklist. Replace “Refs #20686” with the required issue link format, such as “Fixes #20686” when applicable.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)

🟡 Minor · Use the current connection state in the catch block. · use-mobile-terminal-paste.ts:149

mobile/src/session/use-mobile-terminal-paste.ts:149
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the current connection state in the catch block.

If a disconnect rejects the image upload or pending-input flush, execution skips the new connection check. This catch block reads the earlier connState value and can show Paste failed instead of Paste failed (disconnected). Read connStateRef.current here. The new disconnection test changes the state after upload, so it does not cover this path.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: df3fb6f2-4970-46a8-8b43-7012bec15786
📥 Commits

Reviewing files that changed from the base of the PR and between 1db95e3 and 1c7b667.

📒 Files selected for processing: 2
  • mobile/src/session/use-mobile-terminal-paste-dropped.test.ts
  • mobile/src/session/use-mobile-terminal-paste.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

@AmoabaKelvin
AmoabaKelvin merged commit 106716c into main Oct 21, 2026
22 checks passed
@AmoabaKelvin
AmoabaKelvin deleted the terminal-image-paste branch October 21, 2026 23:49
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