diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx index fcca21c98..5dc290211 100644 --- a/src/ui/GameRoot.tsx +++ b/src/ui/GameRoot.tsx @@ -84,6 +84,9 @@ import { ThemeBrowser } from "../Themes/ui/ThemeBrowser"; import { ImportSaveRoot } from "./React/ImportSaveRoot"; import { BypassWrapper } from "./React/BypassWrapper"; +import _wrap from "lodash/wrap"; +import _functions from "lodash/functions"; + const htmlLocation = location; interface IProps { @@ -111,6 +114,9 @@ export let Router: IRouter = { page: () => { throw new Error("Router called before initialization"); }, + allowRouting: () => { + throw new Error("Router called before initialization"); + }, toActiveScripts: () => { throw new Error("Router called before initialization"); }, @@ -238,6 +244,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme if (importString === undefined && page === Page.ImportSave) throw new Error("Trying to go to a page without the proper setup"); + const [allowRoutingCalls, setAllowRoutingCalls] = useState(true); + function resetErrorBoundary(): void { setErrorBoundaryKey(errorBoundaryKey + 1); } @@ -259,6 +267,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme Router = { page: () => page, + allowRouting: (value: boolean) => setAllowRoutingCalls(value), toActiveScripts: () => setPage(Page.ActiveScripts), toAugmentations: () => setPage(Page.Augmentations), toBladeburner: () => setPage(Page.Bladeburner), @@ -333,6 +342,26 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme }, }; + + useEffect(() => { + // Wrap Router navigate functions to be able to disable the execution + _functions(Router). + filter((fnName) => fnName.startsWith('to')). + forEach((fnName) => { + // @ts-ignore - tslint does not like this, couldn't find a way to make it cooperate + Router[fnName] = _wrap(Router[fnName], (func, ...args) => { + if (!allowRoutingCalls) { + // Let's just log to console. + console.log(`Routing is currently disabled - Attempted router.${fnName}()`); + return; + } + + // Call the function normally + return func(...args); + }); + }); + }); + useEffect(() => { if (page !== Page.Terminal) window.scrollTo(0, 0); }); @@ -539,7 +568,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme Router.toTerminal()} + router={Router} /> ); withSidebar = false; diff --git a/src/ui/React/ImportSaveRoot.tsx b/src/ui/React/ImportSaveRoot.tsx index edf4cfeb7..64ca82a6c 100644 --- a/src/ui/React/ImportSaveRoot.tsx +++ b/src/ui/React/ImportSaveRoot.tsx @@ -31,6 +31,7 @@ import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFuncti import { numeralWrapper } from "../numeralFormat"; import { ConfirmationModal } from "./ConfirmationModal"; import { pushImportResult } from "../../Electron"; +import { IRouter } from "../Router"; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -101,28 +102,30 @@ function ComparisonIcon({ isBetter }: { isBetter: boolean }): JSX.Element { } } -export interface ImportSaveProps { +export interface IProps { importString: string; automatic: boolean; - onReturning: () => void; + router: IRouter; } let initialAutosave = 0; -export function ImportSaveRoot({ importString, automatic, onReturning }: ImportSaveProps): JSX.Element { +export function ImportSaveRoot(props: IProps): JSX.Element { const classes = useStyles(); const [importData, setImportData] = useState(); const [currentData, setCurrentData] = useState(); const [importModalOpen, setImportModalOpen] = useState(false); + const [headback, setHeadback] = useState(false); function handleGoBack(): void { Settings.AutosaveInterval = initialAutosave; pushImportResult(false); - onReturning(); + props.router.allowRouting(true); + setHeadback(true) } async function handleImport(): Promise { - await saveObject.importGame(importString, true); + await saveObject.importGame(props.importString, true); pushImportResult(true); } @@ -130,11 +133,16 @@ export function ImportSaveRoot({ importString, automatic, onReturning }: ImportS // We want to disable autosave while we're in this mode initialAutosave = Settings.AutosaveInterval; Settings.AutosaveInterval = 0; + props.router.allowRouting(false); }, []); + useEffect(() => { + if (headback) props.router.toTerminal(); + }, [headback]); + useEffect(() => { async function fetchData(): Promise { - const dataBeingImported = await saveObject.getImportDataFromString(importString); + const dataBeingImported = await saveObject.getImportDataFromString(props.importString); const dataCurrentlyInGame = await saveObject.getImportDataFromString(saveObject.getSaveString(true)); setImportData(dataBeingImported); @@ -142,8 +150,8 @@ export function ImportSaveRoot({ importString, automatic, onReturning }: ImportS return Promise.resolve(); } - if (importString) fetchData(); - }, [importString]); + if (props.importString) fetchData(); + }, [props.importString]); if (!importData || !currentData) return <>; return ( @@ -151,7 +159,7 @@ export function ImportSaveRoot({ importString, automatic, onReturning }: ImportS Import Save Comparison - {automatic && ( + {props.automatic && ( We've found a NEWER save that you may want to use instead. @@ -202,8 +210,14 @@ export function ImportSaveRoot({ importString, automatic, onReturning }: ImportS Saved On - {new Date(currentData.playerData?.lastSave ?? 0).toLocaleString()} - {new Date(importData.playerData?.lastSave ?? 0).toLocaleString()} + + {(currentData.playerData?.lastSave ?? 0) > 0 ? + new Date(currentData.playerData?.lastSave ?? 0).toLocaleString() : 'n/a'} + + + {(importData.playerData?.lastSave ?? 0) > 0 ? + new Date(importData.playerData?.lastSave ?? 0).toLocaleString() : 'n/a'} + {importData.playerData?.lastSave !== currentData.playerData?.lastSave && (