Skip to content

Commit

Permalink
tgui: Converts some uselocal -> usestate (tgstation#83364)
Browse files Browse the repository at this point in the history
## About The Pull Request
Title. Had some extra time, converted some UIs to use
usestate/usecontext rather than uselocalstate.

PAI available software interface was adjusted a little.

<details>
<summary>pictures</summary>

before
![Screenshot 2024-05-20
155616](https://github.com/tgstation/tgstation/assets/42397676/ea5e66bc-1257-4fad-ac8c-6ed40df70563)

after
![Screenshot 2024-05-20
155927](https://github.com/tgstation/tgstation/assets/42397676/2b86f44c-27e9-4bc4-9503-dd3d5a41e4a4)


![image](https://github.com/tgstation/tgstation/assets/42397676/4f745a4d-14c8-429f-91ca-9e06e505c7fc)

</details>

## Why It's Good For The Game
Uselocalstate is deprecated in favor of using plain react hooks.
## Changelog
:cl:
fix: Slightly cleaned up PAI software downloads interface
/:cl:
  • Loading branch information
jlsnow301 authored May 29, 2024
1 parent e00d3a5 commit adc800d
Show file tree
Hide file tree
Showing 14 changed files with 423 additions and 397 deletions.
9 changes: 4 additions & 5 deletions tgui/packages/tgui/interfaces/Biogenerator.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { BooleanLike } from 'common/react';
import { classes } from 'common/react';
import { useState } from 'react';

import { useBackend, useLocalState } from '../backend';
import { useBackend } from '../backend';
import {
Box,
Button,
Expand Down Expand Up @@ -59,8 +60,7 @@ export const Biogenerator = (props) => {
efficiency,
categories,
} = data;
const [selectedCategory, setSelectedCategory] = useLocalState<string>(
'category',
const [selectedCategory, setSelectedCategory] = useState(
data.categories[0]?.name,
);
const items =
Expand Down Expand Up @@ -184,8 +184,7 @@ export const Biogenerator = (props) => {
const ItemList = (props) => {
const { act } = useBackend();
const items = props.items.map((item) => {
const [amount, setAmount] = useLocalState(
'amount' + item.name,
const [amount, setAmount] = useState(
item.is_reagent ? Math.min(Math.max(props.space, 1), 10) : 1,
);
const disabled =
Expand Down
47 changes: 31 additions & 16 deletions tgui/packages/tgui/interfaces/MessageMonitor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BooleanLike } from 'common/react';
import { Dispatch, SetStateAction, useState } from 'react';

import { useBackend, useLocalState } from '../backend';
import { useBackend } from '../backend';
import {
Box,
Button,
Expand Down Expand Up @@ -160,13 +161,12 @@ const HackedScreen = (props) => {
);
};

const MainScreenAuth = (props) => {
const MainScreenAuth = (props: AuthScreenProps) => {
const { auth_password, setPassword } = props;

const { act, data } = useBackend<Data>();
const { status, is_malf, password } = data;
const [auth_password, setPassword] = useLocalState(
'input_password',
password,
);
const { status, is_malf } = data;

return (
<>
<Stack.Item>
Expand Down Expand Up @@ -260,13 +260,15 @@ const MainScreenAuth = (props) => {
);
};

const MainScreenNotAuth = (props) => {
type AuthScreenProps = {
auth_password: string;
setPassword: Dispatch<SetStateAction<string>>;
};

const MainScreenNotAuth = (props: AuthScreenProps) => {
const { auth_password, setPassword } = props;
const { act, data } = useBackend<Data>();
const { status, is_malf, password } = data;
const [auth_password, setPassword] = useLocalState(
'input_password',
password,
);
const { status, is_malf } = data;

return (
<>
Expand Down Expand Up @@ -319,11 +321,24 @@ const MainScreenNotAuth = (props) => {
};

const MainScreen = (props) => {
const { act, data } = useBackend<Data>();
const { auth } = data;
const { data } = useBackend<Data>();
const { auth, password } = data;

const [auth_password, setPassword] = useState(password);

return (
<Stack fill vertical>
{auth ? <MainScreenAuth /> : <MainScreenNotAuth />}
{auth ? (
<MainScreenAuth
auth_password={auth_password}
setPassword={setPassword}
/>
) : (
<MainScreenNotAuth
auth_password={auth_password}
setPassword={setPassword}
/>
)}
</Stack>
);
};
Expand Down
105 changes: 51 additions & 54 deletions tgui/packages/tgui/interfaces/PaiInterface/Available.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,33 @@ import { PaiData } from './types';
/**
* Renders a list of available software and the ram with which to download it
*/
export const AvailableDisplay = () => {
export function AvailableDisplay(props) {
const { data } = useBackend<PaiData>();
const { available } = data;

const entries = Object.entries(available);
if (entries.length === 0) {
return null;
}

return (
<Section
buttons={<MemoryDisplay />}
fill
scrollable
title="Available Software"
>
<SoftwareList />
<Table>
{entries?.map(([name, cost]) => {
return <ListItem cost={cost} key={name} name={name} />;
})}
</Table>
</Section>
);
};
}

/** Displays the remaining RAM left as a progressbar. */
const MemoryDisplay = (props) => {
function MemoryDisplay(props) {
const { data } = useBackend<PaiData>();
const { ram } = data;

Expand All @@ -50,70 +62,55 @@ const MemoryDisplay = (props) => {
bad: [0, 33],
}}
value={ram}
/>
width={5}
>
{ram}
</ProgressBar>
</Table.Cell>
</Table.Row>
</Table>
</Tooltip>
);
};
}

/** A list of available software.
* creates table rows for each, like a vendor.
*/
const SoftwareList = (props) => {
const { data } = useBackend<PaiData>();
const { available } = data;
if (!available) {
return null;
}
const entries = Object.entries(available);
if (entries.length === 0) {
return null;
}

return (
<Table>
{entries?.map(([name, cost], index) => {
return <ListItem cost={cost} key={index} name={name} />;
})}
</Table>
);
type ListItemProps = {
cost: number;
name: string;
};

/** A row for an individual software listing. */
const ListItem = (props) => {
function ListItem(props: ListItemProps) {
const { act, data } = useBackend<PaiData>();
const { installed, ram } = data;
const { cost, name } = props;

const purchased = installed.includes(name);
const tooExpensive = ram < cost;

return (
<Table.Row className="candystripe">
<Table.Cell collapsing>
<Box color="label">{name}</Box>
</Table.Cell>
<Table.Cell collapsing>
<Box color={ram < cost && 'bad'} textAlign="right">
{!purchased && cost}{' '}
<Icon
color={purchased || ram >= cost ? 'purple' : 'bad'}
name={purchased ? 'check' : 'microchip'}
<Tooltip content={SOFTWARE_DESC[name]} position="bottom-start">
<Table.Row className="candystripe">
<Table.Cell>
<Box color="label">{name}</Box>
</Table.Cell>
<Table.Cell collapsing>
<Box color={tooExpensive && 'bad'} textAlign="right">
{!purchased && cost}{' '}
<Icon
color={purchased || ram >= cost ? 'purple' : 'bad'}
name={purchased ? 'check' : 'microchip'}
/>
</Box>
</Table.Cell>
<Table.Cell collapsing>
<Button
icon="download"
mb={0.5}
disabled={tooExpensive || purchased}
onClick={() => act('buy', { selection: name })}
/>
</Box>
</Table.Cell>
<Table.Cell collapsing>
<Button
fluid
mb={0.5}
disabled={ram < cost || purchased}
onClick={() => act('buy', { selection: name })}
tooltip={SOFTWARE_DESC[name]}
tooltipPosition="bottom-start"
>
<Icon ml={1} mr={-2} name="download" />
</Button>
</Table.Cell>
</Table.Row>
</Table.Cell>
</Table.Row>
</Tooltip>
);
};
}
4 changes: 2 additions & 2 deletions tgui/packages/tgui/interfaces/PaiInterface/Directives.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DIRECTIVE_COMPREHENSION, DIRECTIVE_ORDER } from './constants';
import { PaiData } from './types';

/** Shows the hardcoded PAI info along with any supplied orders. */
export const DirectiveDisplay = (props) => {
export function DirectiveDisplay(props) {
const { data } = useBackend<PaiData>();
const { directives = [], master_name } = data;
const displayedLaw = directives?.length
Expand Down Expand Up @@ -43,4 +43,4 @@ export const DirectiveDisplay = (props) => {
</Stack.Item>
</Stack>
);
};
}
91 changes: 43 additions & 48 deletions tgui/packages/tgui/interfaces/PaiInterface/Installed.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useBackend, useLocalState } from 'tgui/backend';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Button, NoticeBox, Section, Stack } from 'tgui/components';

import { DOOR_JACK, HOST_SCAN, PHOTO_MODE, SOFTWARE_DESC } from './constants';
Expand All @@ -9,69 +10,63 @@ import { PaiData } from './types';
* another section that displays the selected installed
* software info.
*/
export const InstalledDisplay = (props) => {
export function InstalledDisplay(props) {
const { data } = useBackend<PaiData>();
const { installed = [] } = data;

const [currentSelection, setCurrentSelection] = useState('');

const title = !currentSelection ? 'Select a Program' : currentSelection;

return (
<Stack fill vertical>
<Stack.Item grow>
<InstalledSoftware />
<Section fill scrollable title={title}>
{currentSelection && (
<Stack fill vertical>
<Stack.Item>{SOFTWARE_DESC[currentSelection]}</Stack.Item>
<Stack.Item grow>
<SoftwareButtons currentSelection={currentSelection} />
</Stack.Item>
</Stack>
)}
</Section>
</Stack.Item>
<Stack.Item grow={2}>
<InstalledInfo />
<Section fill scrollable title="Installed Software">
{!installed.length ? (
<NoticeBox>Nothing installed!</NoticeBox>
) : (
installed.map((software, index) => {
return (
<Button
key={index}
onClick={() => setCurrentSelection(software)}
>
{software}
</Button>
);
})
)}
</Section>
</Stack.Item>
</Stack>
);
};

/** Iterates over installed software to render buttons. */
const InstalledSoftware = (props) => {
const { data } = useBackend<PaiData>();
const { installed = [] } = data;
const [currentSelection, setCurrentSelection] = useLocalState('software', '');

return (
<Section fill scrollable title="Installed Software">
{!installed.length ? (
<NoticeBox>Nothing installed!</NoticeBox>
) : (
installed.map((software, index) => {
return (
<Button key={index} onClick={() => setCurrentSelection(software)}>
{software}
</Button>
);
})
)}
</Section>
);
};

/** Software info for buttons clicked. */
const InstalledInfo = (props) => {
const [currentSelection] = useLocalState('software', '');
const title = !currentSelection ? 'Select a Program' : currentSelection;
}

return (
<Section fill scrollable title={title}>
{currentSelection && (
<Stack fill vertical>
<Stack.Item>{SOFTWARE_DESC[currentSelection]}</Stack.Item>
<Stack.Item grow>
<SoftwareButtons />
</Stack.Item>
</Stack>
)}
</Section>
);
type SoftwareButtonsProps = {
currentSelection: string;
};

/**
* Once a software is selected, generates custom buttons or a default
* power toggle.
*/
const SoftwareButtons = (props) => {
function SoftwareButtons(props: SoftwareButtonsProps) {
const { currentSelection } = props;

const { act, data } = useBackend<PaiData>();
const { door_jack, languages, master_name } = data;
const [currentSelection] = useLocalState('software', '');

switch (currentSelection) {
case 'Door Jack':
Expand Down Expand Up @@ -170,4 +165,4 @@ const SoftwareButtons = (props) => {
</Button>
);
}
};
}
Loading

0 comments on commit adc800d

Please sign in to comment.