bitburner-src/src/ui/React/PromptManager.tsx

156 lines
4.0 KiB
TypeScript
Raw Normal View History

2022-03-17 21:44:44 +01:00
import React, { useState, useEffect } from "react";
2021-10-02 04:53:23 +02:00
import { EventEmitter } from "../../utils/EventEmitter";
2022-03-06 05:05:55 +01:00
import { Modal } from "./Modal";
2021-10-02 04:53:23 +02:00
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import Select, { SelectChangeEvent } from "@mui/material/Select";
2022-03-17 21:44:44 +01:00
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
2022-03-18 11:15:51 +01:00
import { KEY } from "../../utils/helpers/keyCodes";
2021-10-02 04:53:23 +02:00
export const PromptEvent = new EventEmitter<[Prompt]>();
interface Prompt {
txt: string;
2022-03-17 21:44:44 +01:00
options?: { type?: string; choices?: string[] };
resolve: (result: boolean | string) => void;
2021-10-02 04:53:23 +02:00
}
export function PromptManager(): React.ReactElement {
const [prompt, setPrompt] = useState<Prompt | null>(null);
2022-03-17 21:44:44 +01:00
useEffect(() => {
return PromptEvent.subscribe((p: Prompt) => {
setPrompt(p);
});
}, []);
if (prompt === null) {
return <></>;
}
2022-01-30 15:21:46 +01:00
2021-10-02 04:53:23 +02:00
function close(): void {
if (prompt === null) return;
2022-03-17 21:44:44 +01:00
if (["text", "select"].includes(prompt?.options?.type ?? "")) {
prompt.resolve("");
} else {
prompt.resolve(false);
}
2021-10-02 04:53:23 +02:00
setPrompt(null);
}
2022-03-17 21:44:44 +01:00
const types: { [key: string]: any } = {
text: PromptMenuText,
select: PromptMenuSelect,
};
2022-03-17 21:44:44 +01:00
let PromptContent = PromptMenuBoolean;
2022-03-17 23:17:19 +01:00
if (prompt?.options?.type && ["text", "select"].includes(prompt?.options?.type))
PromptContent = types[prompt?.options?.type];
2022-03-17 21:44:44 +01:00
const resolve = (value: boolean | string): void => {
prompt.resolve(value);
setPrompt(null);
};
2021-10-02 04:53:23 +02:00
return (
2022-03-17 21:44:44 +01:00
<Modal open={true} onClose={close}>
<pre>
<Typography>{prompt.txt}</Typography>
</pre>
2022-03-17 21:44:44 +01:00
<PromptContent prompt={prompt} resolve={resolve} />
</Modal>
2021-10-02 04:53:23 +02:00
);
}
2022-03-17 21:44:44 +01:00
interface IContentProps {
prompt: Prompt;
resolve: (value: boolean | string) => void;
}
function PromptMenuBoolean({ resolve }: IContentProps): React.ReactElement {
const yes = (): void => resolve(true);
const no = (): void => resolve(false);
return (
<>
2022-03-17 21:44:44 +01:00
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", paddingTop: "10px" }}>
<Button style={{ marginRight: "auto" }} onClick={yes}>
Yes
</Button>
<Button onClick={no}>No</Button>
</div>
</>
);
}
2022-03-17 21:44:44 +01:00
function PromptMenuText({ resolve }: IContentProps): React.ReactElement {
const [value, setValue] = useState("");
2022-03-17 21:44:44 +01:00
const submit = (): void => resolve(value);
const onInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
setValue(event.target.value);
2022-03-17 21:44:44 +01:00
};
const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>): void => {
event.stopPropagation();
2022-03-18 11:15:51 +01:00
if (event.key === KEY.ENTER) {
event.preventDefault();
submit();
}
2022-03-17 21:44:44 +01:00
};
return (
<>
2022-03-17 21:44:44 +01:00
<div style={{ display: "flex", alignItems: "center", paddingTop: "10px" }}>
<TextField
autoFocus
value={value}
onInput={onInput}
onKeyDown={onKeyDown}
2022-03-17 21:44:44 +01:00
style={{ flex: "1 0 auto" }}
InputProps={{
2022-03-17 21:44:44 +01:00
endAdornment: <Button onClick={submit}>Confirm</Button>,
}}
/>
</div>
</>
);
}
2022-03-17 21:44:44 +01:00
function PromptMenuSelect({ prompt, resolve }: IContentProps): React.ReactElement {
const [value, setValue] = useState("");
2022-03-17 21:44:44 +01:00
const submit = (): void => resolve(value);
const onChange = (event: SelectChangeEvent<string>): void => {
setValue(event.target.value);
2022-03-17 21:44:44 +01:00
};
2022-03-17 21:44:44 +01:00
const getItems = (choices: string[]): React.ReactElement[] => {
const content = [];
2022-03-17 21:44:44 +01:00
for (const i of choices) {
// @ts-ignore
2022-03-17 21:44:44 +01:00
content.push(
<MenuItem key={i} value={i}>
{i}
</MenuItem>,
);
}
return content;
2022-03-17 21:44:44 +01:00
};
return (
<>
2022-03-17 21:44:44 +01:00
<div style={{ display: "flex", alignItems: "center", paddingTop: "10px" }}>
<Select onChange={onChange} value={value} style={{ flex: "1 0 auto" }}>
2022-01-31 19:15:13 +01:00
{getItems(prompt?.options?.choices || [])}
</Select>
2022-03-17 21:44:44 +01:00
<Button onClick={submit} disabled={value === ""}>
Confirm
</Button>
</div>
</>
);
}