From 873c56afdf4ed99f3cf4b058798a0b2294b5a34b Mon Sep 17 00:00:00 2001 From: Jos Poortvliet Date: Sun, 23 Aug 2026 20:19:13 +0200 Subject: [PATCH] fix(Mime): do not set natural dimensions when embedded Handler 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 --- src/components/Images.vue | 18 ++++++++++++++++-- src/mixins/Mime.js | 10 ++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/components/Images.vue b/src/components/Images.vue index dd07e1441..971b3bb80 100644 --- a/src/components/Images.vue +++ b/src/components/Images.vue @@ -18,7 +18,8 @@ :class="{ dragging, loaded, - zoomed: zoomRatio > 1 + zoomed: zoomRatio > 1, + embedded: isEmbedded }" :src="data" :style="imgStyle" @@ -36,7 +37,8 @@ :class="{ dragging, loaded, - zoomed: zoomRatio > 1 + zoomed: zoomRatio > 1, + embedded: isEmbedded }" :style="imgStyle" :playsinline="true" @@ -134,6 +136,10 @@ export default { return this.basename }, imgStyle() { + // let CSS size the element instead of forcing dimensions in JS + if (this.isEmbedded) { + return {} + } if (this.zoomRatio === 1) { return { height: this.zoomHeight + 'px', @@ -492,6 +498,14 @@ img, video { transition: none !important; cursor: move; } + + &.embedded { + max-width: 100%; + max-height: 100%; + width: auto; + height: auto; + object-fit: contain; + } } .live-photo_play_button { diff --git a/src/mixins/Mime.js b/src/mixins/Mime.js index 7e530190d..6e022b06d 100644 --- a/src/mixins/Mime.js +++ b/src/mixins/Mime.js @@ -85,6 +85,11 @@ export default { type: Number, default: undefined, }, + // is the component mounted outside of the viewer modal? + isEmbedded: { + type: Boolean, + default: false, + }, }, data() { @@ -157,6 +162,11 @@ export default { * based on the viewer maximum size */ updateHeightWidth() { + // let CSS size the element when mounted outside of the viewer modal + if (this.isEmbedded) { + return + } + const modalWrapper = this.$parent.$el.querySelector('.modal-wrapper') if (modalWrapper && this.naturalHeight > 0 && this.naturalWidth > 0) { const modalContainer = modalWrapper.querySelector('.modal-container')