From aef362204d1c4fe468684b7fc7542bdb5fb01691 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Thu, 9 May 2024 16:19:30 +0700 Subject: [PATCH] MISC: Handle error when getting save data (#1241) --- src/Electron.tsx | 9 ++++++++- src/Netscript/ErrorMessages.ts | 13 +++++++++++++ src/SaveObject.ts | 17 +++++++++++++++-- src/ui/React/ImportSave/ImportSave.tsx | 12 +++++++++++- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/Electron.tsx b/src/Electron.tsx index 3e40babb9..5ea2a3a9f 100644 --- a/src/Electron.tsx +++ b/src/Electron.tsx @@ -12,6 +12,7 @@ import { CONSTANTS } from "./Constants"; import { hash } from "./hash/hash"; import { resolveFilePath } from "./Paths/FilePath"; import { hasScriptExtension } from "./Paths/ScriptFilePath"; +import { handleGetSaveDataError } from "./Netscript/ErrorMessages"; interface IReturnWebStatus extends IReturnStatus { data?: Record; @@ -159,7 +160,13 @@ function initElectronBridge(): void { if (!bridge) return; bridge.receive("get-save-data-request", async () => { - const saveData = await window.appSaveFns.getSaveData(); + let saveData; + try { + saveData = await window.appSaveFns.getSaveData(); + } catch (error) { + handleGetSaveDataError(error); + return; + } bridge.send("get-save-data-response", saveData); }); bridge.receive("get-save-info-request", async (saveData: unknown) => { diff --git a/src/Netscript/ErrorMessages.ts b/src/Netscript/ErrorMessages.ts index adf151b8a..35bad6b54 100644 --- a/src/Netscript/ErrorMessages.ts +++ b/src/Netscript/ErrorMessages.ts @@ -105,3 +105,16 @@ export function handleUnknownError(e: unknown, ws: WorkerScript | ScriptDeath | } dialogBoxCreate(initialText + e); } + +/** Use this handler to handle the error when we call getSaveData function */ +export function handleGetSaveDataError(error: unknown) { + console.error(error); + let errorMessage = `Cannot get save data. Error: ${error}.`; + if (error instanceof RangeError) { + errorMessage += " This may be because the save data is too large."; + } + if (error instanceof Error && error.stack) { + errorMessage += `\nStack:\n${error.stack}`; + } + dialogBoxCreate(errorMessage); +} diff --git a/src/SaveObject.ts b/src/SaveObject.ts index 732f027c4..5f23c5a52 100644 --- a/src/SaveObject.ts +++ b/src/SaveObject.ts @@ -42,6 +42,7 @@ import { SaveData } from "./types"; import { SaveDataError, canUseBinaryFormat, decodeSaveData, encodeJsonSaveString } from "./utils/SaveDataUtils"; import { isBinaryFormat } from "../electron/saveDataBinaryFormat"; import { downloadContentAsFile } from "./utils/FileUtils"; +import { handleGetSaveDataError } from "./Netscript/ErrorMessages"; /* SaveObject.js * Defines the object used to save/load games @@ -123,7 +124,13 @@ class BitburnerSaveObject { async saveGame(emitToastEvent = true): Promise { const savedOn = new Date().getTime(); Player.lastSave = savedOn; - const saveData = await this.getSaveData(); + let saveData; + try { + saveData = await this.getSaveData(); + } catch (error) { + handleGetSaveDataError(error); + return; + } try { await save(saveData); } catch (error) { @@ -157,7 +164,13 @@ class BitburnerSaveObject { } async exportGame(): Promise { - const saveData = await this.getSaveData(); + let saveData; + try { + saveData = await this.getSaveData(); + } catch (error) { + handleGetSaveDataError(error); + return; + } const filename = this.getSaveFileName(); downloadContentAsFile(saveData, filename); } diff --git a/src/ui/React/ImportSave/ImportSave.tsx b/src/ui/React/ImportSave/ImportSave.tsx index 38ea599dd..640fb13e8 100644 --- a/src/ui/React/ImportSave/ImportSave.tsx +++ b/src/ui/React/ImportSave/ImportSave.tsx @@ -39,6 +39,7 @@ import { useBoolean } from "../hooks"; import { ComparisonIcon } from "./ComparisonIcon"; import { SaveData } from "../../../types"; +import { handleGetSaveDataError } from "../../../Netscript/ErrorMessages"; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -131,7 +132,16 @@ export const ImportSave = (props: { saveData: SaveData; automatic: boolean }): J return Promise.resolve(); } - if (props.saveData) fetchData(); + if (props.saveData) { + fetchData().catch((error) => { + handleGoBack(); + // We cannot show dialog box in this screen (due to "withPopups = false"), so we will try showing it with a + // delay. 1 second is usually enough to go back to other normal screens that allow showing popups. + setTimeout(() => { + handleGetSaveDataError(error); + }, 1000); + }); + } }, [props.saveData]); if (!importData || !currentData) return <>;