* Route image copy through one copyImage service
Copying an image is one feature with a renderer half and a desktop
main-process half, but its request and result shapes were declared four
times (the main helper, the IPC channel map, the desktop bridge and the
renderer) and the renderer re-typed window.okDesktop behind an unknown
cast. The shapes now live once in core's desktop bridge, and the renderer
calls a copyImage service in packages/app/src/lib that tries the desktop
writer and falls back to the browser clipboard, returning a typed outcome
instead of logging from inside each branch.
The editor's copy listener now only recognises an image copy and hands it
to the service, so another surface (a context menu, an image toolbar)
can reuse the same path. The clipboard contents are unchanged.
* Copy only the image to the clipboard in the browser too
The desktop app already writes a copied image as image only, the shape a
macOS screenshot leaves, which PRD-7877 chose because HTML next to the
image made Google Docs render a gray placeholder and markdown pointing at
a localhost asset URL pasted as a broken link into other projects. The
browser fallback still wrote that HTML and markdown, so it now writes the
image alone, and the request drops alt since nothing reads it any more.
* Test copyImage's fetch and ClipboardItem failure seams (PRD-8925)
A rejected fetch and a throwing ClipboardItem constructor now each
resolve to a typed outcome under test, and the default environment is
covered with only the window, navigator, ClipboardItem and fetch
globals stubbed.
GitOrigin-RevId: 2b23366258afb4f474a50a450b32a786df7d3a41