diff --git a/tgui/packages/tgui/byond.js b/tgui/packages/tgui/byond.js index 2adfe6d13f6..2c33d5ffe89 100644 --- a/tgui/packages/tgui/byond.js +++ b/tgui/packages/tgui/byond.js @@ -8,9 +8,11 @@ import { buildQueryString } from 'common/string'; * * @return An integer number or 'null' if this is not a trident engine. */ -export const tridentVersion = (() => { - const { userAgent } = navigator; - const groups = userAgent.match(/Trident\/(\d+).+?;/i); +const tridentVersion = (() => { + const groups = navigator.userAgent.match(/Trident\/(\d+).+?;/i); + if (!groups) { + return null; + } const majorVersion = groups[1]; if (!majorVersion) { return null; @@ -18,6 +20,22 @@ export const tridentVersion = (() => { return parseInt(majorVersion, 10); })(); +/** + * True if browser is an Internet Explorer 8 or lower. + */ +export const IS_IE8 = tridentVersion !== null + && tridentVersion <= 4; + +/** + * True if browser is a BYOND browser. + */ +// We're currently just checking, whether we're running on a localhost +// with a path similar to a BYOND cache. I couldn't find a better/faster +// non-invasive method of doing this. +export const IS_BYOND = tridentVersion !== null + && location.hostname === '127.0.0.1' + && location.pathname.startsWith('/tmp'); + /** * Helper to generate a BYOND href given 'params' as an object * (with an optional 'url' for eg winset). @@ -27,6 +45,10 @@ const createByondUrl = (path, params = {}) => { }; export const callByond = (path, params = {}) => { + // Abort BYOND calls when we're running in a normal browser + if (!IS_BYOND) { + return; + } location.href = createByondUrl(path, params); }; @@ -36,6 +58,10 @@ export const callByond = (path, params = {}) => { * with the return value of that call. */ export const callByondAsync = (url, params = {}) => { + // Abort BYOND calls when we're running in a normal browser + if (!IS_BYOND) { + return new Promise(() => {}); + } // Create a callback array if it doesn't exist yet window.__callbacks__ = window.__callbacks__ || []; // Create a Promise and push its resolve function into callback array diff --git a/tgui/packages/tgui/components/Button.js b/tgui/packages/tgui/components/Button.js index 2ad326e47e6..e5172453432 100644 --- a/tgui/packages/tgui/components/Button.js +++ b/tgui/packages/tgui/components/Button.js @@ -1,6 +1,6 @@ import { classes, pureComponentHooks } from 'common/react'; import { Component, createRef } from 'inferno'; -import { tridentVersion } from '../byond'; +import { IS_IE8 } from '../byond'; import { KEY_ENTER, KEY_ESCAPE, KEY_SPACE } from '../hotkeys'; import { refocusLayout } from '../layouts'; import { createLogger } from '../logging'; @@ -55,7 +55,7 @@ export const Button = props => { className, ])} tabIndex={!disabled && '0'} - unselectable={tridentVersion <= 4} + unselectable={IS_IE8} onclick={e => { refocusLayout(); if (!disabled && onClick) { diff --git a/tgui/packages/tgui/components/ByondUi.js b/tgui/packages/tgui/components/ByondUi.js index 1778969841a..abd60bdcfe5 100644 --- a/tgui/packages/tgui/components/ByondUi.js +++ b/tgui/packages/tgui/components/ByondUi.js @@ -1,7 +1,7 @@ import { shallowDiffers } from 'common/react'; import { debounce } from 'common/timer'; import { Component, createRef } from 'inferno'; -import { callByond, tridentVersion } from '../byond'; +import { callByond, IS_IE8 } from '../byond'; import { createLogger } from '../logging'; import { computeBoxProps } from './Box'; @@ -95,7 +95,7 @@ export class ByondUi extends Component { componentDidMount() { // IE8: It probably works, but fuck you anyway. - if (tridentVersion <= 4) { + if (IS_IE8) { return; } window.addEventListener('resize', this.handleResize); @@ -104,7 +104,7 @@ export class ByondUi extends Component { componentDidUpdate() { // IE8: It probably works, but fuck you anyway. - if (tridentVersion <= 4) { + if (IS_IE8) { return; } const { @@ -121,7 +121,7 @@ export class ByondUi extends Component { componentWillUnmount() { // IE8: It probably works, but fuck you anyway. - if (tridentVersion <= 4) { + if (IS_IE8) { return; } window.removeEventListener('resize', this.handleResize); diff --git a/tgui/packages/tgui/components/Chart.js b/tgui/packages/tgui/components/Chart.js index f54aeac11d4..2f5ad2aedd1 100644 --- a/tgui/packages/tgui/components/Chart.js +++ b/tgui/packages/tgui/components/Chart.js @@ -1,8 +1,8 @@ import { map, zipWith } from 'common/collections'; -import { Component, createRef } from 'inferno'; -import { Box } from './Box'; import { pureComponentHooks } from 'common/react'; -import { tridentVersion } from '../byond'; +import { Component, createRef } from 'inferno'; +import { IS_IE8 } from '../byond'; +import { Box } from './Box'; const normalizeData = (data, scale, rangeX, rangeY) => { if (data.length === 0) { @@ -117,5 +117,5 @@ const Stub = props => null; // IE8: No inline svg support export const Chart = { - Line: tridentVersion <= 4 ? Stub : LineChart, + Line: IS_IE8 ? Stub : LineChart, }; diff --git a/tgui/packages/tgui/components/Flex.js b/tgui/packages/tgui/components/Flex.js index 420f39d079b..04b8d519084 100644 --- a/tgui/packages/tgui/components/Flex.js +++ b/tgui/packages/tgui/components/Flex.js @@ -1,4 +1,5 @@ import { classes, pureComponentHooks } from 'common/react'; +import { IS_IE8 } from '../byond'; import { Box, unit } from './Box'; export const computeFlexProps = props => { @@ -15,6 +16,7 @@ export const computeFlexProps = props => { return { className: classes([ 'Flex', + IS_IE8 && 'Flex--ie8', inline && 'Flex--inline', spacing > 0 && 'Flex--spacing--' + spacing, className, @@ -51,6 +53,7 @@ export const computeFlexItemProps = props => { return { className: classes([ 'Flex__item', + IS_IE8 && 'Flex__item--ie8', className, ]), style: { diff --git a/tgui/packages/tgui/components/Knob.js b/tgui/packages/tgui/components/Knob.js index c13548aa489..501308aea8d 100644 --- a/tgui/packages/tgui/components/Knob.js +++ b/tgui/packages/tgui/components/Knob.js @@ -1,9 +1,18 @@ import { keyOfMatchingRange, scale } from 'common/math'; import { classes } from 'common/react'; +import { IS_IE8 } from '../byond'; import { computeBoxClassName, computeBoxProps } from './Box'; import { DraggableControl } from './DraggableControl'; +import { NumberInput } from './NumberInput'; export const Knob = props => { + // IE8: I don't want to support a yet another component on IE8. + // IE8: It also can't handle SVG. + if (IS_IE8) { + return ( + + ); + } const { // Draggable props (passthrough) animated, @@ -75,11 +84,13 @@ export const Knob = props => { className, computeBoxClassName(rest), ])} - style={{ - 'font-size': size + 'rem', - ...style, - }} - {...computeBoxProps(rest)} + {...computeBoxProps({ + style: { + 'font-size': size + 'rem', + ...style, + }, + ...rest, + })} onMouseDown={handleDragStart}>
(
+ unselectable={IS_IE8}> {value + (unit ? ' ' + unit : '')}
); diff --git a/tgui/packages/tgui/components/Slider.js b/tgui/packages/tgui/components/Slider.js index c8967dcecf6..55ae4ba6c14 100644 --- a/tgui/packages/tgui/components/Slider.js +++ b/tgui/packages/tgui/components/Slider.js @@ -1,9 +1,17 @@ import { clamp01, keyOfMatchingRange, scale } from 'common/math'; import { classes } from 'common/react'; +import { IS_IE8 } from '../byond'; import { computeBoxClassName, computeBoxProps } from './Box'; import { DraggableControl } from './DraggableControl'; +import { NumberInput } from './NumberInput'; export const Slider = props => { + // IE8: I don't want to support a yet another component on IE8. + if (IS_IE8) { + return ( + + ); + } const { // Draggable props (passthrough) animated, diff --git a/tgui/packages/tgui/hotkeys.js b/tgui/packages/tgui/hotkeys.js index b2e4650053a..30c1b910bf4 100644 --- a/tgui/packages/tgui/hotkeys.js +++ b/tgui/packages/tgui/hotkeys.js @@ -1,5 +1,5 @@ +import { callByond, IS_IE8 } from './byond'; import { createLogger } from './logging'; -import { callByond, tridentVersion } from './byond'; const logger = createLogger('hotkeys'); @@ -223,13 +223,13 @@ export const hotKeyMiddleware = store => { subscribeToKeyPresses((e, eventType) => { // IE8: Can't determine the focused element, so by extension it passes // keypresses when inputs are focused. - if (tridentVersion > 4) { + if (!IS_IE8) { handlePassthrough(e, eventType); } handleHotKey(e, eventType, dispatch); }); // IE8: focusin/focusout only available on IE9+ - if (tridentVersion > 4) { + if (!IS_IE8) { // Clean up when browser window completely loses focus subscribeToLossOfFocus(() => { releaseHeldKeys(); diff --git a/tgui/packages/tgui/index.js b/tgui/packages/tgui/index.js index 8a8581a82dc..ff75401f0a8 100644 --- a/tgui/packages/tgui/index.js +++ b/tgui/packages/tgui/index.js @@ -9,14 +9,16 @@ import { loadCSS } from 'fg-loadcss'; import { render } from 'inferno'; import { setupHotReloading } from 'tgui-dev-server/link/client'; import { backendUpdate } from './backend'; -import { tridentVersion } from './byond'; +import { IS_IE8 } from './byond'; import { setupDrag } from './drag'; import { createLogger } from './logging'; import { createStore, StoreProvider } from './store'; +const enteredBundleAt = Date.now(); + const logger = createLogger(); const store = createStore(); -const reactRoot = document.getElementById('react-root'); +let reactRoot; let initialRender = true; @@ -42,6 +44,9 @@ const renderLayout = () => { ); + if (!reactRoot) { + reactRoot = document.getElementById('react-root'); + } render(element, reactRoot); } catch (err) { @@ -51,13 +56,19 @@ const renderLayout = () => { // Report rendering time if (process.env.NODE_ENV !== 'production') { const finishedAt = Date.now(); - const diff = finishedAt - startedAt; - const diffFrames = (diff / 16.6667).toFixed(2); - logger.debug(`rendered in ${diff}ms (${diffFrames} frames)`); if (initialRender) { - const diff = finishedAt - window.__inception__; - const diffFrames = (diff / 16.6667).toFixed(2); - logger.log(`fully loaded in ${diff}ms (${diffFrames} frames)`); + logger.debug('serving from:', location.href); + logger.debug('bundle entered in', timeDiff( + window.__inception__, enteredBundleAt)); + logger.debug('initialized in', timeDiff( + enteredBundleAt, startedAt)); + logger.debug('rendered in', timeDiff( + startedAt, finishedAt)); + logger.log('fully loaded in', timeDiff( + window.__inception__, finishedAt)); + } + else { + logger.debug('rendered in', timeDiff(startedAt, finishedAt)); } } if (initialRender) { @@ -65,6 +76,12 @@ const renderLayout = () => { } }; +const timeDiff = (startedAt, finishedAt) => { + const diff = finishedAt - startedAt; + const diffFrames = (diff / 16.6667).toFixed(2); + return `${diff}ms (${diffFrames} frames)`; +}; + // Parse JSON and report all abnormal JSON strings coming from BYOND const parseStateJson = json => { let reviver = (key, value) => { @@ -77,7 +94,7 @@ const parseStateJson = json => { }; // IE8: No reviver for you! // See: https://stackoverflow.com/questions/1288962 - if (tridentVersion <= 4) { + if (IS_IE8) { reviver = undefined; } try { @@ -130,7 +147,7 @@ const setupApp = () => { }; // IE8: Wait for DOM to properly load -if (tridentVersion <= 4 && document.readyState === 'loading') { +if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', setupApp); } else { diff --git a/tgui/packages/tgui/layouts/Layout.js b/tgui/packages/tgui/layouts/Layout.js index 7a17612fdeb..364564f60aa 100644 --- a/tgui/packages/tgui/layouts/Layout.js +++ b/tgui/packages/tgui/layouts/Layout.js @@ -1,5 +1,5 @@ import { classes } from 'common/react'; -import { tridentVersion } from '../byond'; +import { IS_IE8 } from '../byond'; /** * Brings Layout__content DOM element back to focus. @@ -8,7 +8,7 @@ import { tridentVersion } from '../byond'; */ export const refocusLayout = () => { // IE8: Focus method is seemingly fucked. - if (tridentVersion <= 4) { + if (IS_IE8) { return; } const element = document.getElementById('Layout__content'); diff --git a/tgui/packages/tgui/layouts/Window.js b/tgui/packages/tgui/layouts/Window.js index 21f8e1792da..2b8fafdf9ea 100644 --- a/tgui/packages/tgui/layouts/Window.js +++ b/tgui/packages/tgui/layouts/Window.js @@ -2,7 +2,7 @@ import { classes } from 'common/react'; import { decodeHtmlEntities, toTitleCase } from 'common/string'; import { Component, Fragment } from 'inferno'; import { useBackend } from '../backend'; -import { runCommand, tridentVersion, winset } from '../byond'; +import { IS_IE8, runCommand, winset } from '../byond'; import { Box, Icon } from '../components'; import { UI_DISABLED, UI_INTERACTIVE, UI_UPDATE } from '../constants'; import { dragStartHandler, resizeStartHandler } from '../drag'; @@ -134,7 +134,7 @@ const TitleBar = props => { // IE8: Use a plain character instead of a unicode symbol. // eslint-disable-next-line react/no-unknown-property onclick={onClose}> - {tridentVersion <= 4 ? 'x' : '×'} + {IS_IE8 ? 'x' : '×'}
)}
diff --git a/tgui/packages/tgui/public/shim-css-om.js b/tgui/packages/tgui/public/shim-css-om.js index 82964c71c7a..f7382ca7c7d 100644 --- a/tgui/packages/tgui/public/shim-css-om.js +++ b/tgui/packages/tgui/public/shim-css-om.js @@ -7,7 +7,7 @@ (function(Proto) { function toAttr(prop) { - return prop.replace(/-[a-z]/g, function(bit) { + return prop.replace(/-[a-z]/g, function (bit) { return bit[1].toUpperCase(); }); }