clean up code a bit (split of SideBar component and simulator callbacks from App) + fix bug in property checker
This commit is contained in:
parent
2dd35ab079
commit
9922f8588d
10 changed files with 707 additions and 718 deletions
|
|
@ -1,29 +1,7 @@
|
|||
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||
import { BigStepCause, EditHistory } from "./App";
|
||||
import { VisualEditorState } from "./VisualEditor/VisualEditor";
|
||||
import { emptyState } from "@/statecharts/concrete_syntax";
|
||||
import { InsertMode } from "./TopPanel/InsertModes";
|
||||
import { Conns } from "@/statecharts/timed_reactive";
|
||||
|
||||
export function useUrlHashState(editorState: VisualEditorState | null, setEditHistory: Dispatch<SetStateAction<EditHistory|null>>) {
|
||||
|
||||
// i should probably put all these things into a single object, the 'app state'...
|
||||
const [autoScroll, setAutoScroll] = useState(false);
|
||||
const [autoConnect, setAutoConnect] = useState(true);
|
||||
const [plantConns, setPlantConns] = useState<Conns>({});
|
||||
const [showKeys, setShowKeys] = useState(true);
|
||||
const [zoom, setZoom] = useState(1);
|
||||
const [insertMode, setInsertMode] = useState<InsertMode>("and");
|
||||
const [plantName, setPlantName] = useState("dummy");
|
||||
|
||||
const [showConnections, setShowConnections] = useState(false);
|
||||
const [showProperties, setShowProperties] = useState(false);
|
||||
const [showExecutionTrace, setShowExecutionTrace] = useState(true);
|
||||
const [showPlantTrace, setShowPlantTrace] = useState(false);
|
||||
const [properties, setProperties] = useState<string[]>([]);
|
||||
const [savedTraces, setSavedTraces] = useState<[string, BigStepCause[]][]>([]);
|
||||
const [activeProperty, setActiveProperty] = useState<number>(0);
|
||||
import { useEffect } from "react";
|
||||
|
||||
// persist state in URL hash
|
||||
export function useUrlHashState<T>(recoverCallback: (recoveredState: T) => void): (toPersist: T) => void {
|
||||
|
||||
// recover editor state from URL - we need an effect here because decompression is asynchronous
|
||||
useEffect(() => {
|
||||
|
|
@ -32,7 +10,7 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
|||
if (compressedState.length === 0) {
|
||||
// empty URL hash
|
||||
console.log("no state to recover");
|
||||
setEditHistory(() => ({current: emptyState, history: [], future: []}));
|
||||
// setEditHistory(() => ({current: emptyState, history: [], future: []}));
|
||||
return;
|
||||
}
|
||||
let compressedBuffer;
|
||||
|
|
@ -41,7 +19,7 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
|||
} catch (e) {
|
||||
// probably invalid base64
|
||||
console.error("failed to recover state:", e);
|
||||
setEditHistory(() => ({current: emptyState, history: [], future: []}));
|
||||
// setEditHistory(() => ({current: emptyState, history: [], future: []}));
|
||||
return;
|
||||
}
|
||||
const ds = new DecompressionStream("deflate");
|
||||
|
|
@ -51,153 +29,28 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
|||
new Response(ds.readable).arrayBuffer()
|
||||
.then(decompressedBuffer => {
|
||||
const recoveredState = JSON.parse(new TextDecoder().decode(decompressedBuffer));
|
||||
// we support two formats
|
||||
if (recoveredState.nextID) {
|
||||
// old format
|
||||
setEditHistory(() => ({current: recoveredState, history: [], future: []}));
|
||||
}
|
||||
else {
|
||||
console.log(recoveredState);
|
||||
// new format
|
||||
if (recoveredState.editorState !== undefined) {
|
||||
setEditHistory(() => ({current: recoveredState.editorState, history: [], future: []}));
|
||||
}
|
||||
if (recoveredState.plantName !== undefined) {
|
||||
setPlantName(recoveredState.plantName);
|
||||
}
|
||||
if (recoveredState.autoScroll !== undefined) {
|
||||
setAutoScroll(recoveredState.autoScroll);
|
||||
}
|
||||
if (recoveredState.autoConnect !== undefined) {
|
||||
setAutoConnect(recoveredState.autoConnect);
|
||||
}
|
||||
if (recoveredState.plantConns !== undefined) {
|
||||
setPlantConns(recoveredState.plantConns);
|
||||
}
|
||||
|
||||
if (recoveredState.showKeys !== undefined) {
|
||||
setShowKeys(recoveredState.showKeys);
|
||||
}
|
||||
if (recoveredState.zoom !== undefined) {
|
||||
setZoom(recoveredState.zoom);
|
||||
}
|
||||
if (recoveredState.insertMode !== undefined) {
|
||||
setInsertMode(recoveredState.insertMode);
|
||||
}
|
||||
if (recoveredState.showConnections !== undefined) {
|
||||
setShowConnections(recoveredState.showConnections);
|
||||
}
|
||||
if (recoveredState.showProperties !== undefined) {
|
||||
setShowProperties(recoveredState.showProperties);
|
||||
}
|
||||
if (recoveredState.showExecutionTrace !== undefined) {
|
||||
setShowExecutionTrace(recoveredState.showExecutionTrace);
|
||||
}
|
||||
if (recoveredState.showPlantTrace !== undefined) {
|
||||
setShowPlantTrace(recoveredState.showPlantTrace);
|
||||
}
|
||||
if (recoveredState.properties !== undefined) {
|
||||
setProperties(recoveredState.properties);
|
||||
}
|
||||
if (recoveredState.savedTraces !== undefined) {
|
||||
setSavedTraces(recoveredState.savedTraces);
|
||||
}
|
||||
if (recoveredState.activeProperty !== undefined) {
|
||||
setActiveProperty(recoveredState.activeProperty);
|
||||
}
|
||||
|
||||
}
|
||||
recoverCallback(recoveredState);
|
||||
})
|
||||
.catch(e => {
|
||||
// any other error: invalid JSON, or decompression failed.
|
||||
console.error("failed to recover state:", e);
|
||||
setEditHistory({current: emptyState, history: [], future: []});
|
||||
// setEditHistory({current: emptyState, history: [], future: []});
|
||||
});
|
||||
}, []);
|
||||
|
||||
// save editor state in URL
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
if (editorState === null) {
|
||||
window.location.hash = "#";
|
||||
return;
|
||||
}
|
||||
const serializedState = JSON.stringify({
|
||||
autoConnect,
|
||||
autoScroll,
|
||||
plantConns,
|
||||
showKeys,
|
||||
zoom,
|
||||
insertMode,
|
||||
plantName,
|
||||
editorState,
|
||||
showConnections,
|
||||
showProperties,
|
||||
showExecutionTrace,
|
||||
showPlantTrace,
|
||||
properties,
|
||||
savedTraces,
|
||||
activeProperty,
|
||||
});
|
||||
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();
|
||||
window.location.hash = "#"+compressedStateString;
|
||||
});
|
||||
}, 100);
|
||||
return () => clearTimeout(timeout);
|
||||
}, [
|
||||
editorState,
|
||||
|
||||
autoConnect,
|
||||
autoScroll,
|
||||
plantConns,
|
||||
showKeys,
|
||||
zoom,
|
||||
insertMode,
|
||||
plantName,
|
||||
showConnections,
|
||||
showProperties,
|
||||
showExecutionTrace,
|
||||
showPlantTrace,
|
||||
properties,
|
||||
savedTraces,
|
||||
activeProperty,
|
||||
]);
|
||||
|
||||
return {
|
||||
autoConnect,
|
||||
setAutoConnect,
|
||||
autoScroll,
|
||||
setAutoScroll,
|
||||
plantConns,
|
||||
setPlantConns,
|
||||
showKeys,
|
||||
setShowKeys,
|
||||
zoom,
|
||||
setZoom,
|
||||
insertMode,
|
||||
setInsertMode,
|
||||
plantName,
|
||||
setPlantName,
|
||||
showConnections,
|
||||
setShowConnections,
|
||||
showProperties,
|
||||
setShowProperties,
|
||||
showExecutionTrace,
|
||||
setShowExecutionTrace,
|
||||
showPlantTrace,
|
||||
setShowPlantTrace,
|
||||
properties,
|
||||
setProperties,
|
||||
savedTraces,
|
||||
setSavedTraces,
|
||||
activeProperty,
|
||||
setActiveProperty,
|
||||
function persist(state: T) {
|
||||
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();
|
||||
window.location.hash = "#"+compressedStateString;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return persist;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue