2021-10-01 07:00:50 +02:00
|
|
|
import React, { useState, useEffect, useRef } from "react";
|
|
|
|
import { EventEmitter } from "../../utils/EventEmitter";
|
|
|
|
import { RunningScript } from "../../Script/RunningScript";
|
|
|
|
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
|
|
|
import Typography from "@mui/material/Typography";
|
|
|
|
import Box from "@mui/material/Box";
|
|
|
|
import Button from "@mui/material/Button";
|
|
|
|
import Paper from "@mui/material/Paper";
|
2021-10-05 06:59:40 +02:00
|
|
|
import Draggable from "react-draggable";
|
2021-10-05 07:23:20 +02:00
|
|
|
import { ResizableBox } from "react-resizable";
|
2021-10-07 21:02:54 +02:00
|
|
|
import makeStyles from "@mui/styles/makeStyles";
|
|
|
|
import createStyles from "@mui/styles/createStyles";
|
2021-10-05 07:23:20 +02:00
|
|
|
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
2021-11-17 23:33:44 +01:00
|
|
|
import { workerScripts } from "../../Netscript/WorkerScripts";
|
|
|
|
import { startWorkerScript } from "../../NetscriptWorker";
|
|
|
|
import { GetServer } from "../../Server/AllServers";
|
2021-11-19 21:44:12 +01:00
|
|
|
import { Theme } from "@mui/material";
|
2021-12-21 18:00:12 +01:00
|
|
|
import { findRunningScript } from "../../Script/ScriptHelpers";
|
2022-01-05 01:09:34 +01:00
|
|
|
import { Player } from "../../Player";
|
2022-01-13 02:56:46 +01:00
|
|
|
import { debounce } from "lodash";
|
2021-10-15 20:16:30 +02:00
|
|
|
|
|
|
|
let layerCounter = 0;
|
2021-10-01 07:00:50 +02:00
|
|
|
|
|
|
|
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
2021-11-27 00:47:12 +01:00
|
|
|
export const LogBoxClearEvents = new EventEmitter<[]>();
|
2021-10-01 07:00:50 +02:00
|
|
|
|
|
|
|
interface Log {
|
|
|
|
id: string;
|
|
|
|
script: RunningScript;
|
|
|
|
}
|
|
|
|
|
2021-11-14 01:50:39 +01:00
|
|
|
let logs: Log[] = [];
|
|
|
|
|
2021-10-01 07:00:50 +02:00
|
|
|
export function LogBoxManager(): React.ReactElement {
|
2021-11-14 01:50:39 +01:00
|
|
|
const setRerender = useState(true)[1];
|
|
|
|
function rerender(): void {
|
|
|
|
setRerender((o) => !o);
|
|
|
|
}
|
2021-10-01 07:00:50 +02:00
|
|
|
useEffect(
|
|
|
|
() =>
|
|
|
|
LogBoxEvents.subscribe((script: RunningScript) => {
|
|
|
|
const id = script.server + "-" + script.filename + script.args.map((x: any): string => `${x}`).join("-");
|
2022-01-16 22:21:02 +01:00
|
|
|
if (logs.find((l) => l.id === id)) return;
|
|
|
|
logs.push({
|
|
|
|
id: id,
|
|
|
|
script: script,
|
|
|
|
});
|
|
|
|
rerender();
|
2021-10-01 07:00:50 +02:00
|
|
|
}),
|
|
|
|
[],
|
|
|
|
);
|
|
|
|
|
2021-11-27 00:47:12 +01:00
|
|
|
useEffect(() =>
|
|
|
|
LogBoxClearEvents.subscribe(() => {
|
|
|
|
logs = [];
|
|
|
|
rerender();
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
2021-10-01 07:00:50 +02:00
|
|
|
function close(id: string): void {
|
2021-11-14 01:50:39 +01:00
|
|
|
logs = logs.filter((l) => l.id !== id);
|
|
|
|
rerender();
|
2021-10-01 07:00:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{logs.map((log) => (
|
|
|
|
<LogWindow key={log.id} script={log.script} id={log.id} onClose={() => close(log.id)} />
|
|
|
|
))}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
script: RunningScript;
|
|
|
|
id: string;
|
|
|
|
onClose: () => void;
|
|
|
|
}
|
|
|
|
|
2021-11-19 21:44:12 +01:00
|
|
|
const useStyles = makeStyles((theme: Theme) =>
|
2021-10-07 21:02:54 +02:00
|
|
|
createStyles({
|
2021-12-26 23:38:25 +01:00
|
|
|
title: {
|
|
|
|
"&.is-minimized + *": {
|
2022-01-05 01:09:34 +01:00
|
|
|
border: "none",
|
|
|
|
margin: 0,
|
|
|
|
"max-height": 0,
|
|
|
|
padding: 0,
|
|
|
|
"pointer-events": "none",
|
|
|
|
visibility: "hidden",
|
2021-12-26 23:38:25 +01:00
|
|
|
},
|
|
|
|
},
|
2021-10-07 21:02:54 +02:00
|
|
|
logs: {
|
|
|
|
overflowY: "scroll",
|
|
|
|
overflowX: "hidden",
|
|
|
|
scrollbarWidth: "auto",
|
|
|
|
display: "flex",
|
|
|
|
flexDirection: "column-reverse",
|
|
|
|
},
|
2022-04-23 22:48:48 +02:00
|
|
|
titleButton: {
|
|
|
|
padding: "1px 6px",
|
|
|
|
},
|
2021-11-19 21:44:12 +01:00
|
|
|
success: {
|
|
|
|
color: theme.colors.success,
|
|
|
|
},
|
|
|
|
error: {
|
|
|
|
color: theme.palette.error.main,
|
|
|
|
},
|
|
|
|
primary: {
|
|
|
|
color: theme.palette.primary.main,
|
|
|
|
},
|
|
|
|
info: {
|
|
|
|
color: theme.palette.info.main,
|
|
|
|
},
|
|
|
|
warning: {
|
|
|
|
color: theme.palette.warning.main,
|
|
|
|
},
|
2021-10-07 21:02:54 +02:00
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
2022-01-08 15:59:31 +01:00
|
|
|
export const logBoxBaseZIndex = 1500;
|
|
|
|
|
2021-10-01 07:00:50 +02:00
|
|
|
function LogWindow(props: IProps): React.ReactElement {
|
2022-01-13 02:56:46 +01:00
|
|
|
const draggableRef = useRef<HTMLDivElement>(null);
|
2022-03-29 23:19:14 +02:00
|
|
|
const rootRef = useRef<Draggable>(null);
|
2021-12-21 18:00:12 +01:00
|
|
|
const [script, setScript] = useState(props.script);
|
2021-10-07 21:02:54 +02:00
|
|
|
const classes = useStyles();
|
2021-10-01 07:00:50 +02:00
|
|
|
const container = useRef<HTMLDivElement>(null);
|
|
|
|
const setRerender = useState(false)[1];
|
2021-12-26 23:38:25 +01:00
|
|
|
const [minimized, setMinimized] = useState(false);
|
2021-10-01 07:00:50 +02:00
|
|
|
function rerender(): void {
|
|
|
|
setRerender((old) => !old);
|
|
|
|
}
|
|
|
|
|
2022-03-29 23:19:14 +02:00
|
|
|
// useEffect(
|
|
|
|
// () =>
|
|
|
|
// WorkerScriptStartStopEventEmitter.subscribe(() => {
|
|
|
|
// setTimeout(() => {
|
|
|
|
// const server = GetServer(script.server);
|
|
|
|
// if (server === null) return;
|
|
|
|
// const exisitingScript = findRunningScript(script.filename, script.args, server);
|
|
|
|
// if (exisitingScript) {
|
|
|
|
// exisitingScript.logs = script.logs.concat(exisitingScript.logs)
|
|
|
|
// setScript(exisitingScript)
|
|
|
|
// }
|
|
|
|
// rerender();
|
|
|
|
// }, 100)
|
|
|
|
// }),
|
|
|
|
// [],
|
|
|
|
// );
|
2022-03-21 12:56:54 +01:00
|
|
|
|
2021-10-01 07:00:50 +02:00
|
|
|
useEffect(() => {
|
2021-12-03 20:12:32 +01:00
|
|
|
updateLayer();
|
2021-10-01 07:00:50 +02:00
|
|
|
const id = setInterval(rerender, 1000);
|
|
|
|
return () => clearInterval(id);
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
function kill(): void {
|
2021-12-21 18:00:12 +01:00
|
|
|
killWorkerScript(script, script.server, true);
|
2021-11-17 23:33:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function run(): void {
|
2021-12-21 18:00:12 +01:00
|
|
|
const server = GetServer(script.server);
|
2021-11-17 23:33:44 +01:00
|
|
|
if (server === null) return;
|
2021-12-21 18:00:12 +01:00
|
|
|
const s = findRunningScript(script.filename, script.args, server);
|
|
|
|
if (s === null) {
|
2022-01-05 01:09:34 +01:00
|
|
|
startWorkerScript(Player, script, server);
|
2021-12-21 18:00:12 +01:00
|
|
|
} else {
|
|
|
|
setScript(s);
|
|
|
|
}
|
2021-10-01 07:00:50 +02:00
|
|
|
}
|
2021-10-15 19:49:03 +02:00
|
|
|
|
2021-10-15 19:59:42 +02:00
|
|
|
function updateLayer(): void {
|
2021-10-15 19:49:03 +02:00
|
|
|
const c = container.current;
|
|
|
|
if (c === null) return;
|
2022-01-08 15:59:31 +01:00
|
|
|
c.style.zIndex = logBoxBaseZIndex + layerCounter + "";
|
2021-10-15 20:16:30 +02:00
|
|
|
layerCounter++;
|
2021-10-15 19:49:03 +02:00
|
|
|
rerender();
|
|
|
|
}
|
2021-10-01 07:00:50 +02:00
|
|
|
|
2021-12-26 23:33:15 +01:00
|
|
|
function title(full = false): string {
|
2021-10-16 02:59:16 +02:00
|
|
|
const maxLength = 30;
|
2021-12-21 18:00:12 +01:00
|
|
|
const t = `${script.filename} ${script.args.map((x: any): string => `${x}`).join(" ")}`;
|
2021-12-26 23:33:15 +01:00
|
|
|
if (full || t.length <= maxLength) {
|
2021-10-16 02:59:16 +02:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
return t.slice(0, maxLength - 3) + "...";
|
|
|
|
}
|
|
|
|
|
2021-12-26 23:38:25 +01:00
|
|
|
function minimize(): void {
|
|
|
|
setMinimized(!minimized);
|
|
|
|
}
|
|
|
|
|
2021-11-19 21:44:12 +01:00
|
|
|
function lineClass(s: string): string {
|
2021-11-26 23:55:14 +01:00
|
|
|
if (s.match(/(^\[[^\]]+\] )?ERROR/) || s.match(/(^\[[^\]]+\] )?FAIL/)) {
|
2021-11-19 21:44:12 +01:00
|
|
|
return classes.error;
|
|
|
|
}
|
2021-11-26 23:55:14 +01:00
|
|
|
if (s.match(/(^\[[^\]]+\] )?SUCCESS/)) {
|
2021-11-19 21:44:12 +01:00
|
|
|
return classes.success;
|
|
|
|
}
|
2021-11-26 23:55:14 +01:00
|
|
|
if (s.match(/(^\[[^\]]+\] )?WARN/)) {
|
2021-11-19 21:44:12 +01:00
|
|
|
return classes.warning;
|
|
|
|
}
|
2021-11-26 23:55:14 +01:00
|
|
|
if (s.match(/(^\[[^\]]+\] )?INFO/)) {
|
2021-11-19 21:44:12 +01:00
|
|
|
return classes.info;
|
|
|
|
}
|
|
|
|
return classes.primary;
|
|
|
|
}
|
|
|
|
|
2022-01-13 02:56:46 +01:00
|
|
|
// And trigger fakeDrag when the window is resized
|
|
|
|
useEffect(() => {
|
2022-01-16 02:51:12 +01:00
|
|
|
window.addEventListener("resize", onResize);
|
2022-01-13 02:56:46 +01:00
|
|
|
return () => {
|
2022-01-16 02:51:12 +01:00
|
|
|
window.removeEventListener("resize", onResize);
|
2022-01-13 02:56:46 +01:00
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
2022-01-16 02:51:12 +01:00
|
|
|
const onResize = debounce((): void => {
|
2022-01-13 02:56:46 +01:00
|
|
|
const node = draggableRef?.current;
|
|
|
|
if (!node) return;
|
|
|
|
|
2022-03-21 12:56:54 +01:00
|
|
|
if (!isOnScreen(node)) {
|
2022-01-16 02:51:12 +01:00
|
|
|
resetPosition();
|
|
|
|
}
|
2022-01-13 02:56:46 +01:00
|
|
|
}, 100);
|
|
|
|
|
2022-01-16 02:51:12 +01:00
|
|
|
const isOnScreen = (node: HTMLDivElement): boolean => {
|
|
|
|
const bounds = node.getBoundingClientRect();
|
|
|
|
|
2022-03-29 23:19:14 +02:00
|
|
|
return !(bounds.right < 0 || bounds.bottom < 0 || bounds.left > innerWidth || bounds.top > outerWidth);
|
|
|
|
};
|
2022-01-16 02:51:12 +01:00
|
|
|
|
|
|
|
const resetPosition = (): void => {
|
|
|
|
const node = rootRef?.current;
|
|
|
|
if (!node) return;
|
2022-03-21 12:56:54 +01:00
|
|
|
const state = node.state as { x: number; y: number };
|
2022-01-16 02:51:12 +01:00
|
|
|
state.x = 0;
|
|
|
|
state.y = 0;
|
|
|
|
node.setState(state);
|
2022-03-29 23:19:14 +02:00
|
|
|
};
|
2022-01-16 02:51:12 +01:00
|
|
|
|
|
|
|
const boundToBody = (e: any): void | false => {
|
2022-03-29 23:19:14 +02:00
|
|
|
if (e.clientX < 0 || e.clientY < 0 || e.clientX > innerWidth || e.clientY > innerHeight) return false;
|
|
|
|
};
|
2022-01-13 02:56:46 +01:00
|
|
|
|
2021-10-01 07:00:50 +02:00
|
|
|
return (
|
2022-01-16 02:51:12 +01:00
|
|
|
<Draggable handle=".drag" onDrag={boundToBody} ref={rootRef}>
|
2021-10-01 07:00:50 +02:00
|
|
|
<Paper
|
|
|
|
style={{
|
2021-10-05 06:59:40 +02:00
|
|
|
display: "flex",
|
|
|
|
flexFlow: "column",
|
|
|
|
position: "fixed",
|
2021-10-05 07:30:37 +02:00
|
|
|
left: "40%",
|
|
|
|
top: "30%",
|
|
|
|
zIndex: 1400,
|
2021-10-01 07:00:50 +02:00
|
|
|
}}
|
2021-10-05 06:59:40 +02:00
|
|
|
ref={container}
|
2021-10-01 07:00:50 +02:00
|
|
|
>
|
2021-10-15 19:59:42 +02:00
|
|
|
<div onMouseDown={updateLayer}>
|
|
|
|
<Paper
|
2022-01-05 01:09:34 +01:00
|
|
|
className={classes.title + " " + (minimized ? "is-minimized" : "")}
|
2021-10-15 19:59:42 +02:00
|
|
|
style={{
|
|
|
|
cursor: "grab",
|
|
|
|
}}
|
2021-10-05 07:23:20 +02:00
|
|
|
>
|
2022-01-13 02:56:46 +01:00
|
|
|
<Box className="drag" display="flex" alignItems="center" ref={draggableRef}>
|
2022-04-23 22:48:48 +02:00
|
|
|
<Typography color="primary" variant="h6" sx={{ marginRight: "auto" }} title={title(true)}>
|
2021-10-16 02:59:16 +02:00
|
|
|
{title()}
|
2021-10-15 19:59:42 +02:00
|
|
|
</Typography>
|
|
|
|
|
2022-04-23 22:48:48 +02:00
|
|
|
{!workerScripts.has(script.pid) && (
|
|
|
|
<Button className={classes.titleButton} onClick={run} onTouchEnd={run}>
|
|
|
|
Run
|
2022-04-17 23:40:37 +02:00
|
|
|
</Button>
|
2022-04-23 22:48:48 +02:00
|
|
|
)}
|
|
|
|
{workerScripts.has(script.pid) && (
|
|
|
|
<Button className={classes.titleButton} onClick={kill} onTouchEnd={kill}>
|
|
|
|
Kill
|
2022-04-17 23:40:37 +02:00
|
|
|
</Button>
|
2022-04-23 22:48:48 +02:00
|
|
|
)}
|
|
|
|
<Button className={classes.titleButton} onClick={minimize} onTouchEnd={minimize}>
|
|
|
|
{minimized ? "\u{1F5D6}" : "\u{1F5D5}"}
|
|
|
|
</Button>
|
|
|
|
<Button className={classes.titleButton} onClick={props.onClose} onTouchEnd={props.onClose}>
|
|
|
|
Close
|
|
|
|
</Button>
|
2021-10-05 07:23:20 +02:00
|
|
|
</Box>
|
2021-10-15 19:59:42 +02:00
|
|
|
</Paper>
|
2021-11-17 23:50:02 +01:00
|
|
|
<Paper sx={{ overflow: "scroll", overflowWrap: "break-word", whiteSpace: "pre-wrap" }}>
|
2021-10-15 19:59:42 +02:00
|
|
|
<ResizableBox
|
|
|
|
className={classes.logs}
|
|
|
|
height={500}
|
|
|
|
width={500}
|
|
|
|
handle={
|
|
|
|
<span style={{ position: "absolute", right: "-10px", bottom: "-13px", cursor: "nw-resize" }}>
|
|
|
|
<ArrowForwardIosIcon color="primary" style={{ transform: "rotate(45deg)" }} />
|
|
|
|
</span>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<Box>
|
2021-12-21 18:00:12 +01:00
|
|
|
{script.logs.map(
|
2021-10-15 19:59:42 +02:00
|
|
|
(line: string, i: number): JSX.Element => (
|
2021-11-19 21:44:12 +01:00
|
|
|
<Typography key={i} className={lineClass(line)}>
|
2021-10-15 19:59:42 +02:00
|
|
|
{line}
|
|
|
|
<br />
|
|
|
|
</Typography>
|
|
|
|
),
|
|
|
|
)}
|
|
|
|
</Box>
|
|
|
|
</ResizableBox>
|
|
|
|
</Paper>
|
|
|
|
</div>
|
2021-10-01 07:00:50 +02:00
|
|
|
</Paper>
|
2021-10-05 06:59:40 +02:00
|
|
|
</Draggable>
|
2021-10-01 07:00:50 +02:00
|
|
|
);
|
2022-03-06 05:34:04 +01:00
|
|
|
}
|