Unlock/allow resize once screenshot is done

This commit is contained in:
dgtlmoon
2025-12-18 17:44:48 +01:00
parent ddeba6e4cc
commit a6516d2bad
3 changed files with 34 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ async def capture_full_page_async(page, screenshot_format='JPEG'):
step_size = SCREENSHOT_SIZE_STITCH_THRESHOLD # Size that won't cause GPU to overflow
screenshot_chunks = []
y = 0
elements_locked = False
if page_height > page.viewport_size['height']:
@@ -35,6 +36,7 @@ async def capture_full_page_async(page, screenshot_format='JPEG'):
with open(lock_elements_js_path, 'r') as f:
lock_elements_js = f.read()
await page.evaluate(lock_elements_js)
elements_locked = True
logger.debug("Element dimensions locked before screenshot capture")
@@ -72,6 +74,14 @@ async def capture_full_page_async(page, screenshot_format='JPEG'):
# Restore original viewport size
await page.set_viewport_size({'width': original_viewport['width'], 'height': original_viewport['height']})
# Unlock element dimensions if they were locked
if elements_locked:
unlock_elements_js_path = os.path.join(os.path.dirname(__file__), 'res', 'unlock-elements-sizing.js')
with open(unlock_elements_js_path, 'r') as f:
unlock_elements_js = f.read()
await page.evaluate(unlock_elements_js)
logger.debug("Element dimensions unlocked after screenshot capture")
# If we have multiple chunks, stitch them together
if len(screenshot_chunks) > 1:
logger.debug(f"Screenshot stitching {len(screenshot_chunks)} chunks together")

View File

@@ -49,6 +49,7 @@ async def capture_full_page(page, screenshot_format='JPEG'):
step_size = SCREENSHOT_SIZE_STITCH_THRESHOLD # Something that will not cause the GPU to overflow when taking the screenshot
screenshot_chunks = []
y = 0
elements_locked = False
if page_height > page.viewport['height']:
# Lock all element dimensions BEFORE screenshot to prevent CSS media queries from resizing
# capture_full_page() changes viewport height which triggers @media (min-height) rules
@@ -56,6 +57,7 @@ async def capture_full_page(page, screenshot_format='JPEG'):
with open(lock_elements_js_path, 'r') as f:
lock_elements_js = f.read()
await page.evaluate(lock_elements_js)
elements_locked = True
logger.debug("Element dimensions locked before screenshot capture")
if page_height < step_size:
@@ -85,6 +87,14 @@ async def capture_full_page(page, screenshot_format='JPEG'):
await page.setViewport({'width': original_viewport['width'], 'height': original_viewport['height']})
# Unlock element dimensions if they were locked
if elements_locked:
unlock_elements_js_path = os.path.join(os.path.dirname(__file__), 'res', 'unlock-elements-sizing.js')
with open(unlock_elements_js_path, 'r') as f:
unlock_elements_js = f.read()
await page.evaluate(unlock_elements_js)
logger.debug("Element dimensions unlocked after screenshot capture")
if len(screenshot_chunks) > 1:
from changedetectionio.content_fetchers.screenshot_handler import stitch_images_worker
logger.debug(f"Screenshot stitching {len(screenshot_chunks)} chunks together")

View File

@@ -49,11 +49,25 @@
*/
(() => {
// Store original styles in a global WeakMap for later restoration
window.__elementSizingRestore = new WeakMap();
// Lock ALL element dimensions to prevent media query layout changes
document.querySelectorAll('*').forEach(el => {
const computed = window.getComputedStyle(el);
const rect = el.getBoundingClientRect();
// Save original inline style values BEFORE locking
const properties = ['height', 'min-height', 'max-height', 'width', 'min-width', 'max-width'];
const originalStyles = {};
properties.forEach(prop => {
originalStyles[prop] = {
value: el.style.getPropertyValue(prop),
priority: el.style.getPropertyPriority(prop)
};
});
window.__elementSizingRestore.set(el, originalStyles);
// Lock dimensions with !important to override media queries
if (rect.height > 0) {
el.style.setProperty('height', computed.height, 'important');