fix(blockImage): let a broken image reach its file object #2383

Merged
requilence opened 7:33am on September 18, 2026 wanted to merge 1 commit into anyproto/anytype-ts develop from
fix/JS-9877-broken-image-actions

Pull Request Overview

  • Opened on September 18, 2026
  • Status Merged
  • Commit count 1 with first commit September 18, 2026

Total Delta

0 Total Diff Delta

Open Days

Open 1 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Data pending calculation for pull request

Author avatar

fix(blockImage): let a broken image reach its file object

Closes JS-9877

The problem

A broken image rendered a πŸ”— Image is broken strip that offered no way to act on it:


  • the hover Download icon was explicitly hidden for that state β€” .brokenMedia { .icon.commonDownload { display: none; } }

  • clicking the strip opened the fullscreen preview, which is equally broken


  • Download and Open as object existed only in the block's right-click menu, invisible from the placeholder

The state was drawn with img::before / img::after, which only render because the image failed, so it could never hold real content.

On the file object's own page the placeholder never appeared at all. That page's own .wrap override (position: static; height: 100%; line-height: 0px) is more specific than .brokenMedia, so the area rendered as a large empty box with a spinner running forever.

The label was also hardcoded English inside a CSS content: property, so it never translated.

The change


  • The broken state is a render branch in BlockImage instead of a class poked onto the DOM, so it can hold real content.

  • Clicking the placeholder opens the file object, where name, size and sync state are what actually explain the failure. Modifier-clicks behave normally (cmd β†’ tab, cmd+shift β†’ window) and it fires the same OpenAsObject event the block menu does.

  • The hover Download icon is visible again.

  • On the file object's own page it is label-only β€” nothing is left to open and the right sidebar already carries a Download button β€” and it fills the box the page reserves.

  • An error can reach the block before anything is listening, leaving it stuck behind the loader. An image that is already complete with no naturalWidth is that failure, and is now caught on render.


  • "Image is broken" is the blockImageBroken translation key.

Geometry is otherwise unchanged: the wrap keeps the same inline styles as the sibling branches, minus the 80px the loader placeholder contributes β€” nothing is loading in the error state.

Testing

Verified manually against a real broken image (editor block and file object page, light and dark), including the leave-and-reopen path that surfaced the missed-error case. typecheck, lint (0 errors) and build:dev all pass.

Not covered

popup/preview.tsx still uses the CSS pseudo-element approach and its hardcoded English string β€” which also shows "Image is broken" for broken videos. Converting it means reworking the imperative Image() preloader and galleryMapRef, so it is left for a separate change.

PR was closed without comments.