diff --git a/static/src/css/sign_image_field.css b/static/src/css/sign_image_field.css index 854be79..fd9cee7 100644 --- a/static/src/css/sign_image_field.css +++ b/static/src/css/sign_image_field.css @@ -48,4 +48,20 @@ body div.o_sign_sign_item.o_sign_image_item span.o_placeholder { justify-content: center; width: 100%; height: 100%; + position: relative; +} + +.o_sign_image_loading { + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: o_sign_image_shimmer 1.5s infinite linear; +} + +@keyframes o_sign_image_shimmer { + 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } +} + +.o_sign_image_lazy { + transition: opacity 0.5s ease-in-out; } \ No newline at end of file diff --git a/static/src/js/sign_image_upload.js b/static/src/js/sign_image_upload.js index 48e8463..767721e 100755 --- a/static/src/js/sign_image_upload.js +++ b/static/src/js/sign_image_upload.js @@ -107,6 +107,24 @@ patch(SignablePDFIframe.prototype, { }; reader.readAsDataURL(file); }); + + // Performance Fix: Lazy Load existing images + const lazyImg = el.querySelector('.o_sign_image_lazy'); + if (lazyImg && lazyImg.dataset.src) { + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + lazyImg.src = lazyImg.dataset.src; + lazyImg.onload = () => { + lazyImg.classList.remove('o_sign_image_loading'); + lazyImg.style.opacity = 1; + }; + observer.unobserve(lazyImg); + } + }); + }, { rootMargin: '200px' }); // Load 200px before reaching viewport + observer.observe(lazyImg); + } } }, diff --git a/static/src/xml/sign_items_image.xml b/static/src/xml/sign_items_image.xml index 65fc28c..5be2477 100755 --- a/static/src/xml/sign_items_image.xml +++ b/static/src/xml/sign_items_image.xml @@ -8,7 +8,7 @@