Skip to content

fix(Mime): do not set natural dimensions when embedded - #3338

Open
jospoortvliet wants to merge 1 commit into
nextcloud:masterfrom
jospoortvliet:fix/noid/reference-widget-image-sizing
Open

fix(Mime): do not set natural dimensions when embedded#3338
jospoortvliet wants to merge 1 commit into
nextcloud:masterfrom
jospoortvliet:fix/noid/reference-widget-image-sizing

Conversation

@jospoortvliet

Copy link
Copy Markdown
Member

When using the Smart Picker to view an image, the size of these images is shared with the app, and both Talk and Text take try and display them as such. Now Talk has a different CSS that kind of limits the damage, but it doesn't look great either. Screenshots:

BEFORE: Talk will basically make it fit, distorting the image:
Screenshot 2026-08-23 at 23 09 09

AFTER: No more distortion!
Screenshot 2026-08-23 at 23 20 39

BEFORE: Text just crops (the image on the bottom is the link to the same file as the attachment above it):
Screenshot 2026-08-23 at 23 14 02

AFTER: Looks just fine, can even be resized.
Screenshot 2026-08-23 at 23 16 50

BEFORE: In Text, Tables are entirely broken by inserting an image, as it's rendered 1:1 size and thus creates a huge horizontal scroll.
Screenshot 2026-08-23 at 23 19 11

AFTER: fits nicely in a table cell;
Screenshot 2026-08-23 at 23 18 03

Makes images a lot more useful this way. It does not impact the viewer modal at all - checked that from Talk, Files and Text.

The cause

To let Claude explain the cause of this:

Mime.js's updateHeightWidth() decided whether it was running inside the modal by searching the parent DOM for .modal-wrapper. Anywhere else, it fell through to natural image/video size and wrote that out as a hardcoded inline style, e.g. style="height: 1912px; width: 2940px". The widget's container has overflow: hidden, so only the top-left corner of the image is visible, and in a table cell the oversized intrinsic width blows out the column.

Change

This is what was changed (Claude's words);

  • Declare a new isEmbedded prop on the Mime mixin. The Files widget already passes is-embedded="true" to the handler component, but nothing declared the prop, so it was silently swallowed into $attrs.
  • Return early from updateHeightWidth() when isEmbedded is set, leaving height/width unset. The existing else branch (natural dimensions not yet measured, inside the modal) is untouched.
  • Images.vue's imgStyle returns {} when embedded, instead of computing Math.round(null * zoomRatio)0, which would otherwise render style="height: 0px; width: 0px" and blank the widget entirely.
  • Add a .embedded CSS modifier (max-width/max-height: 100%, object-fit: contain) so the browser sizes the element instead, preserving aspect ratio without upscaling small images.

Applications can work around this bug in their own CSS (Text, Talk), but that's less than ideal.

Testing

  • npm run lint and npm run stylelint pass.
  • Manually verified in the browser: large image, small image (not upscaled).
  • Inside the modal: no visual change. Verified zoom, pan, pinch-zoom, swipe between files.

🤖 AI (if applicable)

Assisted-by: Claude Sonnet 5:claude-sonnet-5

Frankly, Claude did the code/analysis. I tested etc...

  • The content of this PR was partly or fully generated using AI

components (Images.vue, Videos.vue, Audios.vue) are mounted
outside of the Viewer's own modal by other apps, e.g. the Files app's
ReferenceFileWidget for Smart Picker previews. updateHeightWidth()
detected \"inside the modal\" by searching for a .modal-wrapper in the
parent DOM; anywhere else it fell through to natural image/video size,
producing hardcoded inline dimensions such as
style=\"height: 1912px; width: 2940px\" that get clipped by the
widget's overflow: hidden container.

Declare the isEmbedded prop (already passed as is-embedded by
ReferenceFileWidget.vue but previously swallowed into \$attrs) and
return early from updateHeightWidth() when set, leaving height/width
unset. Images.vue's imgStyle must return {} in that case too, since
Math.round(null * zoomRatio) would otherwise emit
style=\"height: 0px; width: 0px\" and blank the widget. Let CSS size
the element instead via a new .embedded modifier using
object-fit: contain, so the aspect ratio is preserved without
upscaling small images.

The modal path (.modal-wrapper found) and the existing \"natural
dimensions not yet measured\" fallback are unchanged.

Assisted-by: Claude Sonnet 5:claude-sonnet-5

Signed-off-by: Jos Poortvliet <jospoortvliet@gmail.com>
@jospoortvliet

Copy link
Copy Markdown
Member Author

just to check - here too - should I recompile and commit assets, or does CI do that?

Please recompile and commit the assets, see the section "Show changes on failure" for details

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