import { captureError } from '../errors' import { lieProps, documentLie } from '../lies' import { createTimer, IS_GECKO, logTestResult, performanceLogger, hashSlice, LowerEntropy, IS_WEBKIT } from '../utils/helpers' import { HTMLNote, patch, html } from '../utils/html' function hasTouch() { try { return 'ontouchstart' in window && !!document.createEvent('TouchEvent') } catch (err) { return false } } export default async function getScreen(log = true) { try { const timer = createTimer() timer.start() let lied = ( lieProps['Screen.width'] || lieProps['Screen.height'] || lieProps['Screen.availWidth'] || lieProps['Screen.availHeight'] || lieProps['Screen.colorDepth'] || lieProps['Screen.pixelDepth'] ) || false const s = (window.screen || {}) const { width, height, availWidth, availHeight, colorDepth, pixelDepth, } = s const dpr = window.devicePixelRatio || 0 const firefoxWithHighDPR = IS_GECKO && (dpr != 1) if (!firefoxWithHighDPR) { // firefox with high dpr requires floating point precision dimensions const matchMediaLie = !matchMedia( `(device-width: ${width}px) and (device-height: ${height}px)`, ).matches if (matchMediaLie) { lied = true documentLie('Screen', 'failed matchMedia') } } const hasLiedDPR = !matchMedia(`(resolution: ${dpr}dppx)`).matches if (!IS_WEBKIT && hasLiedDPR) { lied = true documentLie('Window.devicePixelRatio', 'lied dpr') } const noTaskbar = !(width - availWidth || height - availHeight) if (width > 800 && noTaskbar) { LowerEntropy.SCREEN = true } const data = { width, height, availWidth, availHeight, colorDepth, pixelDepth, touch: hasTouch(), lied, } log && logTestResult({ time: timer.stop(), test: 'screen', passed: true }) return data } catch (error) { log && logTestResult({ test: 'screen', passed: false }) captureError(error) return } } export function screenHTML(fp) { if (!fp.screen) { return `
Screen
...screen: ${HTMLNote.BLOCKED}
....avail: ${HTMLNote.BLOCKED}
touch: ${HTMLNote.BLOCKED}
depth: ${HTMLNote.BLOCKED}
viewport: ${HTMLNote.BLOCKED}
` } const { screen: data, } = fp const { $hash } = data || {} const perf = performanceLogger.getLog().screen const paintScreen = (event) => { const el = document.getElementById('creep-resize') if (!el) { return } removeEventListener('resize', paintScreen) return getScreen(false).then((data) => { requestAnimationFrame( () => patch(el, html`${resizeHTML(({ data, $hash, perf, paintScreen }))}`), ) }) } const resizeHTML = ({ data, $hash, perf, paintScreen }) => { const { width, height, availWidth, availHeight, colorDepth, pixelDepth, touch, lied, } = data addEventListener('resize', paintScreen) const s = (window.screen || {}) const { orientation } = s const { type: orientationType } = orientation || {} const dpr = window.devicePixelRatio || undefined const { width: vVWidth, height: vVHeight } = (window.visualViewport || {}) const mediaOrientation = !window.matchMedia ? undefined : ( matchMedia('(orientation: landscape)').matches ? 'landscape' : matchMedia('(orientation: portrait)').matches ? 'portrait' : undefined ) const displayMode = !window.matchMedia ? undefined : ( matchMedia('(display-mode: fullscreen)').matches ? 'fullscreen' : matchMedia('(display-mode: standalone)').matches ? 'standalone' : matchMedia('(display-mode: minimal-ui)').matches ? 'minimal-ui' : matchMedia('(display-mode: browser)').matches ? 'browser' : undefined ) const getDeviceDimensions = (width, height, diameter = 180) => { const aspectRatio = width / height const isPortrait = height > width const deviceWidth = isPortrait ? diameter * aspectRatio : diameter const deviceHeight = isPortrait ? diameter : diameter / aspectRatio return { deviceWidth, deviceHeight } } // const { deviceWidth, deviceHeight } = getDeviceDimensions(width, height) const { deviceWidth: deviceInnerWidth, deviceHeight: deviceInnerHeight } = getDeviceDimensions(innerWidth, innerHeight) const toFix = (n, nFix) => { const d = +(1+[...Array(nFix)].map((x) => 0).join('')) return Math.round(n*d)/d } const viewportTitle = `Window.outerWidth\nWindow.outerHeight\nWindow.innerWidth\nWindow.innerHeight\nVisualViewport.width\nVisualViewport.height\nWindow.matchMedia()\nScreenOrientation.type\nWindow.devicePixelRatio` return `
${perf} Screen${hashSlice($hash)}
...screen: ${width} x ${height}
....avail: ${availWidth} x ${availHeight}
touch: ${touch}
depth: ${colorDepth}|${pixelDepth}
viewport:
${outerWidth} ${innerWidth} ${toFix(vVWidth, 6)} ${outerHeight} ${innerHeight} ${toFix(vVHeight, 6)} ${displayMode} ${mediaOrientation} ${orientationType} ${dpr}
` } return ` ${resizeHTML({ data, $hash, perf, paintScreen })} ` }