Merge pull request #1294 from danielyxie/big-container

Active Scripts in Mui
This commit is contained in:
hydroflame 2021-09-18 00:16:24 -04:00 committed by GitHub
commit d1cb5b313a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 411 additions and 402 deletions

@ -1,128 +0,0 @@
@import "theme";
.active-scripts-list {
list-style-type: none;
}
.active-scripts-container {
> p {
margin: 6px;
padding: 4px;
}
.accordion-header {
> pre {
color: white;
}
}
}
.active-scripts-server-header {
background-color: #444;
font-size: $defaultFontSize * 1.25;
color: #fff;
margin: 6px 6px 0 6px;
padding: 6px;
cursor: pointer;
width: 60%;
text-align: left;
border: none;
outline: none;
&:after {
content: "\02795"; /* "plus" sign (+) */
font-size: $defaultFontSize * 0.8125;
color: #fff;
float: right;
margin-left: 5px;
}
&.active,
&:hover {
background-color: #555;
}
}
.active-scripts-server-header.active {
&:after {
content: "\2796"; /* "minus" sign (-) */
font-size: $defaultFontSize * 0.8125;
color: #fff;
float: right;
margin-left: 5px;
}
&:hover {
background-color: #666;
}
}
.active-scripts-server-panel {
margin: 0 6px 6px 6px;
padding: 0 6px 6px 6px;
width: 55%;
margin-left: 5%;
display: none;
div,
ul,
ul > li {
background-color: #555;
}
}
.active-scripts-script-header {
background-color: #555;
border: none;
color: var(--my-font-color);
cursor: pointer;
display: block;
outline: none;
padding: 4px 25px 4px 10px;
position: relative;
text-align: left;
width: auto;
&:after {
content: "\02795"; /* "plus" sign (+) */
font-size: $defaultFontSize * 0.8125;
float: right;
margin-left: 5px;
color: transparent;
text-shadow: 0 0 0 var(--my-font-color);
position: absolute;
bottom: 4px;
}
&.active:after {
content: "\2796"; /* "minus" sign (-) */
}
&:hover,
&.active:hover {
background-color: #666;
}
&.active {
background-color: #555;
}
}
.active-scripts-script-panel {
background-color: #555;
display: none;
font-size: 14px;
margin-bottom: 6px;
padding: 0 18px;
width: auto;
pre,
h2,
ul,
li {
background-color: #555;
width: auto;
color: #fff;
margin-left: 5%;
}
}

