BUGFIX: Multiple problems with Job tab (#1976)

This commit is contained in:
catloversg
2025-03-01 03:52:08 +07:00
committed by GitHub
parent f54f7b932c
commit 91b68db1fe
8 changed files with 92 additions and 69 deletions

View File

@@ -30,64 +30,83 @@ import { Page } from "../../ui/Router";
import { serverMetadata } from "../../Server/data/servers";
import { Tooltip } from "@mui/material";
import { getEnumHelper } from "../../utils/EnumHelper";
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
interface IProps {
loc: Location;
location: Location;
showBackButton: boolean;
}
export function GenericLocation({ loc, showBackButton }: IProps): React.ReactElement {
/**
* Determine what needs to be rendered for this location based on the locations
* type. Returns an array of React components that should be rendered
*/
function getLocationSpecificContent(): React.ReactNode[] {
const content: React.ReactNode[] = [];
/**
* Determine what needs to be rendered for this location based on the locations
* type. Returns an array of React components that should be rendered
*/
function getLocationSpecificContent(location: Location): React.ReactNode[] {
const content: React.ReactNode[] = [];
if (loc.types.includes(LocationType.Company)) {
if (!getEnumHelper("CompanyName").isMember(loc.name)) {
throw new Error(`Location name ${loc.name} is for a company but is not a company name.`);
}
content.push(<CompanyLocation key="CompanyLocation" companyName={loc.name} />);
if (location.types.includes(LocationType.Company)) {
if (!getEnumHelper("CompanyName").isMember(location.name)) {
throw new Error(`Location name ${location.name} is for a company but is not a company name.`);
}
if (loc.types.includes(LocationType.Gym)) {
content.push(<GymLocation key="GymLocation" loc={loc} />);
}
if (loc.types.includes(LocationType.Hospital)) {
content.push(<HospitalLocation key="HospitalLocation" />);
}
if (loc.types.includes(LocationType.Slums)) {
content.push(<SlumsLocation key="SlumsLocation" />);
}
if (loc.types.includes(LocationType.Special)) {
content.push(<SpecialLocation key="SpecialLocation" loc={loc} />);
}
if (loc.types.includes(LocationType.TechVendor)) {
content.push(<TechVendorLocation key="TechVendorLocation" loc={loc} />);
}
if (loc.types.includes(LocationType.TravelAgency)) {
content.push(<TravelAgencyRoot key="TravelAgencyRoot" />);
}
if (loc.types.includes(LocationType.University)) {
content.push(<UniversityLocation key="UniversityLocation" loc={loc} />);
}
if (loc.types.includes(LocationType.Casino)) {
content.push(<CasinoLocation key="CasinoLocation" />);
}
return content;
content.push(<CompanyLocation key="CompanyLocation" companyName={location.name} />);
}
const locContent: React.ReactNode[] = getLocationSpecificContent();
const serverMeta = serverMetadata.find((s) => s.specialName === loc.name);
if (location.types.includes(LocationType.Gym)) {
content.push(<GymLocation key="GymLocation" loc={location} />);
}
if (location.types.includes(LocationType.Hospital)) {
content.push(<HospitalLocation key="HospitalLocation" />);
}
if (location.types.includes(LocationType.Slums)) {
content.push(<SlumsLocation key="SlumsLocation" />);
}
if (location.types.includes(LocationType.Special)) {
content.push(<SpecialLocation key="SpecialLocation" loc={location} />);
}
if (location.types.includes(LocationType.TechVendor)) {
content.push(<TechVendorLocation key="TechVendorLocation" loc={location} />);
}
if (location.types.includes(LocationType.TravelAgency)) {
content.push(<TravelAgencyRoot key="TravelAgencyRoot" />);
}
if (location.types.includes(LocationType.University)) {
content.push(<UniversityLocation key="UniversityLocation" loc={location} />);
}
if (location.types.includes(LocationType.Casino)) {
content.push(<CasinoLocation key="CasinoLocation" />);
}
return content;
}
export function GenericLocation({ location, showBackButton }: IProps): React.ReactElement {
/**
* location can be undefined if GenericLocation is used like this:
*
* <GenericLocation location={Locations["unknown"]} showBackButton={true} />
*
* We need to check it before using.
*/
if (location == null) {
exceptionAlert(new Error(`GenericLocation is used with invalid location.`), true);
/**
* Return to the Terminal tab. We put the call of Router.toPage() inside setTimeout to avoid updating GameRoot while
* rendering this component.
*/
setTimeout(() => {
Router.toPage(Page.Terminal);
}, 100);
return <></>;
}
const locationContent: React.ReactNode[] = getLocationSpecificContent(location);
const serverMeta = serverMetadata.find((s) => s.specialName === location.name);
const server = GetServer(serverMeta ? serverMeta.hostname : "");
const backdoorInstalled = server !== null && isBackdoorInstalled(server);
@@ -99,14 +118,14 @@ export function GenericLocation({ loc, showBackButton }: IProps): React.ReactEle
{backdoorInstalled && serverMeta ? (
<Tooltip title={`Backdoor installed on ${serverMeta.hostname}.`}>
<span>
<CorruptableText content={loc.name} spoiler={false} />
<CorruptableText content={location.name} spoiler={false} />
</span>
</Tooltip>
) : (
loc.name
location.name
)}
</Typography>
{locContent}
{locationContent}
</>
);
}

View File

@@ -1,11 +1,12 @@
import React from "react";
import { Box } from "@mui/material";
import { Box, Typography } from "@mui/material";
import { Player } from "@player";
import { getRecordKeys } from "../../Types/Record";
import { useCycleRerender } from "../../ui/React/hooks";
import { Locations } from "../Locations";
import { GenericLocation } from "./GenericLocation";
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
export function JobRoot(): React.ReactElement {
useCycleRerender();
@@ -13,14 +14,23 @@ export function JobRoot(): React.ReactElement {
const jobs = getRecordKeys(Player.jobs).map((companyName) => {
const location = Locations[companyName];
if (location == null) {
throw new Error(`Invalid company name: ${companyName}`);
exceptionAlert(new Error(`Player.jobs contains invalid data. companyName: ${companyName}.`), true);
return <></>;
}
return (
<Box key={companyName} sx={{ marginBottom: "20px" }}>
<GenericLocation loc={location} showBackButton={false} />;
<GenericLocation location={location} showBackButton={false} />;
</Box>
);
});
if (jobs.length === 0) {
return (
<Typography sx={{ height: "100%", display: "flex", justifyContent: "center", alignItems: "center" }}>
No jobs
</Typography>
);
}
return <Box sx={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, 28em)" }}>{jobs}</Box>;
}

View File

@@ -54,7 +54,6 @@ import { AugmentationName, CityName } from "@enums";
import { ProgramsSeen } from "../../Programs/ui/ProgramsRoot";
import { InvitationsSeen } from "../../Faction/ui/FactionsRoot";
import { commitHash } from "../../utils/helpers/commitHash";
import { Locations } from "../../Locations/Locations";
import { useCycleRerender } from "../../ui/React/hooks";
import { playerHasDiscoveredGo } from "../../Go/effects/effect";
import { knowAboutBitverse } from "../../BitNode/BitNodeUtils";
@@ -176,9 +175,7 @@ export function SidebarRoot(props: { page: Page }): React.ReactElement {
const clickPage = useCallback(
(page: Page) => {
if (page === Page.Job) {
Router.toPage(page, { location: Locations[Object.keys(Player.jobs)[0]] });
} else if (page == Page.ScriptEditor || page == Page.Documentation) {
if (page == Page.ScriptEditor || page == Page.Documentation) {
Router.toPage(page, {});
} else if (isSimplePage(page)) {
Router.toPage(page);
@@ -221,7 +218,7 @@ export function SidebarRoot(props: { page: Page }): React.ReactElement {
return canOpenSleeves;
case SimplePage.Grafting:
return canOpenGrafting;
case ComplexPage.Job:
case SimplePage.Job:
return canJob;
case SimplePage.StockMarket:
return canStockMarket;

View File

@@ -31,6 +31,7 @@ export enum SimplePage {
StockMarket = "Stock Market",
Terminal = "Terminal",
Travel = "Travel",
Job = "Job",
Work = "Work",
BladeburnerCinematic = "Bladeburner Cinematic",
Loading = "Loading",
@@ -43,7 +44,6 @@ export enum SimplePage {
export enum ComplexPage {
BitVerse = "BitVerse",
Infiltration = "Infiltration",
Job = "Job",
Faction = "Faction",
FactionAugmentations = "Faction Augmentations",
ScriptEditor = "Script Editor",

View File

@@ -337,7 +337,7 @@ export function GameRoot(): React.ReactElement {
mainPage = <JobRoot />;
break;
case Page.Location: {
mainPage = <GenericLocation loc={pageWithContext.location} showBackButton={true} />;
mainPage = <GenericLocation location={pageWithContext.location} showBackButton={true} />;
break;
}
case Page.Options: {

View File

@@ -14,8 +14,6 @@ export type PageContext<T extends Page> = T extends ComplexPage.BitVerse
? { flume: boolean; quick: boolean }
: T extends ComplexPage.Infiltration
? { location: Location }
: T extends ComplexPage.Job
? { location: Location }
: T extends ComplexPage.Faction
? { faction: Faction }
: T extends ComplexPage.FactionAugmentations
@@ -33,7 +31,6 @@ export type PageContext<T extends Page> = T extends ComplexPage.BitVerse
export type PageWithContext =
| ({ page: ComplexPage.BitVerse } & PageContext<ComplexPage.BitVerse>)
| ({ page: ComplexPage.Infiltration } & PageContext<ComplexPage.Infiltration>)
| ({ page: ComplexPage.Job } & PageContext<ComplexPage.Job>)
| ({ page: ComplexPage.Faction } & PageContext<ComplexPage.Faction>)
| ({ page: ComplexPage.FactionAugmentations } & PageContext<ComplexPage.FactionAugmentations>)
| ({ page: ComplexPage.ScriptEditor } & PageContext<ComplexPage.ScriptEditor>)

View File

@@ -428,11 +428,11 @@ export function WorkInProgressRoot(): React.ReactElement {
buttons: {
cancel: () => {
Player.finishWork(true);
Router.toPage(Page.Job, { location: Locations[comp.name] });
Router.toPage(Page.Job);
},
unfocus: () => {
Player.stopFocusing();
Router.toPage(Page.Job, { location: Locations[comp.name] });
Router.toPage(Page.Job);
},
},
title: (

View File

@@ -28,7 +28,7 @@ export const GoToPageKeyBindingTypes = [
SimplePage.Hacknet,
SimplePage.City,
SimplePage.Travel,
ComplexPage.Job,
SimplePage.Job,
SimplePage.StockMarket,
SimplePage.Go,
SimplePage.Milestones,
@@ -165,7 +165,7 @@ export const DefaultKeyBindings: Record<KeyBindingType, [KeyCombination | null,
},
null,
],
[ComplexPage.Job]: [
[SimplePage.Job]: [
{
control: false,
alt: true,