mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 07:33:48 +01:00
MISC: Remove file-saver (#1217)
Also refactor to dedup our own download code
This commit is contained in:
parent
216500ed32
commit
7b993f3550
6
package-lock.json
generated
6
package-lock.json
generated
@ -27,7 +27,6 @@
|
|||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"escodegen": "^2.1.0",
|
"escodegen": "^2.1.0",
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"material-ui-color": "^1.2.0",
|
"material-ui-color": "^1.2.0",
|
||||||
@ -8458,11 +8457,6 @@
|
|||||||
"node": "^10.12.0 || >=12.0.0"
|
"node": "^10.12.0 || >=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/file-saver": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
|
|
||||||
},
|
|
||||||
"node_modules/filename-reserved-regex": {
|
"node_modules/filename-reserved-regex": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"escodegen": "^2.1.0",
|
"escodegen": "^2.1.0",
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"material-ui-color": "^1.2.0",
|
"material-ui-color": "^1.2.0",
|
||||||
|
@ -7,7 +7,6 @@ export type ContentFilePath = ScriptFilePath | TextFilePath;
|
|||||||
export interface ContentFile {
|
export interface ContentFile {
|
||||||
filename: ContentFilePath;
|
filename: ContentFilePath;
|
||||||
content: string;
|
content: string;
|
||||||
download: () => void;
|
|
||||||
deleteFromServer: (server: BaseServer) => boolean;
|
deleteFromServer: (server: BaseServer) => boolean;
|
||||||
}
|
}
|
||||||
export type ContentFileMap = Map<ContentFilePath, ContentFile>;
|
export type ContentFileMap = Map<ContentFilePath, ContentFile>;
|
||||||
|
@ -41,6 +41,7 @@ import { getGoSave, loadGo } from "./Go/SaveLoad";
|
|||||||
import { SaveData } from "./types";
|
import { SaveData } from "./types";
|
||||||
import { SaveDataError, canUseBinaryFormat, decodeSaveData, encodeJsonSaveString } from "./utils/SaveDataUtils";
|
import { SaveDataError, canUseBinaryFormat, decodeSaveData, encodeJsonSaveString } from "./utils/SaveDataUtils";
|
||||||
import { isBinaryFormat } from "../electron/saveDataBinaryFormat";
|
import { isBinaryFormat } from "../electron/saveDataBinaryFormat";
|
||||||
|
import { downloadContentAsFile } from "./utils/FileUtils";
|
||||||
|
|
||||||
/* SaveObject.js
|
/* SaveObject.js
|
||||||
* Defines the object used to save/load games
|
* Defines the object used to save/load games
|
||||||
@ -158,7 +159,7 @@ class BitburnerSaveObject {
|
|||||||
async exportGame(): Promise<void> {
|
async exportGame(): Promise<void> {
|
||||||
const saveData = await this.getSaveData();
|
const saveData = await this.getSaveData();
|
||||||
const filename = this.getSaveFileName();
|
const filename = this.getSaveFileName();
|
||||||
download(filename, saveData);
|
downloadContentAsFile(saveData, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
async importGame(saveData: SaveData, reload = true): Promise<void> {
|
async importGame(saveData: SaveData, reload = true): Promise<void> {
|
||||||
@ -853,23 +854,8 @@ function createBetaUpdateText() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function download(filename: string, content: SaveData): void {
|
|
||||||
const file = new Blob([content], { type: "text/plain" });
|
|
||||||
|
|
||||||
const a = document.createElement("a"),
|
|
||||||
url = URL.createObjectURL(file);
|
|
||||||
a.href = url;
|
|
||||||
a.download = filename;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
setTimeout(function () {
|
|
||||||
document.body.removeChild(a);
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructorsForReviver.BitburnerSaveObject = BitburnerSaveObject;
|
constructorsForReviver.BitburnerSaveObject = BitburnerSaveObject;
|
||||||
|
|
||||||
export { saveObject, loadGame, download };
|
export { saveObject, loadGame };
|
||||||
|
|
||||||
const saveObject = new BitburnerSaveObject();
|
const saveObject = new BitburnerSaveObject();
|
||||||
|
@ -45,22 +45,6 @@ export class Script implements ContentFile {
|
|||||||
this.server = server; // hostname of server this script is on
|
this.server = server; // hostname of server this script is on
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Download the script as a file */
|
|
||||||
download(): void {
|
|
||||||
const filename = this.filename;
|
|
||||||
const file = new Blob([this.code], { type: "text/plain" });
|
|
||||||
const a = document.createElement("a"),
|
|
||||||
url = URL.createObjectURL(file);
|
|
||||||
a.href = url;
|
|
||||||
a.download = filename;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
setTimeout(function () {
|
|
||||||
document.body.removeChild(a);
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Invalidates the current script module and related data, e.g. when modifying the file. */
|
/** Invalidates the current script module and related data, e.g. when modifying the file. */
|
||||||
invalidateModule(): void {
|
invalidateModule(): void {
|
||||||
// Always clear ram usage
|
// Always clear ram usage
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Terminal } from "../../Terminal";
|
import { Terminal } from "../../Terminal";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import FileSaver from "file-saver";
|
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
import { root } from "../../Paths/Directory";
|
import { root } from "../../Paths/Directory";
|
||||||
import { hasScriptExtension } from "../../Paths/ScriptFilePath";
|
import { hasScriptExtension } from "../../Paths/ScriptFilePath";
|
||||||
import { hasTextExtension } from "../../Paths/TextFilePath";
|
import { hasTextExtension } from "../../Paths/TextFilePath";
|
||||||
import { getGlobbedFileMap } from "../../Paths/GlobbedFiles";
|
import { getGlobbedFileMap } from "../../Paths/GlobbedFiles";
|
||||||
|
import { downloadContentAsFile } from "../../utils/FileUtils";
|
||||||
|
|
||||||
// Basic globbing implementation only supporting * and ?. Can be broken out somewhere else later.
|
// Basic globbing implementation only supporting * and ?. Can be broken out somewhere else later.
|
||||||
export function exportScripts(pattern: string, server: BaseServer, currDir = root): void {
|
export function exportScripts(pattern: string, server: BaseServer, currDir = root): void {
|
||||||
@ -17,10 +17,10 @@ export function exportScripts(pattern: string, server: BaseServer, currDir = roo
|
|||||||
|
|
||||||
// Return an error if no files matched, rather than an empty zip folder
|
// Return an error if no files matched, rather than an empty zip folder
|
||||||
if (Object.keys(zip.files).length == 0) throw new Error(`No files match the pattern ${pattern}`);
|
if (Object.keys(zip.files).length == 0) throw new Error(`No files match the pattern ${pattern}`);
|
||||||
const zipFn = `bitburner${
|
const filename = `bitburner${
|
||||||
hasScriptExtension(pattern) ? "Scripts" : pattern.endsWith(".txt") ? "Texts" : "Files"
|
hasScriptExtension(pattern) ? "Scripts" : pattern.endsWith(".txt") ? "Texts" : "Files"
|
||||||
}.zip`;
|
}.zip`;
|
||||||
zip.generateAsync({ type: "blob" }).then((content: Blob) => FileSaver.saveAs(content, zipFn));
|
zip.generateAsync({ type: "blob" }).then((content: Blob) => downloadContentAsFile(content, filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function download(args: (string | number | boolean)[], server: BaseServer): void {
|
export function download(args: (string | number | boolean)[], server: BaseServer): void {
|
||||||
@ -45,5 +45,5 @@ export function download(args: (string | number | boolean)[], server: BaseServer
|
|||||||
}
|
}
|
||||||
const file = server.getContentFile(path);
|
const file = server.getContentFile(path);
|
||||||
if (!file) return Terminal.error(`File not found: ${path}`);
|
if (!file) return Terminal.error(`File not found: ${path}`);
|
||||||
return file.download();
|
return downloadContentAsFile(file.content, file.filename);
|
||||||
}
|
}
|
||||||
|
@ -24,21 +24,6 @@ export class TextFile implements ContentFile {
|
|||||||
this.text = txt;
|
this.text = txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Serves the file to the user as a downloadable resource through the browser. */
|
|
||||||
download(): void {
|
|
||||||
const file: Blob = new Blob([this.text], { type: "text/plain" });
|
|
||||||
const a: HTMLAnchorElement = document.createElement("a");
|
|
||||||
const url: string = URL.createObjectURL(file);
|
|
||||||
a.href = url;
|
|
||||||
a.download = this.filename;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
setTimeout(() => {
|
|
||||||
document.body.removeChild(a);
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Serialize the current file to a JSON save state. */
|
/** Serialize the current file to a JSON save state. */
|
||||||
toJSON(): IReviverValue {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("TextFile", this);
|
return Generic_toJSON("TextFile", this);
|
||||||
|
@ -5,7 +5,6 @@ import { Settings } from "../../Settings/Settings";
|
|||||||
import { load } from "../../db";
|
import { load } from "../../db";
|
||||||
import { Router } from "../GameRoot";
|
import { Router } from "../GameRoot";
|
||||||
import { Page } from "../Router";
|
import { Page } from "../Router";
|
||||||
import { download } from "../../SaveObject";
|
|
||||||
import { IErrorData, newIssueUrl } from "../../utils/ErrorHelper";
|
import { IErrorData, newIssueUrl } from "../../utils/ErrorHelper";
|
||||||
import { DeleteGameButton } from "./DeleteGameButton";
|
import { DeleteGameButton } from "./DeleteGameButton";
|
||||||
import { SoftResetButton } from "./SoftResetButton";
|
import { SoftResetButton } from "./SoftResetButton";
|
||||||
@ -14,6 +13,7 @@ import DirectionsRunIcon from "@mui/icons-material/DirectionsRun";
|
|||||||
import GitHubIcon from "@mui/icons-material/GitHub";
|
import GitHubIcon from "@mui/icons-material/GitHub";
|
||||||
import { isBinaryFormat } from "../../../electron/saveDataBinaryFormat";
|
import { isBinaryFormat } from "../../../electron/saveDataBinaryFormat";
|
||||||
import { InvalidSaveData, UnsupportedSaveData } from "../../utils/SaveDataUtils";
|
import { InvalidSaveData, UnsupportedSaveData } from "../../utils/SaveDataUtils";
|
||||||
|
import { downloadContentAsFile } from "../../utils/FileUtils";
|
||||||
|
|
||||||
export let RecoveryMode = false;
|
export let RecoveryMode = false;
|
||||||
let sourceError: unknown;
|
let sourceError: unknown;
|
||||||
@ -44,7 +44,7 @@ export function RecoveryRoot({ softReset, errorData, resetError }: IProps): Reac
|
|||||||
const epochTime = Math.round(Date.now() / 1000);
|
const epochTime = Math.round(Date.now() / 1000);
|
||||||
const extension = isBinaryFormat(content) ? "json.gz" : "json";
|
const extension = isBinaryFormat(content) ? "json.gz" : "json";
|
||||||
const filename = `RECOVERY_BITBURNER_${epochTime}.${extension}`;
|
const filename = `RECOVERY_BITBURNER_${epochTime}.${extension}`;
|
||||||
download(filename, content);
|
downloadContentAsFile(content, filename);
|
||||||
})
|
})
|
||||||
.catch((err) => console.error(err));
|
.catch((err) => console.error(err));
|
||||||
}, []);
|
}, []);
|
||||||
|
11
src/utils/FileUtils.ts
Normal file
11
src/utils/FileUtils.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export function downloadContentAsFile(content: BlobPart, filename: string): void {
|
||||||
|
const blob = new Blob([content]);
|
||||||
|
const anchorElement = document.createElement("a");
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
anchorElement.href = url;
|
||||||
|
anchorElement.download = filename;
|
||||||
|
anchorElement.click();
|
||||||
|
setTimeout(function () {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}, 0);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user