BL-17014: paste a picture into a text block as an inline image

Preflight of branch BL-17014-PasteInlineImageInText at 8a7b20166, 2026-10-23 (third run, after simplifying the code). Gates green, every reviewer finished, nothing waiting on you.

Ready for review Mergeable, clean Bots quiet No decisions waiting

What this PR is about

Problem

Pasting a picture into a text block pasted the picture's file path as text instead of the picture. Ctrl+V in a text block is left to the browser and CKEditor, and most picture copies (Bloom's own Copy Image, a file copied in Explorer, a browser's "Copy image") put the path or URL on the clipboard as text beside the picture, so the text is what got pasted. The top-bar Paste button sent the picture to the page's canvas instead, or pasted the same text.

What the PR does

  • With the focus in a text block that can take inline images, pasting a picture (Ctrl+V or the Paste button) adds an inline image holding it to that block, docked right at the start of the block, where Insert Image puts one.
  • With an inline image selected, the pasted picture replaces its picture, through the image's own "Paste image" command. Bloom leaves an image it has just inserted or pasted selected, so Insert Image followed by a paste fills the new image, and a second paste right after a first replaces it, as on a canvas.
  • It reuses the canvas paste's round trip through C#. The image appears only once the picture has arrived, so a failed or cancelled paste leaves nothing, one Undo takes back the paste, and a save made in the meantime waits for the picture. The "Paste image" command now holds that wait for every picture, canvas ones too, and ignores a second paste over a picture still being replaced.
  • One small C# change: when importing a pasted picture fails, C# now tells the page, which before was left waiting.
  • A clipboard with formatted text as well as a picture still pastes as text. Blocks that can't take inline images, and a paste with a canvas picture selected, behave as before.
A picture pasted into a text block appears at the block's top right, selected, with its toolbar
A picture pasted into a text block, selected, with its toolbar.

Quality gate

CheckResult
Typecheck (pnpm typecheck)Pass
Lint (eslint on the changed files, and in the commit hook)Pass, 0 errors
TypeScript tests (vitest, full suite)Pass, 1630 passed · 113 files, at 696cba0ed; the front-end has changed since only by a comment
C# tests (dotnet test via build/agent-dotnet.sh, full suite at HEAD)Pass, 3837 passed · 1 skipped
Repo check: e2e specs at the nightly's window sizeDid not apply: the diff adds or changes no src/BloomE2E/tests/*.spec.ts
Merge with masterClean, up to date
CI (pr-automation)Pass

What changed this run

Simplified the paste code as you asked: the save delay and the double-paste guard moved into the "Paste image" command, the unneeded file-name fallback and an early return went, and a stray comment was folded in. The light review found that the move left one gap, a failed picture import that C# never reported, which a small C# fix closes. See the commit list.

Reviewer outcomes

Local review (light sub-agent pass)
One finding on the simplification: when C# failed to import a pasted picture it sent the page no answer, so the new double-paste guard would have ignored every later paste onto that picture. Fixed in c46293b11 (ChangePicture now reports failure, so OnPasteImage tells the page). It checked the GIF, empty-clipboard, declined-JPEG and new-canvas-element paths and found them fine.
Devin
Complete for 8a7b20166, nothing new. On the simplification it raised two bugs, both answered as not acting: image files without a MIME type (the fallback was removed on purpose) and a cancelled paste keeps an entry (it lasts only until the page changes). All its earlier findings are fixed or answered. Consultation log.
Greptile
Complete for 696cba0ed (re-triggered for the simplification): "no new actionable issue". It has not reviewed the C# fix or the comment fix after it, which Devin has; it was not re-triggered for those.
CI
pr-automation passed for 8a7b20166.
Repo check: e2e specs at the nightly's window size
Did not apply; no e2e spec changed.

Worth knowing

  • The simplification has not been tried in a running Bloom; the earlier live checks (paste into text, replace a selected picture, undo) were of the code before it. Unit tests cover the moved delay and guard, and the C# change has the full C# suite behind it.
  • The canvas picture's own "Paste image" now waits and drops a quick second paste too; the test ideas on the card ask testers to check it still replaces the picture.

Nothing waiting on you

Your last answer (leave the second-paste behavior as it is) is recorded in the code comment on getInlineImagePasteTarget and in the test ideas on BL-17014. The PR is ready for your own final review.