use browser's builtin compression streams API instead of LZ4 package

This commit is contained in:
Joeri Exelmans 2025-10-19 11:51:57 +02:00
parent a10bf9acc8
commit 22fbe70a60
3 changed files with 24 additions and 13 deletions

View file

@ -8,7 +8,6 @@
"@fontsource/roboto": "^5.2.8",
"@mui/icons-material": "^7.3.4",
"@mui/material": "^7.3.4",
"@nick/lz4": "npm:@jsr/nick__lz4",
"react": "^19",
"react-dom": "^19",
},
@ -94,8 +93,6 @@
"@mui/utils": ["@mui/utils@7.3.3", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@mui/types": "^7.4.7", "@types/prop-types": "^15.7.15", "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-is": "^19.1.1" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-kwNAUh7bLZ7mRz9JZ+6qfRnnxbE4Zuc+RzXnhSpRSxjTlSTj7b4JxRLXpG+MVtPVtqks5k/XC8No1Vs3x4Z2gg=="],
"@nick/lz4": ["@jsr/nick__lz4@0.3.4", "https://npm.jsr.io/~/11/@jsr/nick__lz4/0.3.4.tgz", {}, "sha512-ZNc+8lCMC8D/cIa9GrSxRcEQC/MyThBOXXlg6rhrvAWSUcKPODwvscsVA+v1UugiBzfJ2dvQIZ/j8484PMadkg=="],
"@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="],
"@types/bun": ["@types/bun@1.2.23", "", { "dependencies": { "bun-types": "1.2.23" } }, "sha512-le8ueOY5b6VKYf19xT3McVbXqLqmxzPXHsQT/q9JHgikJ2X22wyTW3g3ohz2ZMnp7dod6aduIiq8A14Xyimm0A=="],

View file

@ -15,7 +15,6 @@
"@fontsource/roboto": "^5.2.8",
"@mui/icons-material": "^7.3.4",
"@mui/material": "^7.3.4",
"@nick/lz4": "npm:@jsr/nick__lz4",
"react": "^19",
"react-dom": "^19"
},

View file

@ -1,4 +1,3 @@
import * as lz4 from "@nick/lz4";
import { Dispatch, SetStateAction, useEffect, useMemo, useRef, useState } from "react";
import { Statechart } from "../statecharts/abstract_syntax";
@ -136,9 +135,15 @@ export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highligh
useEffect(() => {
const compressedState = window.location.hash.slice(1);
try {
const compressedBuffer = Uint8Array.fromBase64(compressedState);
const recoveredState = JSON.parse(new TextDecoder().decode(lz4.decompress(compressedBuffer)));
setState(recoveredState);
const ds = new DecompressionStream("deflate");
const writer = ds.writable.getWriter();
writer.write(Uint8Array.fromBase64(compressedState));
writer.close();
new Response(ds.readable).arrayBuffer().then(decompressedBuffer => {
const recoveredState = JSON.parse(new TextDecoder().decode(decompressedBuffer));
setState(recoveredState);
});
}
catch (e) {
console.error("could not recover state:", e);
@ -147,11 +152,21 @@ export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highligh
useEffect(() => {
const timeout = setTimeout(() => {
const stateBuffer = new TextEncoder().encode(JSON.stringify(state));
const compressedStateBuffer = lz4.compress(stateBuffer);
const compressedStateString = compressedStateBuffer.toBase64();
window.location.hash = "#"+compressedStateString;
}, 200);
const serializedState = JSON.stringify(state);
const stateBuffer = new TextEncoder().encode(serializedState);
const cs = new CompressionStream("deflate");
const writer = cs.writable.getWriter();
writer.write(stateBuffer);
writer.close();
// todo: cancel this promise handler when concurrently starting another compression job
new Response(cs.readable).arrayBuffer().then(compressedStateBuffer => {
const compressedStateString = new Uint8Array(compressedStateBuffer).toBase64();
console.log(compressedStateString.length, serializedState.length);
window.location.hash = "#"+compressedStateString;
});
}, 100);
return () => clearTimeout(timeout);
}, [state]);