mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-27 00:17:32 +01:00
logbox manager, alert manager and fix bitverse colors
This commit is contained in:
parent
62cd8ffcc6
commit
97c04a1037
@ -51,7 +51,6 @@ interface IPortalProps {
|
||||
function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||
const [portalOpen, setPortalOpen] = useState(false);
|
||||
const classes = useStyles();
|
||||
const router = use.Router();
|
||||
const bitNode = BitNodes[`BitNode${props.n}`];
|
||||
if (bitNode == null) {
|
||||
return <>O</>;
|
||||
@ -63,9 +62,12 @@ function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||
cssClass = classes.level2;
|
||||
} else if (props.level === 1) {
|
||||
cssClass = classes.level1;
|
||||
} else {
|
||||
} else if (props.level === 3) {
|
||||
cssClass = classes.level3;
|
||||
}
|
||||
if (props.level === 2) {
|
||||
cssClass = classes.level2;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -17,7 +17,7 @@ export function determineCrimeSuccess(p: IPlayer, type: string): boolean {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
dialogBoxCreate(`ERR: Unrecognized crime type: ${type} This is probably a bug please contact the developer`, false);
|
||||
dialogBoxCreate(`ERR: Unrecognized crime type: ${type} This is probably a bug please contact the developer`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ export class HacknetNode implements IHacknetNode {
|
||||
this.moneyGainRatePerSecond = calculateMoneyGainRate(this.level, this.ram, this.cores, prodMult);
|
||||
if (isNaN(this.moneyGainRatePerSecond)) {
|
||||
this.moneyGainRatePerSecond = 0;
|
||||
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer", false);
|
||||
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import Button from "@mui/material/Button";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { getHospitalizationCost } from "../../Hospital/Hospital";
|
||||
|
||||
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
|
@ -58,7 +58,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
|
||||
player.sleeves.push(new Sleeve(player));
|
||||
rerender();
|
||||
} else {
|
||||
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`, false);
|
||||
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ export function getPurchaseServerMaxRam(): number {
|
||||
export function purchaseServer(hostname: string, ram: number, cost: number, p: IPlayer): void {
|
||||
//Check if player has enough money
|
||||
if (!p.canAfford(cost)) {
|
||||
dialogBoxCreate("You don't have enough money to purchase this server!", false);
|
||||
dialogBoxCreate("You don't have enough money to purchase this server!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,11 +104,11 @@ export function StockTickerPositionText(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography>Max Shares: {numeralWrapper.formatShares(stock.maxShares)}</Typography>
|
||||
<Typography className={"tooltip"}>
|
||||
<Typography>
|
||||
Ask Price: <Money money={stock.getAskPrice()} />
|
||||
</Typography>
|
||||
<br />
|
||||
<Typography className={"tooltip"}>
|
||||
<Typography>
|
||||
Bid Price: <Money money={stock.getBidPrice()} />
|
||||
</Typography>
|
||||
<LongPosition {...props} />
|
||||
|
@ -65,7 +65,7 @@ export class TextFile {
|
||||
* Shows the content to the user via the game's dialog box.
|
||||
*/
|
||||
show(): void {
|
||||
dialogBoxCreate(`${this.fn}<br /><br />${this.text}`, true);
|
||||
dialogBoxCreate(`${this.fn}<br /><br />${this.text}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,46 +0,0 @@
|
||||
/**
|
||||
* Basic stateless button that uses the 'accordion-button' css class.
|
||||
* This class has a black background so that it does not clash with the default
|
||||
* accordion coloring
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
interface IProps {
|
||||
addClasses?: string;
|
||||
disabled?: boolean;
|
||||
id?: string;
|
||||
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
|
||||
style?: any;
|
||||
text: string;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
type IInnerHTMLMarkup = {
|
||||
__html: string;
|
||||
};
|
||||
|
||||
export function AccordionButton(props: IProps): React.ReactElement {
|
||||
const hasTooltip = props.tooltip != null && props.tooltip !== "";
|
||||
|
||||
// TODO Add a disabled class for accordion buttons?
|
||||
let className = "accordion-button";
|
||||
if (hasTooltip) {
|
||||
className += " tooltip";
|
||||
}
|
||||
|
||||
if (typeof props.addClasses === "string") {
|
||||
className += ` ${props.addClasses}`;
|
||||
}
|
||||
|
||||
// Tooltip will be set using inner HTML
|
||||
const tooltipMarkup: IInnerHTMLMarkup = {
|
||||
__html: props.tooltip ? props.tooltip : "",
|
||||
};
|
||||
|
||||
return (
|
||||
<button className={className} id={props.id} onClick={props.onClick} style={props.style}>
|
||||
{props.text}
|
||||
{hasTooltip && <span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup}></span>}
|
||||
</button>
|
||||
);
|
||||
}
|
@ -32,9 +32,8 @@ export function AlertManager(): React.ReactElement {
|
||||
);
|
||||
|
||||
function close(): void {
|
||||
console.log("close");
|
||||
setAlerts((old) => {
|
||||
return old.slice(0, -1);
|
||||
return old.slice(1, 1e99);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,67 +0,0 @@
|
||||
/**
|
||||
* Basic paragraph (p Element) that automatically re-renders itself every X seconds
|
||||
*
|
||||
* NOT recommended for usage - only if you really have to
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
interface IProps {
|
||||
intervalTime?: number;
|
||||
style?: any;
|
||||
getContent: () => JSX.Element;
|
||||
getTooltip?: () => JSX.Element;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
i: number;
|
||||
}
|
||||
|
||||
export class AutoupdatingParagraph extends React.Component<IProps, IState> {
|
||||
/**
|
||||
* Timer ID for auto-updating implementation (returned value from setInterval())
|
||||
*/
|
||||
interval = 0;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
i: 0,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
const time = this.props.intervalTime ? this.props.intervalTime : 1000;
|
||||
this.interval = window.setInterval(() => this.tick(), time);
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
tick(): void {
|
||||
this.setState((prevState) => ({
|
||||
i: prevState.i + 1,
|
||||
}));
|
||||
}
|
||||
|
||||
hasTooltip(): boolean {
|
||||
if (this.props.getTooltip != null) {
|
||||
return !!this.props.getTooltip();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
tooltip(): JSX.Element {
|
||||
if (!this.props.getTooltip) return <></>;
|
||||
return this.props.getTooltip();
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<div className="tooltip" style={this.props.style}>
|
||||
<p>{this.props.getContent()}</p>
|
||||
{this.hasTooltip() && <span className={"tooltiptext"}>{this.tooltip()}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Basic stateless button that automatically re-renders itself every X seconds
|
||||
* Uses the 'std-button' css class
|
||||
*
|
||||
* NOT recommended for usage - only if you really have to
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
interface IProps {
|
||||
label?: string;
|
||||
disabled?: boolean;
|
||||
intervalTime?: number;
|
||||
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
|
||||
style?: any;
|
||||
text: string | JSX.Element;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
i: number;
|
||||
}
|
||||
|
||||
type IInnerHTMLMarkup = {
|
||||
__html: string;
|
||||
};
|
||||
|
||||
export class AutoupdatingStdButton extends React.Component<IProps, IState> {
|
||||
/**
|
||||
* Timer ID for auto-updating implementation (returned value from setInterval())
|
||||
*/
|
||||
interval = 0;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
i: 0,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
const time = this.props.intervalTime ? this.props.intervalTime : 1000;
|
||||
this.interval = window.setInterval(() => this.tick(), time);
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
tick(): void {
|
||||
this.setState((prevState) => ({
|
||||
i: prevState.i + 1,
|
||||
}));
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const hasTooltip = this.props.tooltip != null && this.props.tooltip !== "";
|
||||
|
||||
let className = this.props.disabled ? "std-button-disabled" : "std-button";
|
||||
if (hasTooltip) {
|
||||
className += " tooltip";
|
||||
}
|
||||
|
||||
// Tooltip will eb set using inner HTML
|
||||
const tooltipMarkup: IInnerHTMLMarkup = {
|
||||
__html: this.props.tooltip ? this.props.tooltip : "",
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label={this.props.label || ""}
|
||||
className={className}
|
||||
onClick={this.props.onClick}
|
||||
style={this.props.style}
|
||||
>
|
||||
{this.props.text}
|
||||
{hasTooltip && <span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup}></span>}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,43 +1,12 @@
|
||||
import { createPopup } from "./createPopup";
|
||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||
import { AlertEvents } from "./AlertManager";
|
||||
|
||||
import React from "react";
|
||||
import { jsx } from "@emotion/react";
|
||||
|
||||
interface IProps {
|
||||
content: JSX.Element;
|
||||
}
|
||||
|
||||
function MessagePopup(props: IProps): React.ReactElement {
|
||||
return <>{props.content}</>;
|
||||
}
|
||||
|
||||
export function dialogBoxCreate(txt: string | JSX.Element, preformatted = false): void {
|
||||
const popupId =
|
||||
`popup-` +
|
||||
Array.from(Array(16))
|
||||
.map(() => `${getRandomInt(0, 9)}`)
|
||||
.join("");
|
||||
if (typeof txt === "string") {
|
||||
if (preformatted) {
|
||||
// For text files as they are often computed data that
|
||||
// shouldn't be wrapped and should retain tabstops.
|
||||
createPopup(popupId, MessagePopup, {
|
||||
content: <pre dangerouslySetInnerHTML={{ __html: txt }} />,
|
||||
});
|
||||
} else {
|
||||
createPopup(popupId, MessagePopup, {
|
||||
content: (
|
||||
<p
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: txt.replace(/(?:\r\n|\r|\n)/g, "<br />"),
|
||||
}}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
export function dialogBoxCreate(txt: string | JSX.Element): void {
|
||||
if (typeof txt !== "string") {
|
||||
AlertEvents.emit(txt);
|
||||
} else {
|
||||
createPopup(popupId, MessagePopup, {
|
||||
content: txt,
|
||||
});
|
||||
AlertEvents.emit(<pre dangerouslySetInnerHTML={{ __html: txt }} />);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Text (p Element) with Tooltip
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
export interface IParagraphWithTooltipProps {
|
||||
style?: any;
|
||||
content: JSX.Element;
|
||||
tooltip: string | React.ReactElement | JSX.Element;
|
||||
}
|
||||
|
||||
export class ParagraphWithTooltip extends React.Component<IParagraphWithTooltipProps, any> {
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<div className={"tooltip"} style={this.props.style}>
|
||||
<p>{this.props.content}</p>
|
||||
<span className={"tooltiptext"}>{this.props.tooltip}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/**
|
||||
* Basic button for popup dialog boxes
|
||||
* It creates an event handler such that pressing Esc will perform the click handler.
|
||||
*
|
||||
* Should only be used in other React components, otherwise it may not be properly
|
||||
* unmounted
|
||||
*/
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
|
||||
import { KEY } from "../../utils/helpers/keyCodes";
|
||||
import { removeElement } from "../uiHelpers/removeElement";
|
||||
|
||||
export interface IPopupButtonProps {
|
||||
class?: string;
|
||||
popup: HTMLElement | string;
|
||||
style?: any;
|
||||
text: string;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export class PopupButton extends React.Component<IPopupButtonProps, any> {
|
||||
constructor(props: IPopupButtonProps) {
|
||||
super(props);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.keyListener = this.keyListener.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
document.addEventListener("keydown", this.keyListener);
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
document.removeEventListener("keydown", this.keyListener);
|
||||
}
|
||||
|
||||
handleClick(): void {
|
||||
if (this.props.onClose) this.props.onClose();
|
||||
//We might be able to remove this?
|
||||
//Clickhandler from the props will override this anyhow.
|
||||
let popup: HTMLElement | null;
|
||||
if (typeof this.props.popup === "string") {
|
||||
popup = document.getElementById(this.props.popup);
|
||||
} else {
|
||||
popup = this.props.popup;
|
||||
}
|
||||
// TODO Check if this is okay? This is essentially calling to unmount a parent component
|
||||
if (popup instanceof HTMLElement) {
|
||||
ReactDOM.unmountComponentAtNode(popup); // Removes everything inside the wrapper container
|
||||
removeElement(popup); // Removes the wrapper container
|
||||
}
|
||||
}
|
||||
|
||||
keyListener(e: KeyboardEvent): void {
|
||||
//This doesn't really make sense, a button doesnt have to listen to escape IMO
|
||||
//Too affraid to remove it since im not sure what it will break.. But yuck..
|
||||
if (e.keyCode === KEY.ESC) {
|
||||
this.handleClick();
|
||||
}
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const className = this.props.class ? this.props.class : "std-button";
|
||||
|
||||
return (
|
||||
<button className={className} onClick={this.handleClick} style={this.props.style}>
|
||||
{this.props.text}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Close button for popup dialog boxes
|
||||
* It creates an event handler such that pressing Esc will close the binded popup
|
||||
*
|
||||
* Should only be used in other React components, otherwise it may not be properly
|
||||
* unmounted
|
||||
*/
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
|
||||
import { removeElement } from "../uiHelpers/removeElement";
|
||||
import { IPopupButtonProps, PopupButton } from "./PopupButton";
|
||||
|
||||
export interface IPopupCloseButtonProps extends IPopupButtonProps {
|
||||
class?: string;
|
||||
popup: HTMLElement | string;
|
||||
style?: any;
|
||||
text: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export class PopupCloseButton extends PopupButton {
|
||||
constructor(props: IPopupCloseButtonProps) {
|
||||
super(props);
|
||||
|
||||
this.closePopup = this.closePopup.bind(this);
|
||||
}
|
||||
|
||||
closePopup(): void {
|
||||
if (this.props.onClose) this.props.onClose();
|
||||
let popup: HTMLElement | null;
|
||||
if (typeof this.props.popup === "string") {
|
||||
popup = document.getElementById(this.props.popup);
|
||||
} else {
|
||||
popup = this.props.popup;
|
||||
}
|
||||
|
||||
// TODO Check if this is okay? This is essentially calling to unmount a
|
||||
// parent component
|
||||
if (popup instanceof HTMLElement) {
|
||||
// Removes everything inside the wrapper container
|
||||
ReactDOM.unmountComponentAtNode(popup);
|
||||
removeElement(popup); // Removes the wrapper container
|
||||
}
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const className = this.props.class ? this.props.class : "std-button";
|
||||
|
||||
return (
|
||||
<button className={className} onClick={this.closePopup} style={this.props.style}>
|
||||
{this.props.text}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Stateless button that represents something that has been purchased.
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
interface IStdButtonPurchasedProps {
|
||||
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
|
||||
style?: any;
|
||||
text: string;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
type IInnerHTMLMarkup = {
|
||||
__html: string;
|
||||
};
|
||||
|
||||
export class StdButtonPurchased extends React.Component<IStdButtonPurchasedProps, any> {
|
||||
constructor(props: IStdButtonPurchasedProps) {
|
||||
super(props);
|
||||
this.hasTooltip = this.hasTooltip.bind(this);
|
||||
this.tooltip = this.tooltip.bind(this);
|
||||
}
|
||||
|
||||
hasTooltip(): boolean {
|
||||
return this.props.tooltip != null && this.props.tooltip !== "";
|
||||
}
|
||||
|
||||
tooltip(): string {
|
||||
if (!this.props.tooltip) return "";
|
||||
return this.props.tooltip;
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
let className = "std-button-bought";
|
||||
if (this.hasTooltip()) {
|
||||
className += " tooltip";
|
||||
}
|
||||
|
||||
// Tooltip will be set using inner HTML
|
||||
let tooltipMarkup: IInnerHTMLMarkup = {
|
||||
__html: "",
|
||||
};
|
||||
if (this.hasTooltip()) {
|
||||
tooltipMarkup = {
|
||||
__html: this.tooltip(),
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={className} onClick={this.props.onClick} style={this.props.style}>
|
||||
{this.props.text}
|
||||
{this.hasTooltip() && <span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup}></span>}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
@ -21,6 +21,5 @@ export function exceptionAlert(e: IError | string): void {
|
||||
"message as well as details about how to reproduce the bug.<br><br>" +
|
||||
"If you want to be safe, I suggest refreshing the game WITHOUT saving so that your " +
|
||||
"safe doesn't get corrupted",
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user