Files
youchat_proxy/src/utils/browserDisplayFixer.mjs
T

208 lines
6.2 KiB
JavaScript

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<void>}
*/
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<void>}
*/
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<void>}
*/
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<void>}
*/
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);
}
}