@ -32,7 +32,7 @@
.loaderoverlay { .loaderoverlay {
$spinnerBoxSize: 200px; $spinnerBoxSize: 200px;
$themeColor: #6f3; $themeColor: #0c0;
position: absolute; position: absolute;
width: 100%; width: 100%;

@ -4,7 +4,7 @@
@import "reset"; @import "reset";
:root { :root {
--my-font-color: #6f3; --my-font-color: #0c0;
--my-background-color: #000; --my-background-color: #000;
--my-highlight-color: #fff; --my-highlight-color: #fff;
--my-prompt-color: #f92672; --my-prompt-color: #f92672;

@ -340,15 +340,13 @@ export class Blackjack extends Game<Props, State> {
{/* Buttons */} {/* Buttons */}
{!gameInProgress ? ( {!gameInProgress ? (
<div> <div>
<MuiButton color="primary" onClick={this.startOnClick} disabled={wagerInvalid || !this.canStartGame()}> <MuiButton onClick={this.startOnClick} disabled={wagerInvalid || !this.canStartGame()}>
Start Start
</MuiButton> </MuiButton>
</div> </div>
) : ( ) : (
<div> <div>
<MuiButton color="primary" onClick={this.playerHit}> <MuiButton onClick={this.playerHit}>Hit</MuiButton>
Hit
</MuiButton>
<MuiButton color="secondary" onClick={this.playerStay}> <MuiButton color="secondary" onClick={this.playerStay}>
Stay Stay
</MuiButton> </MuiButton>

@ -4,7 +4,6 @@ import { IEngine } from "./IEngine";
import { IRouter } from "./ui/Router"; import { IRouter } from "./ui/Router";
import React from "react"; import React from "react";
import { TTheme as Theme } from "./ui/React/Theme";
import { General } from "./DevMenu/ui/General"; import { General } from "./DevMenu/ui/General";
import { Stats } from "./DevMenu/ui/Stats"; import { Stats } from "./DevMenu/ui/Stats";
@ -30,7 +29,6 @@ interface IProps {
export function DevMenuRoot(props: IProps): React.ReactElement { export function DevMenuRoot(props: IProps): React.ReactElement {
return ( return (
<Theme>
<> <>
<h1>Development Menu - Only meant to be used for testing/debugging</h1> <h1>Development Menu - Only meant to be used for testing/debugging</h1>
<General player={props.player} router={props.router} /> <General player={props.player} router={props.router} />
@ -56,6 +54,5 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
<TimeSkip player={props.player} engine={props.engine} /> <TimeSkip player={props.player} engine={props.engine} />
</> </>
</Theme>
); );
} }

@ -37,12 +37,12 @@ export function Adjuster(props: IProps): React.ReactElement {
startAdornment: ( startAdornment: (
<> <>
<Tooltip title="Add a lot"> <Tooltip title="Add a lot">
<IconButton color="primary" onClick={tons} size="large"> <IconButton onClick={tons} size="large">
<DoubleArrowIcon style={{ transform: "rotate(-90deg)" }} /> <DoubleArrowIcon style={{ transform: "rotate(-90deg)" }} />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title="Add"> <Tooltip title="Add">
<IconButton color="primary" onClick={() => add(typeof value !== "string" ? value : 0)} size="large"> <IconButton onClick={() => add(typeof value !== "string" ? value : 0)} size="large">
<AddIcon /> <AddIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
@ -51,16 +51,12 @@ export function Adjuster(props: IProps): React.ReactElement {
endAdornment: ( endAdornment: (
<> <>
<Tooltip title="Remove"> <Tooltip title="Remove">
<IconButton <IconButton onClick={() => subtract(typeof value !== "string" ? value : 0)} size="large">
color="primary"
onClick={() => subtract(typeof value !== "string" ? value : 0)}
size="large"
>
<RemoveIcon /> <RemoveIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Tooltip title="Reset"> <Tooltip title="Reset">
<IconButton color="primary" onClick={reset} size="large"> <IconButton onClick={reset} size="large">
<ClearIcon /> <ClearIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>

@ -40,7 +40,7 @@ export function Augmentations(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Augmentations</h2> <h2>Augmentations</h2>
</AccordionSummary> </AccordionSummary>
@ -53,23 +53,21 @@ export function Augmentations(props: IProps): React.ReactElement {
</td> </td>
<td> <td>
<Select <Select
id="dev-augs-dropdown"
className="dropdown"
onChange={setAugmentationDropdown} onChange={setAugmentationDropdown}
value={augmentation} value={augmentation}
startAdornment={ startAdornment={
<> <>
<IconButton color="primary" onClick={queueAllAugs} size="large"> <IconButton onClick={queueAllAugs} size="large">
<ReplyAllIcon /> <ReplyAllIcon />
</IconButton> </IconButton>
<IconButton color="primary" onClick={queueAug} size="large"> <IconButton onClick={queueAug} size="large">
<ReplyIcon /> <ReplyIcon />
</IconButton> </IconButton>
</> </>
} }
endAdornment={ endAdornment={
<> <>
<IconButton color="primary" onClick={clearAugs} size="large"> <IconButton onClick={clearAugs} size="large">
<ClearIcon /> <ClearIcon />
</IconButton> </IconButton>
</> </>

@ -55,7 +55,7 @@ export function Bladeburner(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Bladeburner</h2> <h2>Bladeburner</h2>
</AccordionSummary> </AccordionSummary>

@ -25,7 +25,7 @@ export function CodingContracts(): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Coding Contracts</h2> <h2>Coding Contracts</h2>
</AccordionSummary> </AccordionSummary>

@ -69,7 +69,7 @@ export function Companies(): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Companies</h2> <h2>Companies</h2>
</AccordionSummary> </AccordionSummary>

@ -67,7 +67,7 @@ export function Corporation(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Corporation</h2> <h2>Corporation</h2>
</AccordionSummary> </AccordionSummary>

@ -97,7 +97,7 @@ export function Factions(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Factions</h2> <h2>Factions</h2>
</AccordionSummary> </AccordionSummary>
@ -119,10 +119,10 @@ export function Factions(props: IProps): React.ReactElement {
value={faction} value={faction}
startAdornment={ startAdornment={
<> <>
<IconButton color="primary" onClick={receiveAllInvites} size="large"> <IconButton onClick={receiveAllInvites} size="large">
<ReplyAllIcon /> <ReplyAllIcon />
</IconButton> </IconButton>
<IconButton color="primary" onClick={receiveInvite} size="large"> <IconButton onClick={receiveInvite} size="large">
<ReplyIcon /> <ReplyIcon />
</IconButton> </IconButton>
</> </>

@ -36,7 +36,7 @@ export function Gang(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Gang</h2> <h2>Gang</h2>
</AccordionSummary> </AccordionSummary>

@ -43,7 +43,7 @@ export function General(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>General</h2> <h2>General</h2>
</AccordionSummary> </AccordionSummary>

@ -35,7 +35,7 @@ export function Programs(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Programs</h2> <h2>Programs</h2>
</AccordionSummary> </AccordionSummary>

@ -75,7 +75,7 @@ export function Servers(): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Servers</h2> <h2>Servers</h2>
</AccordionSummary> </AccordionSummary>

@ -38,7 +38,7 @@ export function Sleeves(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Sleeves</h2> <h2>Sleeves</h2>
</AccordionSummary> </AccordionSummary>

@ -51,7 +51,7 @@ export function SourceFiles(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Source-Files</h2> <h2>Source-Files</h2>
</AccordionSummary> </AccordionSummary>

@ -136,7 +136,7 @@ export function Stats(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Experience / Stats</h2> <h2>Experience / Stats</h2>
</AccordionSummary> </AccordionSummary>

@ -80,7 +80,7 @@ export function StockMarket(): React.ReactElement {
); );
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Stock Market</h2> <h2>Stock Market</h2>
</AccordionSummary> </AccordionSummary>

@ -28,7 +28,7 @@ export function TimeSkip(props: IProps): React.ReactElement {
} }
return ( return (
<Accordion> <Accordion TransitionProps={{ unmountOnExit: true }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}> <AccordionSummary expandIcon={<ExpandMoreIcon />}>
<h2>Time skip</h2> <h2>Time skip</h2>
</AccordionSummary> </AccordionSummary>

@ -207,10 +207,10 @@ function setTheme() {
/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_BACKGROUND_COLOR) && /^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_BACKGROUND_COLOR) &&
/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_PROMPT_COLOR) /^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_PROMPT_COLOR)
) { ) {
document.body.style.setProperty("--my-highlight-color", FconfSettings.THEME_HIGHLIGHT_COLOR); // document.body.style.setProperty("--my-highlight-color", FconfSettings.THEME_HIGHLIGHT_COLOR);
document.body.style.setProperty("--my-font-color", FconfSettings.THEME_FONT_COLOR); // document.body.style.setProperty("--my-font-color", FconfSettings.THEME_FONT_COLOR);
document.body.style.setProperty("--my-background-color", FconfSettings.THEME_BACKGROUND_COLOR); // document.body.style.setProperty("--my-background-color", FconfSettings.THEME_BACKGROUND_COLOR);
document.body.style.setProperty("--my-prompt-color", FconfSettings.THEME_PROMPT_COLOR); // document.body.style.setProperty("--my-prompt-color", FconfSettings.THEME_PROMPT_COLOR);
} }
} }

@ -55,7 +55,9 @@ export function GangStats(props: IProps): React.ReactElement {
</p> </p>
<br /> <br />
<div> <div>
<p style={{ display: "inline-block" }}>Money gain rate: {MoneyRate(5 * props.gang.moneyGainRate)}</p> <p style={{ display: "inline-block" }}>
Money gain rate: <MoneyRate money={5 * props.gang.moneyGainRate} />
</p>
</div> </div>
<br /> <br />
<p className="tooltip" style={{ display: "inline-block" }}> <p className="tooltip" style={{ display: "inline-block" }}>

@ -28,7 +28,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
const tasks = props.gang.getAllTaskNames(); const tasks = props.gang.getAllTaskNames();
const data = [ const data = [
[`Money:`, MoneyRate(5 * props.member.calculateMoneyGain(props.gang))], [`Money:`, <MoneyRate money={5 * props.member.calculateMoneyGain(props.gang)} />],
[`Respect:`, `${numeralWrapper.formatRespect(5 * props.member.calculateRespectGain(props.gang))} / sec`], [`Respect:`, `${numeralWrapper.formatRespect(5 * props.member.calculateRespectGain(props.gang))} / sec`],
[`Wanted Level:`, `${numeralWrapper.formatWanted(5 * props.member.calculateWantedLevelGain(props.gang))} / sec`], [`Wanted Level:`, `${numeralWrapper.formatWanted(5 * props.member.calculateWantedLevelGain(props.gang))} / sec`],
[`Total Respect:`, `${numeralWrapper.formatRespect(props.member.earnedRespect)}`], [`Total Respect:`, `${numeralWrapper.formatRespect(props.member.earnedRespect)}`],

@ -144,7 +144,8 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
<div className={"row"}> <div className={"row"}>
<p>Production:</p> <p>Production:</p>
<span className={"text money-gold"}> <span className={"text money-gold"}>
<Money money={node.totalMoneyGenerated} player={props.player} /> ({MoneyRate(node.moneyGainRatePerSecond)}) <Money money={node.totalMoneyGenerated} player={props.player} /> (
<MoneyRate money={node.moneyGainRatePerSecond} />)
</span> </span>
</div> </div>
<div className={"row"}> <div className={"row"}>

@ -25,7 +25,7 @@ export function PlayerInfo(props: IProps): React.ReactElement {
if (hasServers) { if (hasServers) {
prod = HashRate(props.totalProduction); prod = HashRate(props.totalProduction);
} else { } else {
prod = MoneyRate(props.totalProduction); prod = <MoneyRate money={props.totalProduction} />;
} }
return ( return (

@ -586,7 +586,7 @@ export function createAndAddWorkerScript(runningScriptObj, server, parent) {
* Updates the online running time stat of all running scripts * Updates the online running time stat of all running scripts
*/ */
export function updateOnlineScriptTimes(numCycles = 1) { export function updateOnlineScriptTimes(numCycles = 1) {
var time = (numCycles * Engine._idleSpeed) / 1000; //seconds var time = (numCycles * CONSTANTS._idleSpeed) / 1000; //seconds
for (const ws of workerScripts.values()) { for (const ws of workerScripts.values()) {
ws.scriptRef.onlineRunningTime += time; ws.scriptRef.onlineRunningTime += time;
} }

@ -175,7 +175,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
// }); // });
} else { } else {
data = [ data = [
[`Money:`, MoneyRate(5 * props.sleeve.gainRatesForTask.money)], [`Money:`, <MoneyRate money={5 * props.sleeve.gainRatesForTask.money} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.hack)} / s`], [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.hack)} / s`],
[`Strength Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.str)} / s`], [`Strength Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.str)} / s`],
[`Defense Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.def)} / s`], [`Defense Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.def)} / s`],

@ -333,18 +333,18 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<Drawer open={open} anchor="left" variant="permanent"> <Drawer open={open} anchor="left" variant="permanent">
<ListItem classes={{ root: classes.listitem }} button onClick={toggleDrawer}> <ListItem classes={{ root: classes.listitem }} button onClick={toggleDrawer}>
<ListItemIcon> <ListItemIcon>
{!open ? <ChevronRightIcon color={"primary"} /> : <ChevronLeftIcon color={"primary"} />} {!open ? <ChevronRightIcon color="primary" /> : <ChevronLeftIcon color="primary" />}
</ListItemIcon> </ListItemIcon>
<ListItemText primary={<Typography color="primary">Bitburner v{CONSTANTS.Version}</Typography>} /> <ListItemText primary={<Typography>Bitburner v{CONSTANTS.Version}</Typography>} />
</ListItem> </ListItem>
<Divider /> <Divider />
<List> <List>
<ListItem classes={{ root: classes.listitem }} button onClick={() => setHackingOpen((old) => !old)}> <ListItem classes={{ root: classes.listitem }} button onClick={() => setHackingOpen((old) => !old)}>
<ListItemIcon> <ListItemIcon>
<ComputerIcon color={"primary"} /> <ComputerIcon color="primary" />
</ListItemIcon> </ListItemIcon>
<ListItemText primary={<Typography color="primary">Hacking</Typography>} /> <ListItemText primary={<Typography>Hacking</Typography>} />
{hackingOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />} {hackingOpen ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItem> </ListItem>
<Collapse in={hackingOpen} timeout="auto" unmountOnExit> <Collapse in={hackingOpen} timeout="auto" unmountOnExit>
<List> <List>
@ -435,10 +435,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<Divider /> <Divider />
<ListItem classes={{ root: classes.listitem }} button onClick={() => setCharacterOpen((old) => !old)}> <ListItem classes={{ root: classes.listitem }} button onClick={() => setCharacterOpen((old) => !old)}>
<ListItemIcon> <ListItemIcon>
<AccountBoxIcon color={"primary"} /> <AccountBoxIcon color="primary" />
</ListItemIcon> </ListItemIcon>
<ListItemText primary={<Typography color="primary">Character</Typography>} /> <ListItemText primary={<Typography>Character</Typography>} />
{characterOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />} {characterOpen ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItem> </ListItem>
<Collapse in={characterOpen} timeout="auto" unmountOnExit> <Collapse in={characterOpen} timeout="auto" unmountOnExit>
<ListItem <ListItem
@ -545,10 +545,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<Divider /> <Divider />
<ListItem classes={{ root: classes.listitem }} button onClick={() => setWorldOpen((old) => !old)}> <ListItem classes={{ root: classes.listitem }} button onClick={() => setWorldOpen((old) => !old)}>
<ListItemIcon> <ListItemIcon>
<PublicIcon color={"primary"} /> <PublicIcon color="primary" />
</ListItemIcon> </ListItemIcon>
<ListItemText primary={<Typography color="primary">World</Typography>} /> <ListItemText primary={<Typography>World</Typography>} />
{worldOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />} {worldOpen ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItem> </ListItem>
<Collapse in={worldOpen} timeout="auto" unmountOnExit> <Collapse in={worldOpen} timeout="auto" unmountOnExit>
<ListItem <ListItem
@ -678,10 +678,10 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<Divider /> <Divider />
<ListItem classes={{ root: classes.listitem }} button onClick={() => setHelpOpen((old) => !old)}> <ListItem classes={{ root: classes.listitem }} button onClick={() => setHelpOpen((old) => !old)}>
<ListItemIcon> <ListItemIcon>
<LiveHelpIcon color={"primary"} /> <LiveHelpIcon color="primary" />
</ListItemIcon> </ListItemIcon>
<ListItemText primary={<Typography color="primary">Help</Typography>} /> <ListItemText primary={<Typography>Help</Typography>} />
{helpOpen ? <ExpandLessIcon color={"primary"} /> : <ExpandMoreIcon color={"primary"} />} {helpOpen ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItem> </ListItem>
<Collapse in={helpOpen} timeout="auto" unmountOnExit> <Collapse in={helpOpen} timeout="auto" unmountOnExit>
<ListItem <ListItem

@ -8,7 +8,6 @@ import "../css/mainmenu.scss";
import "../css/characteroverview.scss"; import "../css/characteroverview.scss";
import "../css/terminal.scss"; import "../css/terminal.scss";
import "../css/scripteditor.scss"; import "../css/scripteditor.scss";
import "../css/activescripts.scss";
import "../css/hacknetnodes.scss"; import "../css/hacknetnodes.scss";
import "../css/menupages.scss"; import "../css/menupages.scss";
import "../css/augmentations.scss"; import "../css/augmentations.scss";

@ -8,10 +8,11 @@ import { ScriptProduction } from "./ScriptProduction";
import { ServerAccordions } from "./ServerAccordions"; import { ServerAccordions } from "./ServerAccordions";
import { WorkerScript } from "../../Netscript/WorkerScript"; import { WorkerScript } from "../../Netscript/WorkerScript";
import { IPlayer } from "../../PersonObjects/IPlayer";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
type IProps = { type IProps = {
p: IPlayer;
workerScripts: Map<number, WorkerScript>; workerScripts: Map<number, WorkerScript>;
}; };
@ -27,15 +28,15 @@ export function ActiveScriptsRoot(props: IProps): React.ReactElement {
}, []); }, []);
return ( return (
<div className="active-scripts-container"> <>
<p> <Typography>
This page displays a list of all of your scripts that are currently running across every machine. It also This page displays a list of all of your scripts that are currently running across every machine. It also
provides information about each script's production. The scripts are categorized by the hostname of the servers provides information about each script's production. The scripts are categorized by the hostname of the servers
on which they are running. on which they are running.
</p> </Typography>
<ScriptProduction {...props} /> <ScriptProduction {...props} />
<ServerAccordions {...props} /> <ServerAccordions {...props} />
</div> </>
); );
} }

@ -5,16 +5,44 @@
import * as React from "react"; import * as React from "react";
import { WorkerScript } from "../../Netscript/WorkerScript"; import { WorkerScript } from "../../Netscript/WorkerScript";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Money } from "../React/Money"; import { Money } from "../React/Money";
import { MoneyRate } from "../React/MoneyRate";
import { use } from "../Context";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
type IProps = { type IProps = {
p: IPlayer;
workerScripts: Map<number, WorkerScript>; workerScripts: Map<number, WorkerScript>;
}; };
const useStyles = makeStyles((theme: Theme) =>
createStyles({
cell: {
borderBottom: "none",
padding: theme.spacing(1),
margin: theme.spacing(1),
whiteSpace: "nowrap",
},
size: {
width: "1px",
},
}),
);
export function ScriptProduction(props: IProps): React.ReactElement { export function ScriptProduction(props: IProps): React.ReactElement {
const prodRateSinceLastAug = props.p.scriptProdSinceLastAug / (props.p.playtimeSinceLastAug / 1000); const player = use.Player();
const classes = useStyles();
const prodRateSinceLastAug = player.scriptProdSinceLastAug / (player.playtimeSinceLastAug / 1000);
let onlineProduction = 0; let onlineProduction = 0;
for (const ws of props.workerScripts.values()) { for (const ws of props.workerScripts.values()) {
@ -22,27 +50,29 @@ export function ScriptProduction(props: IProps): React.ReactElement {
} }
return ( return (
<p id="active-scripts-total-prod"> <Table size="small" classes={{ root: classes.size }}>
Total online production of Active scripts:&nbsp; <TableBody>
<span className="money-gold"> <TableRow>
<span id="active-scripts-total-production-active"> <TableCell component="th" scope="row" classes={{ root: classes.cell }}>
<Money money={onlineProduction} /> <Typography variant="body2">Total online production of Active scripts:</Typography>
</span>{" "} </TableCell>
/ sec <TableCell align="left" classes={{ root: classes.cell }}>
</span> <Typography variant="body2">
<br /> <Money money={player.scriptProdSinceLastAug} />
Total online production since last Aug installation:&nbsp; </Typography>
<span id="active-scripts-total-prod-aug-total" className="money-gold"> </TableCell>
<Money money={props.p.scriptProdSinceLastAug} /> </TableRow>
</span> <TableRow style={{ width: "1px" }}>
&nbsp;( <TableCell component="th" scope="row" classes={{ root: classes.cell }}>
<span className="money-gold"> <Typography variant="body2">Total online production since last Aug installation:</Typography>
<span id="active-scripts-total-prod-aug-avg" className="money-gold"> </TableCell>
<Money money={prodRateSinceLastAug} /> <TableCell align="left" classes={{ root: classes.cell }}>
</span>{" "} <Typography variant="body2">
/ sec (<MoneyRate money={prodRateSinceLastAug} />)
</span> </Typography>
) </TableCell>
</p> </TableRow>
</TableBody>
</Table>
); );
} }

@ -4,7 +4,15 @@
*/ */
import * as React from "react"; import * as React from "react";
import { BBAccordion } from "../React/BBAccordion"; import Typography from "@mui/material/Typography";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemText from "@mui/material/ListItemText";
import Paper from "@mui/material/Paper";
import Collapse from "@mui/material/Collapse";
import ExpandMore from "@mui/icons-material/ExpandMore";
import ExpandLess from "@mui/icons-material/ExpandLess";
import { ServerAccordionContent } from "./ServerAccordionContent"; import { ServerAccordionContent } from "./ServerAccordionContent";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
@ -18,6 +26,7 @@ type IProps = {
}; };
export function ServerAccordion(props: IProps): React.ReactElement { export function ServerAccordion(props: IProps): React.ReactElement {
const [open, setOpen] = React.useState(false);
const server = props.server; const server = props.server;
// Accordion's header text // Accordion's header text
@ -34,9 +43,14 @@ export function ServerAccordion(props: IProps): React.ReactElement {
const headerTxt = `${paddedName} ${createProgressBarText(barOptions)}`; const headerTxt = `${paddedName} ${createProgressBarText(barOptions)}`;
return ( return (
<BBAccordion <>
headerContent={<pre>{headerTxt}</pre>} <ListItemButton onClick={() => setOpen((old) => !old)} component={Paper}>
panelContent={<ServerAccordionContent workerScripts={props.workerScripts} />} <ListItemText primary={<Typography style={{ whiteSpace: "pre-wrap" }}>{headerTxt}</Typography>} />
/> {open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
</ListItemButton>
<Collapse in={open} timeout={0} unmountOnExit>
<ServerAccordionContent workerScripts={props.workerScripts} />
</Collapse>
</>
); );
} }

@ -2,6 +2,10 @@ import React, { useState } from "react";
import { WorkerScript } from "../../Netscript/WorkerScript"; import { WorkerScript } from "../../Netscript/WorkerScript";
import { WorkerScriptAccordion } from "./WorkerScriptAccordion"; import { WorkerScriptAccordion } from "./WorkerScriptAccordion";
import { AccordionButton } from "../React/AccordionButton"; import { AccordionButton } from "../React/AccordionButton";
import Paper from "@mui/material/Paper";
import List from "@mui/material/List";
import TablePagination from "@mui/material/TablePagination";
import { TablePaginationActionsAll } from "../React/TablePaginationActionsAll";
const pageSize = 20; const pageSize = 20;
@ -10,61 +14,34 @@ interface IProps {
} }
export function ServerAccordionContent(props: IProps): React.ReactElement { export function ServerAccordionContent(props: IProps): React.ReactElement {
if (props.workerScripts.length > pageSize) {
return <ServerAccordionContentPaginated workerScripts={props.workerScripts} />;
}
const scripts = props.workerScripts.map((ws) => {
return <WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />;
});
return <ul>{scripts}</ul>;
}
export function ServerAccordionContentPaginated(props: IProps): React.ReactElement {
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const scripts: React.ReactElement[] = []; const [rowsPerPage, setRowsPerPage] = useState(10);
const maxPage = Math.ceil(props.workerScripts.length / pageSize); const handleChangePage = (event: unknown, newPage: number) => {
const maxScript = Math.min((page + 1) * pageSize, props.workerScripts.length); setPage(newPage);
for (let i = page * pageSize; i < maxScript; i++) { };
const ws = props.workerScripts[i];
scripts.push(<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />);
}
function capPage(page: number): number { const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
if (page < 0) { setRowsPerPage(parseInt(event.target.value, 10));
page = 0; setPage(0);
} };
if (maxPage - 1 < page) {
page = maxPage - 1;
}
return page;
}
// in case we're on an invalid page number because scripts were killed.
const capped = capPage(page);
if (capped !== page) setPage(capped);
function changePage(n: number): void {
setPage((newPage) => {
newPage += n;
newPage = Math.round(newPage);
return capPage(newPage);
});
}
return ( return (
<> <>
<ul>{scripts}</ul> <List>
<AccordionButton onClick={() => changePage(-1e99)} text="<<" /> {props.workerScripts.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((ws) => (
<AccordionButton onClick={() => changePage(-1)} text="<" /> <WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
<span className="text"> ))}
{page + 1} / {maxPage} </List>
</span> <TablePagination
<AccordionButton onClick={() => changePage(1)} text=">" /> rowsPerPageOptions={[10, 15, 20]}
<AccordionButton onClick={() => changePage(1e99)} text=">>" /> component="div"
count={props.workerScripts.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActionsAll}
/>
</> </>
); );
} }

@ -2,14 +2,20 @@
* React Component for rendering the Accordion elements for all servers * React Component for rendering the Accordion elements for all servers
* on which scripts are running * on which scripts are running
*/ */
import * as React from "react"; import React, { useState, useEffect } from "react";
import { ServerAccordion } from "./ServerAccordion"; import { ServerAccordion } from "./ServerAccordion";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import Paper from "@mui/material/Paper";
import List from "@mui/material/List";
import TablePagination from "@mui/material/TablePagination";
import { WorkerScript } from "../../Netscript/WorkerScript"; import { WorkerScript } from "../../Netscript/WorkerScript";
import { WorkerScriptStartStopEventEmitter } from "../../Netscript/WorkerScriptStartStopEventEmitter"; import { WorkerScriptStartStopEventEmitter } from "../../Netscript/WorkerScriptStartStopEventEmitter";
import { getServer } from "../../Server/ServerHelpers"; import { getServer } from "../../Server/ServerHelpers";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
import { TablePaginationActionsAll } from "../React/TablePaginationActionsAll";
// Map of server hostname -> all workerscripts on that server for all active scripts // Map of server hostname -> all workerscripts on that server for all active scripts
interface IServerData { interface IServerData {
@ -18,7 +24,7 @@ interface IServerData {
} }
interface IServerToScriptsMap { interface IServerToScriptsMap {
[key: string]: IServerData; [key: string]: IServerData | undefined;
} }
type IProps = { type IProps = {
@ -31,72 +37,91 @@ type IState = {
const subscriberId = "ActiveScriptsUI"; const subscriberId = "ActiveScriptsUI";
export class ServerAccordions extends React.Component<IProps, IState> { export function ServerAccordions(props: IProps): React.ReactElement {
serverToScriptMap: IServerToScriptsMap = {}; const [filter, setFilter] = useState("");
const [page, setPage] = useState(0);
constructor(props: IProps) { const [rowsPerPage, setRowsPerPage] = useState(10);
super(props); const setRerender = useState(false)[1];
function rerender(): void {
this.state = { setRerender((old) => !old);
rerenderFlag: false,
};
this.updateServerToScriptsMap();
this.rerender = this.rerender.bind(this);
} }
componentDidMount(): void { useEffect(() => {
WorkerScriptStartStopEventEmitter.addSubscriber({ WorkerScriptStartStopEventEmitter.addSubscriber({
cb: this.rerender, cb: rerender,
id: subscriberId, id: subscriberId,
}); });
return () => WorkerScriptStartStopEventEmitter.removeSubscriber(subscriberId);
}, []);
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
function handleFilterChange(event: React.ChangeEvent<HTMLInputElement>): void {
setFilter(event.target.value);
setPage(0);
} }
componentWillUnmount(): void { const serverToScriptMap: IServerToScriptsMap = {};
WorkerScriptStartStopEventEmitter.removeSubscriber(subscriberId); for (const ws of props.workerScripts.values()) {
}
updateServerToScriptsMap(): void {
const map: IServerToScriptsMap = {};
for (const ws of this.props.workerScripts.values()) {
const server = getServer(ws.serverIp); const server = getServer(ws.serverIp);
if (server == null) { if (server == null) {
console.warn(`WorkerScript has invalid IP address: ${ws.serverIp}`); console.warn(`WorkerScript has invalid IP address: ${ws.serverIp}`);
continue; continue;
} }
if (map[server.hostname] == null) { let data = serverToScriptMap[server.hostname];
map[server.hostname] = {
if (data === undefined) {
serverToScriptMap[server.hostname] = {
server: server, server: server,
workerScripts: [], workerScripts: [],
}; };
data = serverToScriptMap[server.hostname];
}
if (data !== undefined) data.workerScripts.push(ws);
} }
map[server.hostname].workerScripts.push(ws); const filtered = Object.values(serverToScriptMap).filter((data) => data && data.server.hostname.includes(filter));
}
this.serverToScriptMap = map;
}
rerender(): void {
this.updateServerToScriptsMap();
this.setState((prevState) => {
return { rerenderFlag: !prevState.rerenderFlag };
});
}
render(): React.ReactNode {
const elems = Object.keys(this.serverToScriptMap).map((serverName) => {
const data = this.serverToScriptMap[serverName];
return <ServerAccordion key={serverName} server={data.server} workerScripts={data.workerScripts} />;
});
return ( return (
<ul className="active-scripts-list" id="active-scripts-list"> <>
{elems} <TextField
</ul> value={filter}
onChange={handleFilterChange}
color="primary"
autoFocus
variant="standard"
InputProps={{
startAdornment: <Typography m={1}>Filter:</Typography>,
spellCheck: false,
}}
/>
<List>
{filtered.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((data) => {
return (
data && (
<ServerAccordion key={data.server.hostname} server={data.server} workerScripts={data.workerScripts} />
)
);
})}
</List>
<TablePagination
rowsPerPageOptions={[10, 15, 20]}
component="div"
count={filtered.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActionsAll}
/>
</>
); );
}
} }

@ -6,8 +6,23 @@ import * as React from "react";
import { numeralWrapper } from "../numeralFormat"; import { numeralWrapper } from "../numeralFormat";
import { BBAccordion } from "../React/BBAccordion"; import Button from "@mui/material/Button";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";
import Accordion from "@mui/material/Accordion";
import AccordionSummary from "@mui/material/AccordionSummary";
import AccordionDetails from "@mui/material/AccordionDetails";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { AccordionButton } from "../React/AccordionButton"; import { AccordionButton } from "../React/AccordionButton";
import IconButton from "@mui/material/IconButton";
import DeleteIcon from "@mui/icons-material/Delete";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemText from "@mui/material/ListItemText";
import Collapse from "@mui/material/Collapse";
import ExpandMore from "@mui/icons-material/ExpandMore";
import ExpandLess from "@mui/icons-material/ExpandLess";
import { killWorkerScript } from "../../Netscript/killWorkerScript"; import { killWorkerScript } from "../../Netscript/killWorkerScript";
import { WorkerScript } from "../../Netscript/WorkerScript"; import { WorkerScript } from "../../Netscript/WorkerScript";
@ -23,6 +38,7 @@ type IProps = {
}; };
export function WorkerScriptAccordion(props: IProps): React.ReactElement { export function WorkerScriptAccordion(props: IProps): React.ReactElement {
const [open, setOpen] = React.useState(false);
const workerScript = props.workerScript; const workerScript = props.workerScript;
const scriptRef = workerScript.scriptRef; const scriptRef = workerScript.scriptRef;
@ -41,12 +57,13 @@ export function WorkerScriptAccordion(props: IProps): React.ReactElement {
const offlineEps = scriptRef.offlineExpGained / scriptRef.offlineRunningTime; const offlineEps = scriptRef.offlineExpGained / scriptRef.offlineRunningTime;
return ( return (
<BBAccordion
headerClass="active-scripts-script-header"
headerContent={<>{props.workerScript.name}</>}
panelClass="active-scripts-script-panel"
panelContent={
<> <>
<ListItemButton onClick={() => setOpen((old) => !old)} component={Paper}>
<ListItemText primary={<Typography style={{ whiteSpace: "pre-wrap" }}>{props.workerScript.name}</Typography>} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout={0} unmountOnExit>
<Box m={3}>
<pre>Threads: {numeralWrapper.formatThreads(props.workerScript.scriptRef.threads)}</pre> <pre>Threads: {numeralWrapper.formatThreads(props.workerScript.scriptRef.threads)}</pre>
<pre>Args: {arrayToString(props.workerScript.args)}</pre> <pre>Args: {arrayToString(props.workerScript.args)}</pre>
<pre>Online Time: {convertTimeMsToTimeElapsedString(scriptRef.onlineRunningTime * 1e3)}</pre> <pre>Online Time: {convertTimeMsToTimeElapsedString(scriptRef.onlineRunningTime * 1e3)}</pre>
@ -68,10 +85,14 @@ export function WorkerScriptAccordion(props: IProps): React.ReactElement {
</pre> </pre>
<pre>{Array(26).join(" ") + numeralWrapper.formatExp(offlineEps) + " hacking exp / second"}</pre> <pre>{Array(26).join(" ") + numeralWrapper.formatExp(offlineEps) + " hacking exp / second"}</pre>
<AccordionButton onClick={logClickHandler} text="Log" /> <Button onClick={logClickHandler}>
<AccordionButton onClick={killScriptClickHandler} text="Kill Script" /> <Typography>Log</Typography>
</Button>
<IconButton onClick={killScriptClickHandler}>
<DeleteIcon color="error" />
</IconButton>
</Box>
</Collapse>
</> </>
}
/>
); );
} }

@ -278,7 +278,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
) : page === Page.CreateScript ? ( ) : page === Page.CreateScript ? (
<ScriptEditorRoot filename={filename} code={code} player={player} router={Router} /> <ScriptEditorRoot filename={filename} code={code} player={player} router={Router} />
) : page === Page.ActiveScripts ? ( ) : page === Page.ActiveScripts ? (
<ActiveScriptsRoot p={player} workerScripts={workerScripts} /> <ActiveScriptsRoot workerScripts={workerScripts} />
) : page === Page.Hacknet ? ( ) : page === Page.Hacknet ? (
<HacknetRoot player={player} /> <HacknetRoot player={player} />
) : page === Page.CreateProgram ? ( ) : page === Page.CreateProgram ? (

@ -257,7 +257,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={<Switch color="primary" checked={suppressMessages} onChange={handleSuppressMessagesChange} />} control={<Switch checked={suppressMessages} onChange={handleSuppressMessagesChange} />}
label={ label={
<Tooltip <Tooltip
title={ title={
@ -275,13 +275,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={ control={<Switch checked={suppressFactionInvites} onChange={handleSuppressFactionInvitesChange} />}
<Switch
color="primary"
checked={suppressFactionInvites}
onChange={handleSuppressFactionInvitesChange}
/>
}
label={ label={
<Tooltip <Tooltip
title={ title={
@ -299,11 +293,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={ control={
<Switch <Switch checked={suppressTravelConfirmations} onChange={handleSuppressTravelConfirmationsChange} />
color="primary"
checked={suppressTravelConfirmations}
onChange={handleSuppressTravelConfirmationsChange}
/>
} }
label={ label={
<Tooltip <Tooltip
@ -323,7 +313,6 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<FormControlLabel <FormControlLabel
control={ control={
<Switch <Switch
color="primary"
checked={suppressBuyAugmentationConfirmation} checked={suppressBuyAugmentationConfirmation}
onChange={handleSuppressBuyAugmentationConfirmationChange} onChange={handleSuppressBuyAugmentationConfirmationChange}
/> />
@ -344,11 +333,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={ control={
<Switch <Switch checked={suppressHospitalizationPopup} onChange={handleSuppressHospitalizationPopupChange} />
color="primary"
checked={suppressHospitalizationPopup}
onChange={handleSuppressHospitalizationPopupChange}
/>
} }
label={ label={
<Tooltip <Tooltip
@ -368,11 +353,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={ control={
<Switch <Switch checked={suppressBladeburnerPopup} onChange={handleSuppressBladeburnerPopupChange} />
color="primary"
checked={suppressBladeburnerPopup}
onChange={handleSuppressBladeburnerPopupChange}
/>
} }
label={ label={
<Tooltip <Tooltip
@ -391,7 +372,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
)} )}
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={<Switch color="primary" checked={disableHotkeys} onChange={handleDisableHotkeysChange} />} control={<Switch checked={disableHotkeys} onChange={handleDisableHotkeysChange} />}
label={ label={
<Tooltip <Tooltip
title={ title={
@ -409,7 +390,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={<Switch color="primary" checked={disableASCIIArt} onChange={handleDisableASCIIArtChange} />} control={<Switch checked={disableASCIIArt} onChange={handleDisableASCIIArtChange} />}
label={ label={
<Tooltip title={<Typography>If this is set all ASCII art will be disabled.</Typography>}> <Tooltip title={<Typography>If this is set all ASCII art will be disabled.</Typography>}>
<Typography>Disable ascii art</Typography> <Typography>Disable ascii art</Typography>
@ -419,9 +400,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
</ListItem> </ListItem>
<ListItem> <ListItem>
<FormControlLabel <FormControlLabel
control={ control={<Switch checked={disableTextEffects} onChange={handleDisableTextEffectsChange} />}
<Switch color="primary" checked={disableTextEffects} onChange={handleDisableTextEffectsChange} />
}
label={ label={
<Tooltip <Tooltip
title={ title={

@ -2,6 +2,6 @@ import React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
export function MoneyRate(money: number): JSX.Element { export function MoneyRate({ money }: { money: number }): JSX.Element {
return <Money money={`${numeralWrapper.formatMoney(money)} / sec`} />; return <Money money={`${numeralWrapper.formatMoney(money)} / sec`} />;
} }

@ -0,0 +1,69 @@
import * as React from "react";
import { useTheme } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableFooter from "@mui/material/TableFooter";
import TablePagination from "@mui/material/TablePagination";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import IconButton from "@mui/material/IconButton";
import FirstPageIcon from "@mui/icons-material/FirstPage";
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft";
import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight";
import LastPageIcon from "@mui/icons-material/LastPage";
interface TablePaginationActionsProps {
count: number;
page: number;
rowsPerPage: number;
onPageChange: (event: React.MouseEvent<HTMLButtonElement>, newPage: number) => void;
}
export function TablePaginationActionsAll(props: TablePaginationActionsProps) {
const theme = useTheme();
const { count, page, rowsPerPage, onPageChange } = props;
const handleFirstPageButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
onPageChange(event, 0);
};
const handleBackButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
onPageChange(event, page - 1);
};
const handleNextButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
onPageChange(event, page + 1);
};
const handleLastPageButtonClick = (event: React.MouseEvent<HTMLButtonElement>) => {
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<Box sx={{ flexShrink: 0, ml: 2.5 }}>
<IconButton onClick={handleFirstPageButtonClick} disabled={page === 0} aria-label="first page">
{theme.direction === "rtl" ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
{theme.direction === "rtl" ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
</IconButton>
<IconButton
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
{theme.direction === "rtl" ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
</IconButton>
<IconButton
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
{theme.direction === "rtl" ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</Box>
);
}

@ -19,6 +19,14 @@ export const colors = {
secondary: "#888", secondary: "#888",
secondarydark: "#666", secondarydark: "#666",
warninglight: "#ff0",
warning: "#cc0",
warningdark: "#990",
infolight: "#69f",
info: "#36c",
infodark: "#039",
welllight: "#444", welllight: "#444",
well: "#222", well: "#222",
white: "#fff", white: "#fff",
@ -49,6 +57,16 @@ export const theme = createTheme({
main: colors.error, main: colors.error,
dark: colors.errordark, dark: colors.errordark,
}, },
info: {
light: colors.infolight,
main: colors.info,
dark: colors.infodark,
},
warning: {
light: colors.warninglight,
main: colors.warning,
dark: colors.warningdark,
},
background: { background: {
paper: colors.well, paper: colors.well,
}, },
@ -64,9 +82,9 @@ export const theme = createTheme({
styleOverrides: { styleOverrides: {
root: { root: {
backgroundColor: colors.well, backgroundColor: colors.well,
color: colors.primary,
}, },
input: { input: {
color: colors.primary,
"&::placeholder": { "&::placeholder": {
userSelect: "none", userSelect: "none",
color: colors.primarydark, color: colors.primarydark,
@ -225,11 +243,19 @@ export const theme = createTheme({
MuiPaper: { MuiPaper: {
styleOverrides: { styleOverrides: {
root: { root: {
borderRadius: 0,
backgroundColor: colors.black, backgroundColor: colors.black,
border: "1px solid " + colors.welllight, border: "1px solid " + colors.welllight,
}, },
}, },
}, },
MuiTablePagination: {
styleOverrides: {
select: {
color: colors.primary,
},
},
},
}, },
}); });

@ -47,7 +47,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<br /> <br />
You have earned: <br /> You have earned: <br />
<br /> <br />
<Money money={player.workMoneyGained} /> ({MoneyRate(player.workMoneyGainRate * CYCLES_PER_SEC)}) <br /> <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br />
<br /> <br />
{Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation for {Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation for
this faction <br /> this faction <br />
@ -112,7 +113,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<br /> <br />
<br /> <br />
This has cost you: <br /> This has cost you: <br />
<Money money={-player.workMoneyGained} /> ({MoneyRate(player.workMoneyLossRate * CYCLES_PER_SEC)}) <br /> <Money money={-player.workMoneyGained} /> (<MoneyRate money={player.workMoneyLossRate * CYCLES_PER_SEC} />){" "}
<br />
<br /> <br />
You have gained: <br /> You have gained: <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( {numeralWrapper.formatExp(player.workHackExpGained)} (
@ -173,7 +175,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<br /> <br />
You have earned: <br /> You have earned: <br />
<br /> <br />
<Money money={player.workMoneyGained} /> ({MoneyRate(player.workMoneyGainRate * CYCLES_PER_SEC)}) <br /> <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br />
<br /> <br />
{Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation for {Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation for
this company <br /> this company <br />
@ -241,7 +244,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<br /> <br />
You have earned: <br /> You have earned: <br />
<br /> <br />
<Money money={player.workMoneyGained} /> ({MoneyRate(player.workMoneyGainRate * CYCLES_PER_SEC)}) <br /> <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br />
<br /> <br />
{Reputation(player.workRepGained)} ( {Reputation(player.workRepGained)} (
{Reputation(`${numeralWrapper.formatExp(player.workRepGainRate * CYCLES_PER_SEC)} / sec`)} {Reputation(`${numeralWrapper.formatExp(player.workRepGainRate * CYCLES_PER_SEC)} / sec`)}