import sysLogger from './sysLogger.mjs'; /** * @param {Object} page - Puppeteer * @param {Object} options - * @param {number} options.width - * @param {number} options.height - * @param {number} options.deviceScaleFactor - * @param {boolean} options.isMobile - * @param {boolean} options.hasTouch - * @param {boolean} options.isLandscape - * @returns {Promise} */ export async function fixBrowserDisplay(page, options = {}) { if (!page) { sysLogger.error('Page object is empty, unable to fix display'); return; } const defaultOptions = { width: 1280, height: 800, deviceScaleFactor: 1, isMobile: false, hasTouch: false, isLandscape: true }; const settings = {...defaultOptions, ...options}; try { // Set viewport size and device ratio await page.setViewport({ width: settings.width, height: settings.height, deviceScaleFactor: settings.deviceScaleFactor, isMobile: settings.isMobile, hasTouch: settings.hasTouch, isLandscape: settings.isLandscape }); // Try resizing window const session = await page.target().createCDPSession(); await session.send('Emulation.setDeviceMetricsOverride', { width: settings.width, height: settings.height, deviceScaleFactor: settings.deviceScaleFactor, mobile: settings.isMobile, screenWidth: settings.width, screenHeight: settings.height }); // Reset page zoom await page.evaluate(() => { document.body.style.zoom = '100%'; document.body.style.transform = 'scale(1)'; document.body.style.transformOrigin = '0 0'; // Attempt to fix possible CSS const styleElement = document.createElement('style'); styleElement.textContent = ` html, body { width: 100% !important; height: 100% !important; overflow: auto !important; } .container, .main, #app, #root { max-width: 100% !important; width: auto !important; } `; document.head.appendChild(styleElement); window.dispatchEvent(new Event('resize')); }); } catch (error) { sysLogger.error('Browser:', error); } } /** * CSS * @param {Object} page - Puppeteer * @param {number} scale - * @returns {Promise} */ export async function adjustCssScaling(page, scale = 1) { if (!page) return; try { await page.evaluate((scale) => { const styleElem = document.createElement('style'); styleElem.id = 'puppeteer-display-fix'; styleElem.textContent = ` html { transform: scale(${scale}); transform-origin: top left; width: ${100 / scale}% !important; height: ${100 / scale}% !important; } `; document.head.appendChild(styleElem); // Recalculate layout window.dispatchEvent(new Event('resize')); }, scale); } catch (error) { sysLogger.error('Error adjusting CSS ratio:', error); } } /** * DPI * @param {Object} page - Puppeteer * @returns {Promise} */ export async function fixHighDpiDisplay(page) { if (!page) return; try { // Detect device pixel ratio const devicePixelRatio = await page.evaluate(() => window.devicePixelRatio); if (devicePixelRatio > 1) { await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: devicePixelRatio }); await page.evaluate((dpr) => { const meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', `initial-scale=1, minimum-scale=1, maximum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi, user-scalable=no`); document.head.appendChild(meta); }, devicePixelRatio); } } catch (error) { sysLogger.error('Fix High-DPI display:', error); } } /** * Browser * @param {Object} page - Puppeteer * @param {Object} options - * @returns {Promise} */ export async function optimizeBrowserDisplay(page, options = {}) { const defaultOptions = { width: 1280, height: 800, deviceScaleFactor: 1, cssScale: null, fixHighDpi: true, forceResize: true }; const config = {...defaultOptions, ...options}; try { // Basic display fix await fixBrowserDisplay(page, { width: config.width, height: config.height, deviceScaleFactor: config.deviceScaleFactor }); // Fix High-DPI display if (config.fixHighDpi) { await fixHighDpiDisplay(page); } if (config.cssScale !== null) { await adjustCssScaling(page, config.cssScale); } // If forced to resize window if (config.forceResize && !config.isHeadless) { try { const client = await page.target().createCDPSession(); await client.send('Browser.getWindowForTarget'); await client.send('Browser.setWindowBounds', { windowId: 1, bounds: { width: config.width, height: config.height } }); } catch (resizeError) { // sysLogger.debug('Unable to resize window:', resizeError.message); try { await page.evaluate((width, height) => { window.resizeTo(width, height); }, config.width, config.height); } catch (altError) { sysLogger.debug('Failed:', altError.message); } } } } catch (error) { sysLogger.error('BrowserDisplay optimization failed:', error); } }