mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
no thoughts, head segfaulted
This commit is contained in:
@@ -39,6 +39,10 @@ export const loadSourceMaps = async bundleDir => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const retrace = stack => {
|
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 header = stack.split(/\n\s.*at/)[0];
|
||||||
const mappedStack = StackTraceParser.parse(stack)
|
const mappedStack = StackTraceParser.parse(stack)
|
||||||
.map(frame => {
|
.map(frame => {
|
||||||
|
|||||||
127
tgui/packages/tgui/interfaces/AtmosControlPanel.js
Normal file
127
tgui/packages/tgui/interfaces/AtmosControlPanel.js
Normal file
@@ -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 (
|
||||||
|
<Window
|
||||||
|
title="SSAir Control Panel"
|
||||||
|
width={900}
|
||||||
|
height={500}
|
||||||
|
resizable>
|
||||||
|
<Section m={1}>
|
||||||
|
<Flex
|
||||||
|
justify="space-between"
|
||||||
|
align="baseline">
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
onClick={() => act('toggle-freeze')}
|
||||||
|
color={data.frozen === 1 ? 'good' : 'bad'}>
|
||||||
|
{data.frozen === 1
|
||||||
|
? 'Freeze Subsystem'
|
||||||
|
: 'Unfreeze Subsystem'}
|
||||||
|
</Button>
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
Fire Cnt: {data.fire_count}
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
Active Turfs: {data.active_size}
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
Excited Groups: {data.excited_size}
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
Hotspots: {data.hotspots_size}
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
Superconductors: {data.conducting_size}
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button.Checkbox
|
||||||
|
checked={data.showing_user}
|
||||||
|
onClick={() => act('toggle_user_display')}>
|
||||||
|
Personal View
|
||||||
|
</Button.Checkbox>
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button.Checkbox
|
||||||
|
checked={data.show_all}
|
||||||
|
onClick={() => act('toggle_show_all')}>
|
||||||
|
Display all
|
||||||
|
</Button.Checkbox>
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
</Section>
|
||||||
|
<Box fillPositionedParent top="45px">
|
||||||
|
<Window.Content scrollable>
|
||||||
|
<Section>
|
||||||
|
<Table>
|
||||||
|
<Table.Row header>
|
||||||
|
<Table.Cell>
|
||||||
|
Area Name
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell collapsing>
|
||||||
|
Breakdown
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell collapsing>
|
||||||
|
Dismantle
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell collapsing>
|
||||||
|
Turfs
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell collapsing>
|
||||||
|
{data.display_max === 1 && "Max Share"}
|
||||||
|
</Table.Cell>
|
||||||
|
<Table.Cell collapsing>
|
||||||
|
Display
|
||||||
|
</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
{groups.map(group => (
|
||||||
|
<tr key={group.id}>
|
||||||
|
<td>
|
||||||
|
<Button
|
||||||
|
content={group.area}
|
||||||
|
onClick={() => act('move-to-target', {
|
||||||
|
spot: group.jump_to,
|
||||||
|
})} />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{group.breakdown}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{group.dismantle}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{group.size}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{data.display_max === 1 && group.max_share}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Button.Checkbox
|
||||||
|
checked={group.should_show}
|
||||||
|
onClick={() => act('toggle_show_group', {
|
||||||
|
group: group.group,
|
||||||
|
})} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</Table>
|
||||||
|
</Section>
|
||||||
|
</Window.Content>
|
||||||
|
</Box>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -5,7 +5,7 @@ import { createSearch } from 'common/string';
|
|||||||
import { Fragment } from 'inferno';
|
import { Fragment } from 'inferno';
|
||||||
import { useBackend, useLocalState } from '../backend';
|
import { useBackend, useLocalState } from '../backend';
|
||||||
import { Button, ByondUi, Input, Section } from '../components';
|
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
|
* Returns previous and next camera names relative to the currently
|
||||||
@@ -123,12 +123,9 @@ export const CameraConsoleContent = (props, context) => {
|
|||||||
&& camera.name === activeCamera.name
|
&& camera.name === activeCamera.name
|
||||||
&& 'Button--selected',
|
&& 'Button--selected',
|
||||||
])}
|
])}
|
||||||
onClick={() => {
|
onClick={() => act('switch_camera', {
|
||||||
refocusLayout();
|
|
||||||
act('switch_camera', {
|
|
||||||
name: camera.name,
|
name: camera.name,
|
||||||
});
|
})}>
|
||||||
}}>
|
|
||||||
{camera.name}
|
{camera.name}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const Cargo = (props, context) => {
|
|||||||
resizable>
|
resizable>
|
||||||
<Window.Content scrollable>
|
<Window.Content scrollable>
|
||||||
<CargoStatus />
|
<CargoStatus />
|
||||||
|
<Section fitted>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
icon="list"
|
icon="list"
|
||||||
@@ -48,6 +49,7 @@ export const Cargo = (props, context) => {
|
|||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
)}
|
)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
</Section>
|
||||||
{tab === 'catalog' && (
|
{tab === 'catalog' && (
|
||||||
<CargoCatalog />
|
<CargoCatalog />
|
||||||
)}
|
)}
|
||||||
@@ -143,7 +145,7 @@ export const CargoCatalog = (props, context) => {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}>
|
)}>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Flex.Item>
|
<Flex.Item ml={-1} mr={1}>
|
||||||
<Tabs vertical>
|
<Tabs vertical>
|
||||||
{supplies.map(supply => (
|
{supplies.map(supply => (
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
|
|||||||
@@ -242,13 +242,14 @@ const CfStep2 = (props, context) => {
|
|||||||
</Table.Row>
|
</Table.Row>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell bold position="relative">
|
<Table.Cell bold position="relative">
|
||||||
Card Reader:
|
Secondary Card Reader:
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={multiline`
|
content={multiline`
|
||||||
Adds a slot that allows you to manipulate RFID cards.
|
Adds a secondary RFID card reader, for manipulating or
|
||||||
Please note that this is not necessary to allow the device
|
reading from a second standard RFID card.
|
||||||
to read your identification, it is just necessary to
|
Please note that a primary card reader is necessary to
|
||||||
manipulate other cards.
|
allow the device to read your identification, but one
|
||||||
|
is included in the base price.
|
||||||
`}
|
`}
|
||||||
position="right" />
|
position="right" />
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
|
|||||||
102
tgui/packages/tgui/interfaces/GhostPoolProtection.js
Normal file
102
tgui/packages/tgui/interfaces/GhostPoolProtection.js
Normal file
@@ -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 (
|
||||||
|
<Window
|
||||||
|
title="Ghost Pool Protection"
|
||||||
|
width={400}
|
||||||
|
height={270}>
|
||||||
|
<Window.Content>
|
||||||
|
<Flex grow={1} height="100%">
|
||||||
|
<Section
|
||||||
|
title="Options"
|
||||||
|
buttons={
|
||||||
|
<Fragment>
|
||||||
|
<Button
|
||||||
|
color="good"
|
||||||
|
icon="plus-circle"
|
||||||
|
content="Enable Everything"
|
||||||
|
onClick={() => act("all_roles")} />
|
||||||
|
<Button
|
||||||
|
color="bad"
|
||||||
|
icon="minus-circle"
|
||||||
|
content="Disable Everything"
|
||||||
|
onClick={() => act("no_roles")} />
|
||||||
|
</Fragment>
|
||||||
|
}>
|
||||||
|
<NoticeBox danger>
|
||||||
|
For people creating a sneaky event: If you
|
||||||
|
toggle Station Created Sentience, people may
|
||||||
|
catch on that admins have disabled roles for
|
||||||
|
your event...
|
||||||
|
</NoticeBox>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
color={events_or_midrounds ? "good" : "bad"}
|
||||||
|
icon="meteor"
|
||||||
|
content="Events and Midround Rulesets"
|
||||||
|
onClick={() => act("toggle_events_or_midrounds")} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
color={spawners ? "good" : "bad"}
|
||||||
|
icon="pastafarianism"
|
||||||
|
content="Ghost Role Spawners"
|
||||||
|
onClick={() => act("toggle_spawners")} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
color={station_sentience ? "good" : "bad"}
|
||||||
|
icon="user-astronaut"
|
||||||
|
content="Station Created Sentience"
|
||||||
|
onClick={() => act("toggle_station_sentience")} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
color={silicons ? "good" : "bad"}
|
||||||
|
icon="robot"
|
||||||
|
content="Silicons"
|
||||||
|
onClick={() => act("toggle_silicons")} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
color={minigames ? "good" : "bad"}
|
||||||
|
icon="gamepad"
|
||||||
|
content="Minigames"
|
||||||
|
onClick={() => act("toggle_minigames")} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
color="orange"
|
||||||
|
icon="check"
|
||||||
|
content="Apply Changes"
|
||||||
|
onClick={() => act("apply_settings")} />
|
||||||
|
</Flex.Item>
|
||||||
|
</Section>
|
||||||
|
</Flex>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
97
tgui/packages/tgui/interfaces/MechpadConsole.js
Normal file
97
tgui/packages/tgui/interfaces/MechpadConsole.js
Normal file
@@ -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 (
|
||||||
|
<Section
|
||||||
|
title={(
|
||||||
|
<Input
|
||||||
|
value={pad_name}
|
||||||
|
width="170px"
|
||||||
|
onChange={(e, value) => act('rename', {
|
||||||
|
name: value,
|
||||||
|
})} />
|
||||||
|
)}
|
||||||
|
level={topLevel ? 1 : 2}
|
||||||
|
buttons={(
|
||||||
|
<Button
|
||||||
|
icon="times"
|
||||||
|
content="Remove"
|
||||||
|
color="bad"
|
||||||
|
onClick={() => act('remove')} />
|
||||||
|
)}>
|
||||||
|
{!connected_mechpad && (
|
||||||
|
<Box color="bad" textAlign="center">
|
||||||
|
No Pad Connected.
|
||||||
|
</Box>
|
||||||
|
) || (
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
icon="upload"
|
||||||
|
content="Launch"
|
||||||
|
textAlign="center"
|
||||||
|
onClick={() => act('launch')} />
|
||||||
|
)}
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MechpadConsole = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
const {
|
||||||
|
mechpads = [],
|
||||||
|
selected_id,
|
||||||
|
} = data;
|
||||||
|
return (
|
||||||
|
<Window
|
||||||
|
width={475}
|
||||||
|
height={130}
|
||||||
|
resizable>
|
||||||
|
<Window.Content>
|
||||||
|
{mechpads.length === 0 && (
|
||||||
|
<NoticeBox>
|
||||||
|
No Pads Connected
|
||||||
|
</NoticeBox>
|
||||||
|
) || (
|
||||||
|
<Section>
|
||||||
|
<Flex minHeight="70px">
|
||||||
|
<Flex.Item width="140px" minHeight="70px">
|
||||||
|
{mechpads.map(mechpad => (
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
ellipsis
|
||||||
|
key={mechpad.name}
|
||||||
|
content={mechpad.name}
|
||||||
|
selected={selected_id === mechpad.id}
|
||||||
|
color="transparent"
|
||||||
|
onClick={() => act('select_pad', {
|
||||||
|
id: mechpad.id,
|
||||||
|
})} />
|
||||||
|
))}
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item minHeight="100%">
|
||||||
|
<Divider vertical />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item grow={1} basis={0} minHeight="100%">
|
||||||
|
{selected_id && (
|
||||||
|
<MechpadControl />
|
||||||
|
) || (
|
||||||
|
<Box>
|
||||||
|
Please select a pad
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
</Section>
|
||||||
|
)}
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -28,6 +28,8 @@ export const NtosMain = (props, context) => {
|
|||||||
has_light,
|
has_light,
|
||||||
light_on,
|
light_on,
|
||||||
comp_light_color,
|
comp_light_color,
|
||||||
|
removable_media = [],
|
||||||
|
login = [],
|
||||||
} = data;
|
} = data;
|
||||||
return (
|
return (
|
||||||
<NtosWindow
|
<NtosWindow
|
||||||
@@ -56,6 +58,44 @@ export const NtosMain = (props, context) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Section>
|
</Section>
|
||||||
)}
|
)}
|
||||||
|
<Section
|
||||||
|
title="User Login"
|
||||||
|
buttons={(
|
||||||
|
<Button
|
||||||
|
icon="eject"
|
||||||
|
content="Eject ID"
|
||||||
|
disabled={!login.IDName}
|
||||||
|
onClick={() => act('PC_Eject_Disk', { name: "ID" })}
|
||||||
|
/>
|
||||||
|
)}>
|
||||||
|
<Table>
|
||||||
|
<Table.Row>
|
||||||
|
ID Name: {login.IDName}
|
||||||
|
</Table.Row>
|
||||||
|
<Table.Row>
|
||||||
|
Assignment: {login.IDJob}
|
||||||
|
</Table.Row>
|
||||||
|
</Table>
|
||||||
|
</Section>
|
||||||
|
{!!removable_media.length && (
|
||||||
|
<Section title="Media Eject">
|
||||||
|
<Table>
|
||||||
|
{removable_media.map(device => (
|
||||||
|
<Table.Row key={device}>
|
||||||
|
<Table.Cell>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
color="transparent"
|
||||||
|
icon="eject"
|
||||||
|
content={device}
|
||||||
|
onClick={() => act('PC_Eject_Disk', { name: device })}
|
||||||
|
/>
|
||||||
|
</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
))}
|
||||||
|
</Table>
|
||||||
|
</Section>
|
||||||
|
)}
|
||||||
<Section title="Programs">
|
<Section title="Programs">
|
||||||
<Table>
|
<Table>
|
||||||
{programs.map(program => (
|
{programs.map(program => (
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const NtosRadar = (props, context) => {
|
|||||||
width={800}
|
width={800}
|
||||||
height={600}
|
height={600}
|
||||||
theme="ntos">
|
theme="ntos">
|
||||||
<NtosRadarContent />
|
<NtosRadarContent sig_err={"Signal Lost"} />
|
||||||
</NtosWindow>
|
</NtosWindow>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -23,6 +23,7 @@ export const NtosRadarContent = (props, context) => {
|
|||||||
target = [],
|
target = [],
|
||||||
scanning,
|
scanning,
|
||||||
} = data;
|
} = data;
|
||||||
|
const { sig_err } = props;
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
direction={"row"}
|
direction={"row"}
|
||||||
@@ -89,7 +90,7 @@ export const NtosRadarContent = (props, context) => {
|
|||||||
width={42}
|
width={42}
|
||||||
fontSize="30px"
|
fontSize="30px"
|
||||||
textAlign="center">
|
textAlign="center">
|
||||||
Signal Lost
|
{sig_err}
|
||||||
</NoticeBox>
|
</NoticeBox>
|
||||||
)
|
)
|
||||||
: !!target.userot && (
|
: !!target.userot && (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const NtosRadarSyndicate = (props, context) => {
|
|||||||
width={800}
|
width={800}
|
||||||
height={600}
|
height={600}
|
||||||
theme="syndicate">
|
theme="syndicate">
|
||||||
<NtosRadarContent />
|
<NtosRadarContent sig_err={"Out of Range"} />
|
||||||
</NtosWindow>
|
</NtosWindow>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { classes, isFalsy } from "common/react";
|
import { classes } from 'common/react';
|
||||||
import { vecScale, vecSubtract } from 'common/vector';
|
import { vecScale, vecSubtract } from 'common/vector';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import { Component } from 'inferno';
|
import { Component } from 'inferno';
|
||||||
@@ -241,13 +241,11 @@ const PaperSheetView = (props, context) => {
|
|||||||
stamps,
|
stamps,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
readOnly,
|
readOnly,
|
||||||
...rest
|
|
||||||
} = props;
|
} = props;
|
||||||
const readonly = !isFalsy(readOnly);
|
|
||||||
const stamp_list = stamps || [];
|
const stamp_list = stamps || [];
|
||||||
const text_html = {
|
const text_html = {
|
||||||
__html: '<span class="paper-text">'
|
__html: '<span class="paper-text">'
|
||||||
+ setInputReadonly(value, readonly)
|
+ setInputReadonly(value, readOnly)
|
||||||
+ '</span>',
|
+ '</span>',
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@@ -323,7 +321,12 @@ class PaperSheetStamper extends Component {
|
|||||||
handleMouseClick(e) {
|
handleMouseClick(e) {
|
||||||
const pos = this.findStampPosition(e);
|
const pos = this.findStampPosition(e);
|
||||||
const { act, data } = useBackend(this.context);
|
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] });
|
this.setState({ x: pos[0], y: pos[1] });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,7 +363,7 @@ class PaperSheetStamper extends Component {
|
|||||||
onMouseMove={this.handleMouseMove.bind(this)}
|
onMouseMove={this.handleMouseMove.bind(this)}
|
||||||
onwheel={this.handleWheel.bind(this)} {...rest}>
|
onwheel={this.handleWheel.bind(this)} {...rest}>
|
||||||
<PaperSheetView
|
<PaperSheetView
|
||||||
readOnly={1}
|
readOnly
|
||||||
value={value}
|
value={value}
|
||||||
stamps={stamp_list} />
|
stamps={stamp_list} />
|
||||||
<Stamp
|
<Stamp
|
||||||
@@ -593,7 +596,7 @@ export const PaperSheet = (props, context) => {
|
|||||||
<PaperSheetView
|
<PaperSheetView
|
||||||
value={text}
|
value={text}
|
||||||
stamps={stamp_list}
|
stamps={stamp_list}
|
||||||
readOnly={1} />
|
readOnly />
|
||||||
);
|
);
|
||||||
case 1:
|
case 1:
|
||||||
return (
|
return (
|
||||||
|
|||||||
182
tgui/packages/tgui/interfaces/Photocopier.js
Normal file
182
tgui/packages/tgui/interfaces/Photocopier.js
Normal file
@@ -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 (
|
||||||
|
<Window
|
||||||
|
title="Photocopier"
|
||||||
|
width={240}
|
||||||
|
height={isAI ? 309 : 234}>
|
||||||
|
<Window.Content>
|
||||||
|
{has_toner ? (
|
||||||
|
<Toner />
|
||||||
|
) : (
|
||||||
|
<Section title="Toner">
|
||||||
|
<Box color="average">
|
||||||
|
No inserted toner cartridge.
|
||||||
|
</Box>
|
||||||
|
</Section>
|
||||||
|
)}
|
||||||
|
{has_item ? (
|
||||||
|
<Options />
|
||||||
|
) : (
|
||||||
|
<Section title="Options">
|
||||||
|
<Box color="average">
|
||||||
|
No inserted item.
|
||||||
|
</Box>
|
||||||
|
</Section>
|
||||||
|
)}
|
||||||
|
{!!isAI && (
|
||||||
|
<AIOptions />
|
||||||
|
)}
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Section
|
||||||
|
title="Toner"
|
||||||
|
buttons={
|
||||||
|
<Button
|
||||||
|
disabled={!current_toner}
|
||||||
|
onClick={() => act('remove_toner')}
|
||||||
|
icon="eject">
|
||||||
|
Eject
|
||||||
|
</Button>
|
||||||
|
}>
|
||||||
|
<ProgressBar
|
||||||
|
ranges={{
|
||||||
|
good: [average_toner, max_toner],
|
||||||
|
average: [bad_toner, average_toner],
|
||||||
|
bad: [0, bad_toner],
|
||||||
|
}}
|
||||||
|
value={current_toner}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={max_toner} />
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Options = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
const {
|
||||||
|
color_mode,
|
||||||
|
is_photo,
|
||||||
|
num_copies,
|
||||||
|
has_enough_toner,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="Options">
|
||||||
|
<Flex>
|
||||||
|
<Flex.Item
|
||||||
|
mt={0.4}
|
||||||
|
width={11}
|
||||||
|
color="label">
|
||||||
|
Make copies:
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<NumberInput
|
||||||
|
animate
|
||||||
|
width={2.6}
|
||||||
|
height={1.65}
|
||||||
|
step={1}
|
||||||
|
stepPixelSize={8}
|
||||||
|
minValue={1}
|
||||||
|
maxValue={10}
|
||||||
|
value={num_copies}
|
||||||
|
onDrag={(e, value) => act('set_copies', {
|
||||||
|
num_copies: value,
|
||||||
|
})} />
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item>
|
||||||
|
<Button
|
||||||
|
ml={0.2}
|
||||||
|
icon="copy"
|
||||||
|
textAlign="center"
|
||||||
|
disabled={!has_enough_toner}
|
||||||
|
onClick={() => act('make_copy')}>
|
||||||
|
Copy
|
||||||
|
</Button>
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
{!!is_photo && (
|
||||||
|
<Flex mt={0.5}>
|
||||||
|
<Flex.Item
|
||||||
|
mr={0.4}
|
||||||
|
width="50%">
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
selected={color_mode === "Greyscale"}
|
||||||
|
onClick={() => act('color_mode', {
|
||||||
|
mode: "Greyscale",
|
||||||
|
})}>
|
||||||
|
Greyscale
|
||||||
|
</Button>
|
||||||
|
</Flex.Item>
|
||||||
|
<Flex.Item
|
||||||
|
ml={0.4}
|
||||||
|
width="50%">
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
textAlign="center"
|
||||||
|
selected={color_mode === "Color"}
|
||||||
|
onClick={() => act('color_mode', {
|
||||||
|
mode: "Color",
|
||||||
|
})}>
|
||||||
|
Color
|
||||||
|
</Button>
|
||||||
|
</Flex.Item>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
mt={0.5}
|
||||||
|
textAlign="center"
|
||||||
|
icon="reply"
|
||||||
|
fluid
|
||||||
|
onClick={() => act('remove')}>
|
||||||
|
Remove item
|
||||||
|
</Button>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AIOptions = (props, context) => {
|
||||||
|
const { act, data } = useBackend(context);
|
||||||
|
const { can_AI_print } = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Section title="AI Options">
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
fluid
|
||||||
|
icon="images"
|
||||||
|
textAlign="center"
|
||||||
|
disabled={!can_AI_print}
|
||||||
|
onClick={() => act('ai_photo')}>
|
||||||
|
Print photo from database
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Section>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,17 +1,25 @@
|
|||||||
import { Fragment } from 'inferno';
|
import { Fragment } from 'inferno';
|
||||||
import { useBackend } from '../backend';
|
import { useBackend } from '../backend';
|
||||||
import { Box, Button, LabeledList, Section } from '../components';
|
import { Box, Button, LabeledList, Section, NoticeBox } from '../components';
|
||||||
import { Window } from '../layouts';
|
import { Window } from '../layouts';
|
||||||
|
|
||||||
export const Wires = (props, context) => {
|
export const Wires = (props, context) => {
|
||||||
const { act, data } = useBackend(context);
|
const { act, data } = useBackend(context);
|
||||||
|
const { proper_name } = data;
|
||||||
const wires = data.wires || [];
|
const wires = data.wires || [];
|
||||||
const statuses = data.status || [];
|
const statuses = data.status || [];
|
||||||
return (
|
return (
|
||||||
<Window
|
<Window
|
||||||
width={350}
|
width={350}
|
||||||
height={150 + wires.length * 30}>
|
height={150
|
||||||
|
+ (wires.length * 30)
|
||||||
|
+ (!!proper_name && 30)}>
|
||||||
<Window.Content>
|
<Window.Content>
|
||||||
|
{(!!proper_name && (
|
||||||
|
<NoticeBox textAlign="center">
|
||||||
|
{proper_name} Wire Configuration
|
||||||
|
</NoticeBox>
|
||||||
|
))}
|
||||||
<Section>
|
<Section>
|
||||||
<LabeledList>
|
<LabeledList>
|
||||||
{wires.map(wire => (
|
{wires.map(wire => (
|
||||||
|
|||||||
@@ -5,29 +5,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { classes } from 'common/react';
|
import { classes } from 'common/react';
|
||||||
import { computeBoxProps, computeBoxClassName } from '../components/Box';
|
import { computeBoxClassName, computeBoxProps } from '../components/Box';
|
||||||
|
import { addScrollableNode, removeScrollableNode } from '../events';
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Layout = props => {
|
export const Layout = props => {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
theme = 'nanotrasen',
|
theme = 'nanotrasen',
|
||||||
children,
|
children,
|
||||||
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
return (
|
return (
|
||||||
<div className={'theme-' + theme}>
|
<div className={'theme-' + theme}>
|
||||||
@@ -35,7 +21,9 @@ export const Layout = props => {
|
|||||||
className={classes([
|
className={classes([
|
||||||
'Layout',
|
'Layout',
|
||||||
className,
|
className,
|
||||||
])}>
|
...computeBoxClassName(rest),
|
||||||
|
])}
|
||||||
|
{...computeBoxProps(rest)}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,7 +39,6 @@ const LayoutContent = props => {
|
|||||||
} = props;
|
} = props;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id="Layout__content"
|
|
||||||
className={classes([
|
className={classes([
|
||||||
'Layout__content',
|
'Layout__content',
|
||||||
scrollable && 'Layout__content--scrollable',
|
scrollable && 'Layout__content--scrollable',
|
||||||
@@ -64,4 +51,9 @@ const LayoutContent = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LayoutContent.defaultHooks = {
|
||||||
|
onComponentDidMount: node => addScrollableNode(node),
|
||||||
|
onComponentWillUnmount: node => removeScrollableNode(node),
|
||||||
|
};
|
||||||
|
|
||||||
Layout.Content = LayoutContent;
|
Layout.Content = LayoutContent;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export { Layout, refocusLayout } from './Layout';
|
export { Layout } from './Layout';
|
||||||
export { NtosWindow } from './NtosWindow';
|
export { NtosWindow } from './NtosWindow';
|
||||||
|
export { Pane } from './Pane';
|
||||||
export { Window } from './Window';
|
export { Window } from './Window';
|
||||||
|
|||||||
Reference in New Issue
Block a user