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 })}
`
}