From 8efdd1f4feef3be988a92169647b92806c733448 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Fri, 21 Jun 2024 17:14:16 +0100 Subject: [PATCH 1/2] compress state in url fragment w/ gzip now the APIs are standard --- src/index.tsx | 4 ++-- src/state/app-state.ts | 2 +- src/state/fragment-state.ts | 48 ++++++++++++++++++++++++++++++++----- tsconfig.json | 2 +- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index ca69083..fd7250f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -52,12 +52,12 @@ declare var BrowserFS: BrowserFSInterface console.log('Failed to read the persisted state from local storage.', e) } statePersister = { - set: ({view, params}) => { + set: async ({view, params}) => { fs.writeFile('/state.json', JSON.stringify({view, params})); } }; } else { - persistedState = readStateFromFragment(); + persistedState = await readStateFromFragment(); statePersister = { set: writeStateInFragment, }; diff --git a/src/state/app-state.ts b/src/state/app-state.ts index 92553d9..bc913b1 100644 --- a/src/state/app-state.ts +++ b/src/state/app-state.ts @@ -51,7 +51,7 @@ export interface State { }; export interface StatePersister { - set(state: State): void; + set(state: State): Promise; } export {} \ No newline at end of file diff --git a/src/state/fragment-state.ts b/src/state/fragment-state.ts index 6d40a19..b9d1156 100644 --- a/src/state/fragment-state.ts +++ b/src/state/fragment-state.ts @@ -7,19 +7,55 @@ import { defaultModelColor } from "./initial-state"; export function buildUrlForStateParams(state: State) {//partialState: {params: State['params'], view: State['view']}) { return `${location.protocol}//${location.host}${location.pathname}#${encodeStateParamsAsFragment(state)}`; } -export function writeStateInFragment(state: State) { - window.location.hash = encodeStateParamsAsFragment(state); +export async function writeStateInFragment(state: State) { + window.location.hash = await encodeStateParamsAsFragment(state); } +async function compressString(input: string): Promise { + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(new TextEncoder().encode(input)); + controller.close(); + } + }); + const compressedStream = stream.pipeThrough(new CompressionStream('gzip')); + const compressedData = await new Response(compressedStream).arrayBuffer(); + return btoa(String.fromCharCode(...new Uint8Array(compressedData))); +} + +async function decompressString(compressedInput: string): Promise { + const compressedData = Uint8Array.from(atob(compressedInput), c => c.charCodeAt(0)); + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(compressedData); + controller.close(); + } + }); + + const decompressedStream = stream.pipeThrough(new DecompressionStream('gzip')); + const decompressedData = await new Response(decompressedStream).arrayBuffer(); + return new TextDecoder().decode(decompressedData); +} + export function encodeStateParamsAsFragment(state: State) { - return encodeURIComponent(JSON.stringify({ + const json = JSON.stringify({ params: state.params, view: state.view - })); + }); + // return encodeURIComponent(json); + return compressString(json); } -export function readStateFromFragment(): State | null { +export async function readStateFromFragment(): Promise { if (window.location.hash.startsWith('#') && window.location.hash.length > 1) { try { - const {params, view} = JSON.parse(decodeURIComponent(window.location.hash.substring(1))); + const serialized = window.location.hash.substring(1); + let obj; + try { + obj = JSON.parse(await decompressString(serialized)); + } catch (e) { + // Backwards compatibility + obj = JSON.parse(decodeURIComponent(serialized)); + } + const {params, view} = obj; return { params: { sourcePath: validateString(params?.sourcePath), diff --git a/tsconfig.json b/tsconfig.json index 1be57fe..760e85f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "lib": [ "dom", "dom.iterable", - "ES2021", + "ES2023", "WebWorker", ], "rootDir": "src", From 7e7a408ea7dcc71f0e691353ef290a981f341ba6 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Fri, 21 Jun 2024 17:20:09 +0100 Subject: [PATCH 2/2] rename {revarbat -> BelfrySCAD}/BOSL2 --- LICENSE.md | 2 +- Makefile | 2 +- src/components/HelpMenu.tsx | 2 +- src/fs/zip-archives.ts | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 8089a3e..429fcd9 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -163,7 +163,7 @@ Licensed under the [GNU LGPLv2.1](#lgplv21). ### BOSL2 https://github.com/revarbat/BOSL -https://github.com/revarbat/BOSL2 +https://github.com/BelfrySCAD/BOSL2 ``` BSD 2-Clause License diff --git a/Makefile b/Makefile index c043436..29f6e59 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ public/libraries/openscad.zip: libs/openscad ( cd libs/openscad ; zip -r ../../public/libraries/openscad.zip `find examples -name '*.scad' | grep -v tests` ) libs/BOSL2: - git clone --recurse https://github.com/revarbat/BOSL2.git ${SHALLOW} ${SINGLE_BRANCH} $@ + git clone --recurse https://github.com/BelfrySCAD/BOSL2.git ${SHALLOW} ${SINGLE_BRANCH} $@ public/libraries/BOSL2.zip: libs/BOSL2 mkdir -p public/libraries diff --git a/src/components/HelpMenu.tsx b/src/components/HelpMenu.tsx index 1590330..77b994f 100644 --- a/src/components/HelpMenu.tsx +++ b/src/components/HelpMenu.tsx @@ -37,7 +37,7 @@ export default function HelpMenu() { { label: 'BOSL2 Cheatsheet', icon: 'pi pi-palette', - url: 'https://github.com/revarbat/BOSL2/wiki/CheatSheet', + url: 'https://github.com/BelfrySCAD/BOSL2/wiki/CheatSheet', target: '_blank' }, ] as MenuItem[]} popup ref={menuRef} /> diff --git a/src/fs/zip-archives.ts b/src/fs/zip-archives.ts index fc2fd2b..4522435 100644 --- a/src/fs/zip-archives.ts +++ b/src/fs/zip-archives.ts @@ -54,12 +54,12 @@ export const zipArchives: ZipArchives = { description: 'The Belfry OpenScad Library, v2.0', gitOrigin: { branch: 'master', - repoUrl: 'https://github.com/revarbat/BOSL2', + repoUrl: 'https://github.com/BelfrySCAD/BOSL2', include: [{glob: ['**/*.scad', 'LICENSE']}], }, docs: { - 'CheatSheet': 'https://github.com/revarbat/BOSL2/wiki/CheatSheet', - 'Wiki': 'https://github.com/revarbat/BOSL2/wiki', + 'CheatSheet': 'https://github.com/BelfrySCAD/BOSL2/wiki/CheatSheet', + 'Wiki': 'https://github.com/BelfrySCAD/BOSL2/wiki', }, }, 'NopSCADlib': {