web: Remove jszip, use rust
This commit is contained in:
parent
eb26616886
commit
0ded7c61ea
|
@ -4662,6 +4662,7 @@ dependencies = [
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-streams",
|
"wasm-streams",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -59,6 +59,7 @@ gloo-net = { version = "0.5.0", default-features = false, features = ["websocke
|
||||||
rfd = { version = "0.14.1", features = ["file-handle-inner"] }
|
rfd = { version = "0.14.1", features = ["file-handle-inner"] }
|
||||||
wasm-streams = "0.4.0"
|
wasm-streams = "0.4.0"
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
|
zip = { version = "2.1.2", default-features = false, features = ["deflate"]}
|
||||||
|
|
||||||
[dependencies.ruffle_core]
|
[dependencies.ruffle_core]
|
||||||
path = "../core"
|
path = "../core"
|
||||||
|
|
|
@ -4376,7 +4376,8 @@
|
||||||
"node_modules/core-util-is": {
|
"node_modules/core-util-is": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/cosmiconfig": {
|
"node_modules/cosmiconfig": {
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
|
@ -7162,7 +7163,8 @@
|
||||||
"node_modules/immediate": {
|
"node_modules/immediate": {
|
||||||
"version": "3.0.6",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
|
@ -7231,7 +7233,8 @@
|
||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/ini": {
|
"node_modules/ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
|
@ -7532,7 +7535,8 @@
|
||||||
"node_modules/isarray": {
|
"node_modules/isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
@ -8062,6 +8066,7 @@
|
||||||
"version": "3.10.1",
|
"version": "3.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lie": "~3.3.0",
|
"lie": "~3.3.0",
|
||||||
"pako": "~1.0.2",
|
"pako": "~1.0.2",
|
||||||
|
@ -8073,6 +8078,7 @@
|
||||||
"version": "2.3.8",
|
"version": "2.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
|
@ -8086,12 +8092,14 @@
|
||||||
"node_modules/jszip/node_modules/safe-buffer": {
|
"node_modules/jszip/node_modules/safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/jszip/node_modules/string_decoder": {
|
"node_modules/jszip/node_modules/string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
@ -8222,6 +8230,7 @@
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"immediate": "~3.0.5"
|
"immediate": "~3.0.5"
|
||||||
}
|
}
|
||||||
|
@ -9503,7 +9512,8 @@
|
||||||
"node_modules/pako": {
|
"node_modules/pako": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
|
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -9919,7 +9929,8 @@
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/progress": {
|
"node_modules/progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
@ -11165,7 +11176,8 @@
|
||||||
"node_modules/setimmediate": {
|
"node_modules/setimmediate": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
|
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/setprototypeof": {
|
"node_modules/setprototypeof": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
|
@ -12500,7 +12512,8 @@
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/utils-merge": {
|
"node_modules/utils-merge": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -13581,7 +13594,6 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "(MIT OR Apache-2.0)",
|
"license": "(MIT OR Apache-2.0)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jszip": "^3.10.1",
|
|
||||||
"wasm-feature-detect": "^1.6.1"
|
"wasm-feature-detect": "^1.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
"checkTypes": "tsc --noemit"
|
"checkTypes": "tsc --noemit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jszip": "^3.10.1",
|
|
||||||
"wasm-feature-detect": "^1.6.1"
|
"wasm-feature-detect": "^1.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
signExtensions,
|
signExtensions,
|
||||||
referenceTypes,
|
referenceTypes,
|
||||||
} from "wasm-feature-detect";
|
} from "wasm-feature-detect";
|
||||||
import type { RuffleInstanceBuilder } from "../dist/ruffle_web";
|
import type { RuffleInstanceBuilder, ZipWriter } from "../dist/ruffle_web";
|
||||||
import { setPolyfillsOnLoad } from "./js-polyfills";
|
import { setPolyfillsOnLoad } from "./js-polyfills";
|
||||||
import { publicPath } from "./public-path";
|
import { publicPath } from "./public-path";
|
||||||
import { BaseLoadOptions } from "./load-options";
|
import { BaseLoadOptions } from "./load-options";
|
||||||
|
@ -35,7 +35,7 @@ type ProgressCallback = (bytesLoaded: number, bytesTotal: number) => void;
|
||||||
async function fetchRuffle(
|
async function fetchRuffle(
|
||||||
config: BaseLoadOptions,
|
config: BaseLoadOptions,
|
||||||
progressCallback?: ProgressCallback,
|
progressCallback?: ProgressCallback,
|
||||||
): Promise<typeof RuffleInstanceBuilder> {
|
): Promise<[typeof RuffleInstanceBuilder, typeof ZipWriter]> {
|
||||||
// Apply some pure JavaScript polyfills to prevent conflicts with external
|
// Apply some pure JavaScript polyfills to prevent conflicts with external
|
||||||
// libraries, if needed.
|
// libraries, if needed.
|
||||||
setPolyfillsOnLoad();
|
setPolyfillsOnLoad();
|
||||||
|
@ -65,7 +65,11 @@ async function fetchRuffle(
|
||||||
|
|
||||||
// Note: The argument passed to import() has to be a simple string literal,
|
// Note: The argument passed to import() has to be a simple string literal,
|
||||||
// otherwise some bundler will get confused and won't include the module?
|
// otherwise some bundler will get confused and won't include the module?
|
||||||
const { default: init, RuffleInstanceBuilder } = await (extensionsSupported
|
const {
|
||||||
|
default: init,
|
||||||
|
RuffleInstanceBuilder,
|
||||||
|
ZipWriter,
|
||||||
|
} = await (extensionsSupported
|
||||||
? import("../dist/ruffle_web-wasm_extensions")
|
? import("../dist/ruffle_web-wasm_extensions")
|
||||||
: import("../dist/ruffle_web"));
|
: import("../dist/ruffle_web"));
|
||||||
let response;
|
let response;
|
||||||
|
@ -113,10 +117,12 @@ async function fetchRuffle(
|
||||||
|
|
||||||
await init(response);
|
await init(response);
|
||||||
|
|
||||||
return RuffleInstanceBuilder;
|
return [RuffleInstanceBuilder, ZipWriter];
|
||||||
}
|
}
|
||||||
|
|
||||||
let nativeConstructor: Promise<typeof RuffleInstanceBuilder> | null = null;
|
let nativeConstructors: Promise<
|
||||||
|
[typeof RuffleInstanceBuilder, typeof ZipWriter]
|
||||||
|
> | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain an instance of `Ruffle`.
|
* Obtain an instance of `Ruffle`.
|
||||||
|
@ -130,11 +136,11 @@ let nativeConstructor: Promise<typeof RuffleInstanceBuilder> | null = null;
|
||||||
export async function createRuffleBuilder(
|
export async function createRuffleBuilder(
|
||||||
config: BaseLoadOptions,
|
config: BaseLoadOptions,
|
||||||
progressCallback?: ProgressCallback,
|
progressCallback?: ProgressCallback,
|
||||||
): Promise<RuffleInstanceBuilder> {
|
): Promise<[RuffleInstanceBuilder, () => ZipWriter]> {
|
||||||
if (nativeConstructor === null) {
|
if (nativeConstructors === null) {
|
||||||
nativeConstructor = fetchRuffle(config, progressCallback);
|
nativeConstructors = fetchRuffle(config, progressCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
const constructor = await nativeConstructor;
|
const constructors = await nativeConstructors;
|
||||||
return new constructor();
|
return [new constructors[0](), () => new constructors[1]()];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { RuffleHandle } from "../dist/ruffle_web";
|
import type { RuffleHandle, ZipWriter } from "../dist/ruffle_web";
|
||||||
import { createRuffleBuilder } from "./load-ruffle";
|
import { createRuffleBuilder } from "./load-ruffle";
|
||||||
import { applyStaticStyles, ruffleShadowTemplate } from "./shadow-template";
|
import { applyStaticStyles, ruffleShadowTemplate } from "./shadow-template";
|
||||||
import { lookupElement } from "./register-element";
|
import { lookupElement } from "./register-element";
|
||||||
|
@ -15,7 +15,6 @@ import type { MovieMetadata } from "./movie-metadata";
|
||||||
import { swfFileName } from "./swf-utils";
|
import { swfFileName } from "./swf-utils";
|
||||||
import { buildInfo } from "./build-info";
|
import { buildInfo } from "./build-info";
|
||||||
import { text, textAsParagraphs } from "./i18n";
|
import { text, textAsParagraphs } from "./i18n";
|
||||||
import JSZip from "jszip";
|
|
||||||
import { isExtension } from "./current-script";
|
import { isExtension } from "./current-script";
|
||||||
import { configureBuilder } from "./internal/builder";
|
import { configureBuilder } from "./internal/builder";
|
||||||
|
|
||||||
|
@ -167,6 +166,7 @@ export class RufflePlayer extends HTMLElement {
|
||||||
|
|
||||||
private swfUrl?: URL;
|
private swfUrl?: URL;
|
||||||
private instance: RuffleHandle | null;
|
private instance: RuffleHandle | null;
|
||||||
|
private newZipWriter: (() => ZipWriter) | null;
|
||||||
private lastActivePlayingState: boolean;
|
private lastActivePlayingState: boolean;
|
||||||
|
|
||||||
private _metadata: MovieMetadata | null;
|
private _metadata: MovieMetadata | null;
|
||||||
|
@ -333,6 +333,7 @@ export class RufflePlayer extends HTMLElement {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
|
this.newZipWriter = null;
|
||||||
this.onFSCommand = null;
|
this.onFSCommand = null;
|
||||||
|
|
||||||
this._readyState = ReadyState.HaveNothing;
|
this._readyState = ReadyState.HaveNothing;
|
||||||
|
@ -673,7 +674,8 @@ export class RufflePlayer extends HTMLElement {
|
||||||
'The configuration option contextMenu no longer takes a boolean. Use "on", "off", or "rightClickOnly".',
|
'The configuration option contextMenu no longer takes a boolean. Use "on", "off", or "rightClickOnly".',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const builder = await createRuffleBuilder(
|
|
||||||
|
const [builder, zipWriterClass] = await createRuffleBuilder(
|
||||||
this.loadedConfig || {},
|
this.loadedConfig || {},
|
||||||
this.onRuffleDownloadProgress.bind(this),
|
this.onRuffleDownloadProgress.bind(this),
|
||||||
).catch((e) => {
|
).catch((e) => {
|
||||||
|
@ -714,6 +716,7 @@ export class RufflePlayer extends HTMLElement {
|
||||||
this.panic(e);
|
this.panic(e);
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
|
this.newZipWriter = zipWriterClass;
|
||||||
configureBuilder(builder, this.loadedConfig || {});
|
configureBuilder(builder, this.loadedConfig || {});
|
||||||
builder.setVolume(this.volumeSettings.get_volume());
|
builder.setVolume(this.volumeSettings.get_volume());
|
||||||
|
|
||||||
|
@ -1159,13 +1162,17 @@ export class RufflePlayer extends HTMLElement {
|
||||||
event.pointerType === "touch" || event.pointerType === "pen";
|
event.pointerType === "touch" || event.pointerType === "pen";
|
||||||
}
|
}
|
||||||
|
|
||||||
private base64ToBlob(bytesBase64: string, mimeString: string): Blob {
|
private base64ToArray(bytesBase64: string): Uint8Array {
|
||||||
const byteString = atob(bytesBase64);
|
const byteString = atob(bytesBase64);
|
||||||
const ab = new ArrayBuffer(byteString.length);
|
const ia = new Uint8Array(byteString.length);
|
||||||
const ia = new Uint8Array(ab);
|
|
||||||
for (let i = 0; i < byteString.length; i++) {
|
for (let i = 0; i < byteString.length; i++) {
|
||||||
ia[i] = byteString.charCodeAt(i);
|
ia[i] = byteString.charCodeAt(i);
|
||||||
}
|
}
|
||||||
|
return ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
private base64ToBlob(bytesBase64: string, mimeString: string): Blob {
|
||||||
|
const ab = this.base64ToArray(bytesBase64);
|
||||||
const blob = new Blob([ab], { type: mimeString });
|
const blob = new Blob([ab], { type: mimeString });
|
||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
|
@ -1342,16 +1349,13 @@ export class RufflePlayer extends HTMLElement {
|
||||||
* Gets the local save information as SOL files and downloads them as a single ZIP file.
|
* Gets the local save information as SOL files and downloads them as a single ZIP file.
|
||||||
*/
|
*/
|
||||||
private async backupSaves(): Promise<void> {
|
private async backupSaves(): Promise<void> {
|
||||||
const zip = new JSZip();
|
const zip = this.newZipWriter!();
|
||||||
const duplicateNames: string[] = [];
|
const duplicateNames: string[] = [];
|
||||||
Object.keys(localStorage).forEach((key) => {
|
Object.keys(localStorage).forEach((key) => {
|
||||||
let solName = String(key.split("/").pop());
|
let solName = String(key.split("/").pop());
|
||||||
const solData = localStorage.getItem(key);
|
const solData = localStorage.getItem(key);
|
||||||
if (solData && this.isB64SOL(solData)) {
|
if (solData && this.isB64SOL(solData)) {
|
||||||
const blob = this.base64ToBlob(
|
const array = this.base64ToArray(solData);
|
||||||
solData,
|
|
||||||
"application/octet-stream",
|
|
||||||
);
|
|
||||||
const duplicate = duplicateNames.filter(
|
const duplicate = duplicateNames.filter(
|
||||||
(value) => value === solName,
|
(value) => value === solName,
|
||||||
).length;
|
).length;
|
||||||
|
@ -1359,10 +1363,10 @@ export class RufflePlayer extends HTMLElement {
|
||||||
if (duplicate > 0) {
|
if (duplicate > 0) {
|
||||||
solName += ` (${duplicate + 1})`;
|
solName += ` (${duplicate + 1})`;
|
||||||
}
|
}
|
||||||
zip.file(solName + ".sol", blob);
|
zip.addFile(solName + ".sol", array);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const blob = await zip.generateAsync({ type: "blob" });
|
const blob = new Blob([zip.save()]);
|
||||||
this.saveFile(blob, "saves.zip");
|
this.saveFile(blob, "saves.zip");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ mod log_adapter;
|
||||||
mod navigator;
|
mod navigator;
|
||||||
mod storage;
|
mod storage;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
mod zip;
|
||||||
|
|
||||||
use crate::builder::RuffleInstanceBuilder;
|
use crate::builder::RuffleInstanceBuilder;
|
||||||
use external_interface::{external_to_js_value, js_to_external_value};
|
use external_interface::{external_to_js_value, js_to_external_value};
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::Write;
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
use wasm_bindgen::JsValue;
|
||||||
|
use zip::write::SimpleFileOptions;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ZipWriter {
|
||||||
|
files: HashMap<String, Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl ZipWriter {
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = "addFile")]
|
||||||
|
pub fn add_file(&mut self, name: String, bytes: Vec<u8>) {
|
||||||
|
self.files.insert(name, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> Result<Vec<u8>, JsValue> {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
let mut zip = zip::ZipWriter::new(std::io::Cursor::new(&mut buffer));
|
||||||
|
for (name, content) in &self.files {
|
||||||
|
zip.start_file(name.to_string(), SimpleFileOptions::default())
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
zip.write_all(content).map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
zip.finish().map_err(|e| e.to_string())?;
|
||||||
|
Ok(buffer)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue