From a327e7d33f8d23d9f7caa70af3c6be659da36080 Mon Sep 17 00:00:00 2001 From: Letter N <24603524+LetterN@users.noreply.github.com> Date: Sat, 15 Aug 2020 16:48:10 +0800 Subject: [PATCH] no thoughts, head segfaulted --- tgui/packages/tgui-dev-server/link/retrace.js | 4 + .../tgui/interfaces/AtmosControlPanel.js | 127 ++++++++++++ .../packages/tgui/interfaces/CameraConsole.js | 11 +- tgui/packages/tgui/interfaces/Cargo.js | 56 +++--- .../tgui/interfaces/ComputerFabricator.js | 11 +- .../tgui/interfaces/GhostPoolProtection.js | 102 ++++++++++ .../tgui/interfaces/MechpadConsole.js | 97 ++++++++++ tgui/packages/tgui/interfaces/NtosMain.js | 40 ++++ tgui/packages/tgui/interfaces/NtosRadar.js | 5 +- .../tgui/interfaces/NtosRadarSyndicate.js | 2 +- tgui/packages/tgui/interfaces/PaperSheet.js | 17 +- tgui/packages/tgui/interfaces/Photocopier.js | 182 ++++++++++++++++++ tgui/packages/tgui/interfaces/Wires.js | 12 +- tgui/packages/tgui/layouts/Layout.js | 30 ++- tgui/packages/tgui/layouts/index.js | 3 +- 15 files changed, 628 insertions(+), 71 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/AtmosControlPanel.js create mode 100644 tgui/packages/tgui/interfaces/GhostPoolProtection.js create mode 100644 tgui/packages/tgui/interfaces/MechpadConsole.js create mode 100644 tgui/packages/tgui/interfaces/Photocopier.js diff --git a/tgui/packages/tgui-dev-server/link/retrace.js b/tgui/packages/tgui-dev-server/link/retrace.js index e0b17a01d6..4bcb8e40c6 100644 --- a/tgui/packages/tgui-dev-server/link/retrace.js +++ b/tgui/packages/tgui-dev-server/link/retrace.js @@ -39,6 +39,10 @@ export const loadSourceMaps = async bundleDir => { }; export const retrace = stack => { + if (typeof stack !== 'string') { + logger.log('ERROR: Stack is not a string!', stack); + return stack; + } const header = stack.split(/\n\s.*at/)[0]; const mappedStack = StackTraceParser.parse(stack) .map(frame => { diff --git a/tgui/packages/tgui/interfaces/AtmosControlPanel.js b/tgui/packages/tgui/interfaces/AtmosControlPanel.js new file mode 100644 index 0000000000..bf9d4c033a --- /dev/null +++ b/tgui/packages/tgui/interfaces/AtmosControlPanel.js @@ -0,0 +1,127 @@ +import { map, sortBy } from 'common/collections'; +import { flow } from 'common/fp'; +import { useBackend } from '../backend'; +import { Box, Button, Flex, Section, Table } from '../components'; +import { Window } from '../layouts'; + +export const AtmosControlPanel = (props, context) => { + const { act, data } = useBackend(context); + const groups = flow([ + map((group, i) => ({ + ...group, + // Generate a unique id + id: group.area + i, + })), + sortBy(group => group.id), + ])(data.excited_groups); + return ( + +
+ + + + + + Fire Cnt: {data.fire_count} + + + Active Turfs: {data.active_size} + + + Excited Groups: {data.excited_size} + + + Hotspots: {data.hotspots_size} + + + Superconductors: {data.conducting_size} + + + act('toggle_user_display')}> + Personal View + + + + act('toggle_show_all')}> + Display all + + + +
+ + +
+ + + + Area Name + + + Breakdown + + + Dismantle + + + Turfs + + + {data.display_max === 1 && "Max Share"} + + + Display + + + {groups.map(group => ( + + + + + + + + + ))} +
+ + {group.breakdown} + + {group.dismantle} + + {group.size} + + {data.display_max === 1 && group.max_share} + + act('toggle_show_group', { + group: group.group, + })} /> +
+
+
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/CameraConsole.js b/tgui/packages/tgui/interfaces/CameraConsole.js index 6437769a78..fefa3981db 100644 --- a/tgui/packages/tgui/interfaces/CameraConsole.js +++ b/tgui/packages/tgui/interfaces/CameraConsole.js @@ -5,7 +5,7 @@ import { createSearch } from 'common/string'; import { Fragment } from 'inferno'; import { useBackend, useLocalState } from '../backend'; import { Button, ByondUi, Input, Section } from '../components'; -import { refocusLayout, Window } from '../layouts'; +import { Window } from '../layouts'; /** * Returns previous and next camera names relative to the currently @@ -123,12 +123,9 @@ export const CameraConsoleContent = (props, context) => { && camera.name === activeCamera.name && 'Button--selected', ])} - onClick={() => { - refocusLayout(); - act('switch_camera', { - name: camera.name, - }); - }}> + onClick={() => act('switch_camera', { + name: camera.name, + })}> {camera.name} ))} diff --git a/tgui/packages/tgui/interfaces/Cargo.js b/tgui/packages/tgui/interfaces/Cargo.js index c270a37a10..9854e21833 100644 --- a/tgui/packages/tgui/interfaces/Cargo.js +++ b/tgui/packages/tgui/interfaces/Cargo.js @@ -20,34 +20,36 @@ export const Cargo = (props, context) => { resizable> - - setTab('catalog')}> - Catalog - - 0 - && 'yellow'} - selected={tab === 'requests'} - onClick={() => setTab('requests')}> - Requests ({requests.length}) - - {!requestonly && ( +
+ 0 - && 'yellow'} - selected={tab === 'cart'} - onClick={() => setTab('cart')}> - Checkout ({cart.length}) + icon="list" + selected={tab === 'catalog'} + onClick={() => setTab('catalog')}> + Catalog - )} - + 0 + && 'yellow'} + selected={tab === 'requests'} + onClick={() => setTab('requests')}> + Requests ({requests.length}) + + {!requestonly && ( + 0 + && 'yellow'} + selected={tab === 'cart'} + onClick={() => setTab('cart')}> + Checkout ({cart.length}) + + )} + +
{tab === 'catalog' && ( )} @@ -143,7 +145,7 @@ export const CargoCatalog = (props, context) => { )}> - + {supplies.map(supply => ( { - Card Reader: + Secondary Card Reader: diff --git a/tgui/packages/tgui/interfaces/GhostPoolProtection.js b/tgui/packages/tgui/interfaces/GhostPoolProtection.js new file mode 100644 index 0000000000..92a98c96fc --- /dev/null +++ b/tgui/packages/tgui/interfaces/GhostPoolProtection.js @@ -0,0 +1,102 @@ +import { useBackend } from '../backend'; +import { Button, Flex, Fragment, Section, NoticeBox } from '../components'; +import { Window } from '../layouts'; + +export const GhostPoolProtection = (props, context) => { + const { act, data } = useBackend(context); + const { + events_or_midrounds, + spawners, + station_sentience, + silicons, + minigames, + } = data; + return ( + + + +
+
+
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/MechpadConsole.js b/tgui/packages/tgui/interfaces/MechpadConsole.js new file mode 100644 index 0000000000..cc9086cc6e --- /dev/null +++ b/tgui/packages/tgui/interfaces/MechpadConsole.js @@ -0,0 +1,97 @@ +import { useBackend } from '../backend'; +import { Box, Button, Divider, Flex, Grid, Input, NoticeBox, NumberInput, Section } from '../components'; +import { Window } from '../layouts'; + +export const MechpadControl = (props, context) => { + const { topLevel } = props; + const { act, data } = useBackend(context); + const { + pad_name, + connected_mechpad, + } = data; + return ( +
act('rename', { + name: value, + })} /> + )} + level={topLevel ? 1 : 2} + buttons={( +
+ ); +}; + +export const MechpadConsole = (props, context) => { + const { act, data } = useBackend(context); + const { + mechpads = [], + selected_id, + } = data; + return ( + + + {mechpads.length === 0 && ( + + No Pads Connected + + ) || ( +
+ + + {mechpads.map(mechpad => ( +
+ )} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/NtosMain.js b/tgui/packages/tgui/interfaces/NtosMain.js index c61767bd7b..7f26d20188 100644 --- a/tgui/packages/tgui/interfaces/NtosMain.js +++ b/tgui/packages/tgui/interfaces/NtosMain.js @@ -28,6 +28,8 @@ export const NtosMain = (props, context) => { has_light, light_on, comp_light_color, + removable_media = [], + login = [], } = data; return ( { )} +
act('PC_Eject_Disk', { name: "ID" })} + /> + )}> + + + ID Name: {login.IDName} + + + Assignment: {login.IDJob} + +
+
+ {!!removable_media.length && ( +
+ + {removable_media.map(device => ( + + +
+
+ )}
{programs.map(program => ( diff --git a/tgui/packages/tgui/interfaces/NtosRadar.js b/tgui/packages/tgui/interfaces/NtosRadar.js index 2d2fe6a452..3ba8683574 100644 --- a/tgui/packages/tgui/interfaces/NtosRadar.js +++ b/tgui/packages/tgui/interfaces/NtosRadar.js @@ -10,7 +10,7 @@ export const NtosRadar = (props, context) => { width={800} height={600} theme="ntos"> - + ); }; @@ -23,6 +23,7 @@ export const NtosRadarContent = (props, context) => { target = [], scanning, } = data; + const { sig_err } = props; return ( { width={42} fontSize="30px" textAlign="center"> - Signal Lost + {sig_err} ) : !!target.userot && ( diff --git a/tgui/packages/tgui/interfaces/NtosRadarSyndicate.js b/tgui/packages/tgui/interfaces/NtosRadarSyndicate.js index 3cb4626bb9..2ce76c0a94 100644 --- a/tgui/packages/tgui/interfaces/NtosRadarSyndicate.js +++ b/tgui/packages/tgui/interfaces/NtosRadarSyndicate.js @@ -7,7 +7,7 @@ export const NtosRadarSyndicate = (props, context) => { width={800} height={600} theme="syndicate"> - + ); }; diff --git a/tgui/packages/tgui/interfaces/PaperSheet.js b/tgui/packages/tgui/interfaces/PaperSheet.js index b3f4a945c8..b79538a9f9 100644 --- a/tgui/packages/tgui/interfaces/PaperSheet.js +++ b/tgui/packages/tgui/interfaces/PaperSheet.js @@ -6,7 +6,7 @@ * @license MIT */ -import { classes, isFalsy } from "common/react"; +import { classes } from 'common/react'; import { vecScale, vecSubtract } from 'common/vector'; import DOMPurify from 'dompurify'; import { Component } from 'inferno'; @@ -241,13 +241,11 @@ const PaperSheetView = (props, context) => { stamps, backgroundColor, readOnly, - ...rest } = props; - const readonly = !isFalsy(readOnly); const stamp_list = stamps || []; const text_html = { __html: '' - + setInputReadonly(value, readonly) + + setInputReadonly(value, readOnly) + '', }; return ( @@ -323,7 +321,12 @@ class PaperSheetStamper extends Component { handleMouseClick(e) { const pos = this.findStampPosition(e); const { act, data } = useBackend(this.context); - act("stamp", { x: pos[0], y: pos[1], r: this.state.rotate }); + const stamp_obj = { + x: pos[0], y: pos[1], r: this.state.rotate, + stamp_class: this.props.stamp_class, + stamp_icon_state: data.stamp_icon_state, + }; + act("stamp", stamp_obj); this.setState({ x: pos[0], y: pos[1] }); } @@ -360,7 +363,7 @@ class PaperSheetStamper extends Component { onMouseMove={this.handleMouseMove.bind(this)} onwheel={this.handleWheel.bind(this)} {...rest}> { + readOnly /> ); case 1: return ( diff --git a/tgui/packages/tgui/interfaces/Photocopier.js b/tgui/packages/tgui/interfaces/Photocopier.js new file mode 100644 index 0000000000..fc79571e8c --- /dev/null +++ b/tgui/packages/tgui/interfaces/Photocopier.js @@ -0,0 +1,182 @@ +import { ProgressBar, NumberInput, Button, Section, Box, Flex } from '../components'; +import { useBackend } from '../backend'; +import { Window } from '../layouts'; + +export const Photocopier = (props, context) => { + const { data } = useBackend(context); + const { + isAI, + has_toner, + has_item, + } = data; + + return ( + + + {has_toner ? ( + + ) : ( +
+ + No inserted toner cartridge. + +
+ )} + {has_item ? ( + + ) : ( +
+ + No inserted item. + +
+ )} + {!!isAI && ( + + )} +
+
+ ); +}; + +const Toner = (props, context) => { + const { act, data } = useBackend(context); + const { + max_toner, + current_toner, + } = data; + + const average_toner = max_toner * 0.66; + const bad_toner = max_toner * 0.33; + + return ( +
act('remove_toner')} + icon="eject"> + Eject + + }> + +
+ ); +}; + +const Options = (props, context) => { + const { act, data } = useBackend(context); + const { + color_mode, + is_photo, + num_copies, + has_enough_toner, + } = data; + + return ( +
+ + + Make copies: + + + act('set_copies', { + num_copies: value, + })} /> + + + + + + {!!is_photo && ( + + + + + + + + + )} + +
+ ); +}; + +const AIOptions = (props, context) => { + const { act, data } = useBackend(context); + const { can_AI_print } = data; + + return ( +
+ + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/Wires.js b/tgui/packages/tgui/interfaces/Wires.js index 4f3e16f77f..e8b5972734 100644 --- a/tgui/packages/tgui/interfaces/Wires.js +++ b/tgui/packages/tgui/interfaces/Wires.js @@ -1,17 +1,25 @@ import { Fragment } from 'inferno'; import { useBackend } from '../backend'; -import { Box, Button, LabeledList, Section } from '../components'; +import { Box, Button, LabeledList, Section, NoticeBox } from '../components'; import { Window } from '../layouts'; export const Wires = (props, context) => { const { act, data } = useBackend(context); + const { proper_name } = data; const wires = data.wires || []; const statuses = data.status || []; return ( + height={150 + + (wires.length * 30) + + (!!proper_name && 30)}> + {(!!proper_name && ( + + {proper_name} Wire Configuration + + ))}
{wires.map(wire => ( diff --git a/tgui/packages/tgui/layouts/Layout.js b/tgui/packages/tgui/layouts/Layout.js index a00115e5f9..cd253ae257 100644 --- a/tgui/packages/tgui/layouts/Layout.js +++ b/tgui/packages/tgui/layouts/Layout.js @@ -5,29 +5,15 @@ */ import { classes } from 'common/react'; -import { computeBoxProps, computeBoxClassName } from '../components/Box'; - -/** - * Brings Layout__content DOM element back to focus. - * - * Commonly used to keep the content scrollable in IE. - */ -export const refocusLayout = () => { - // IE8: Focus method is seemingly fucked. - if (Byond.IS_LTE_IE8) { - return; - } - const element = document.getElementById('Layout__content'); - if (element) { - element.focus(); - } -}; +import { computeBoxClassName, computeBoxProps } from '../components/Box'; +import { addScrollableNode, removeScrollableNode } from '../events'; export const Layout = props => { const { className, theme = 'nanotrasen', children, + ...rest } = props; return (
@@ -35,7 +21,9 @@ export const Layout = props => { className={classes([ 'Layout', className, - ])}> + ...computeBoxClassName(rest), + ])} + {...computeBoxProps(rest)}> {children}
@@ -51,7 +39,6 @@ const LayoutContent = props => { } = props; return (
{ ); }; +LayoutContent.defaultHooks = { + onComponentDidMount: node => addScrollableNode(node), + onComponentWillUnmount: node => removeScrollableNode(node), +}; + Layout.Content = LayoutContent; diff --git a/tgui/packages/tgui/layouts/index.js b/tgui/packages/tgui/layouts/index.js index 57d9f3ef0d..6e02bf74d0 100644 --- a/tgui/packages/tgui/layouts/index.js +++ b/tgui/packages/tgui/layouts/index.js @@ -4,6 +4,7 @@ * @license MIT */ -export { Layout, refocusLayout } from './Layout'; +export { Layout } from './Layout'; export { NtosWindow } from './NtosWindow'; +export { Pane } from './Pane'; export { Window } from './Window';