diff --git a/static/src/js/sign_image_upload.js b/static/src/js/sign_image_upload.js index 709f187..3f97341 100755 --- a/static/src/js/sign_image_upload.js +++ b/static/src/js/sign_image_upload.js @@ -1,9 +1,63 @@ /** @odoo-module **/ import { patch } from "@web/core/utils/patch"; +import { PDFIframe } from "@sign/components/sign_request/PDF_iframe"; import { SignablePDFIframe } from "@sign/components/sign_request/signable_PDF_iframe"; +/** + * Shared logic for triggered lazy loading of images. + * This ensures that when a sign item element is created or scrolled into view, + * its image is loaded from the data-src attribute. + */ +const lazyLoadMixin = { + _triggerLazyLoad(el) { + if (!el) return; + const lazyImg = el.querySelector('.o_sign_image_lazy'); + if (lazyImg && lazyImg.dataset.src) { + const currentSrc = lazyImg.getAttribute('src'); + // Check if it's currently showing the transparent placeholder + if (!currentSrc || currentSrc.startsWith('data:image/gif')) { + lazyImg.src = lazyImg.dataset.src; + lazyImg.onload = () => { + lazyImg.classList.remove('o_sign_image_loading'); + el.classList.remove('o_sign_image_loading_container'); + lazyImg.style.opacity = 1; + }; + } + } + }, + + refreshSignItemsForPage(page) { + super.refreshSignItemsForPage(page); + if (this.signItems && this.signItems[page]) { + for (const id in this.signItems[page]) { + const item = this.signItems[page][id]; + if (item && item.el) { + this._triggerLazyLoad(item.el); + } + } + } + } +}; + +// 1. Patch the base PDFIframe for shared lazy-loading logic (covers read-only views) +patch(PDFIframe.prototype, { + ...lazyLoadMixin, + + // We also hook into enableCustom to trigger lazy load for initial items + enableCustom(signItem) { + super.enableCustom(signItem); + if (signItem.data.type === 'image') { + this._triggerLazyLoad(signItem.el); + } + } +}); + +// 2. Patch SignablePDFIframe for upload handlers and specific behaviors (covers signing views) patch(SignablePDFIframe.prototype, { + // Note: Mixin methods are already inherited if not overwritten, + // but SignablePDFIframe might need its own hooks. + enableCustom(signItem) { super.enableCustom(signItem); if (signItem.data.type === 'image') { @@ -13,33 +67,23 @@ patch(SignablePDFIframe.prototype, { // Add data-type attribute for CSS targeting el.setAttribute('data-type', 'image'); - // Function to adjust font size based on container dimensions + // Initial font size adjustment for placeholder text const adjustFontSize = () => { const placeholder = el.querySelector('.o_placeholder'); if (placeholder) { - const containerHeight = el.offsetHeight; - const containerWidth = el.offsetWidth; - const minDimension = Math.min(containerHeight, containerWidth); + const minDimension = Math.min(el.offsetHeight, el.offsetWidth); const fontSize = Math.max(10, Math.min(16, minDimension * 0.4)); placeholder.style.fontSize = fontSize + 'px !important'; placeholder.style.lineHeight = '1'; } }; - - // Initial font size adjustment setTimeout(adjustFontSize, 100); - // Watch for size changes - if (window.ResizeObserver) { - const resizeObserver = new ResizeObserver(adjustFontSize); - resizeObserver.observe(el); - } - + // Upload implementation const input = el.querySelector('.o_sign_image_upload_input'); if (input) { el.addEventListener('click', (e) => { if (this.readonly || (data.responsible > 0 && data.responsible !== this.currentRole)) return; - // Prevent recursive click if clicking the input itself bubbles up if (e.target !== input) { input.click(); } @@ -56,33 +100,26 @@ patch(SignablePDFIframe.prototype, { const canvas = document.createElement('canvas'); let width = img.width; let height = img.height; - const MAX_SIZE = 1080; if (width > height) { if (width > MAX_SIZE) { height *= MAX_SIZE / width; width = MAX_SIZE; } - } else { - if (height > MAX_SIZE) { - width *= MAX_SIZE / height; - height = MAX_SIZE; - } + } else if (height > MAX_SIZE) { + width *= MAX_SIZE / height; + height = MAX_SIZE; } canvas.width = width; canvas.height = height; - const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, width, height); const compressedDataUrl = canvas.toDataURL('image/jpeg', 0.7); - - // Update state and element data.value = compressedDataUrl; el.dataset.value = compressedDataUrl; - // Force immediate display update const placeholder = el.querySelector('.o_placeholder'); if (placeholder) placeholder.remove(); @@ -97,7 +134,6 @@ patch(SignablePDFIframe.prototype, { } existingImg.src = compressedDataUrl; - // Notify Odoo of the value change if (this.handleInput) { this.handleInput(); } @@ -108,44 +144,11 @@ patch(SignablePDFIframe.prototype, { }); } - // Performance Fix: Trigger lazy load if already visible + // Immediately trigger load if value exists this._triggerLazyLoad(el); } }, - refreshSignItemsForPage(page) { - super.refreshSignItemsForPage(page); - if (this.signItems && this.signItems[page]) { - for (const id in this.signItems[page]) { - const item = this.signItems[page][id]; - if (item && item.el) { - this._triggerLazyLoad(item.el); - } - } - } - }, - - /** - * Triggers the load of a lazy-loaded image if it has a data-src attribute - * @param {HTMLElement} el - */ - _triggerLazyLoad(el) { - if (!el) return; - const lazyImg = el.querySelector('.o_sign_image_lazy'); - if (lazyImg && lazyImg.dataset.src) { - const currentSrc = lazyImg.getAttribute('src'); - // If src is still the transparent placeholder gif or empty, load the real image - if (!currentSrc || currentSrc.startsWith('data:image/gif')) { - lazyImg.src = lazyImg.dataset.src; - lazyImg.onload = () => { - lazyImg.classList.remove('o_sign_image_loading'); - el.classList.remove('o_sign_image_loading_container'); - lazyImg.style.opacity = 1; - }; - } - } - }, - getSignatureValueFromElement(item) { if (item.data.type === 'image') { return item.el.dataset.value || item.data.value || false;