Naive persistence of state in URL fragment

This commit is contained in:
ochafik 2023-03-24 04:33:39 +00:00
commit a890b4ce45
6 changed files with 114 additions and 43 deletions

View file

@ -1,10 +1,23 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import React from 'react';
import SCADEditor from './Editor';
import React, { useState } from 'react';
import {State} from './app-state'
import Editor from '@monaco-editor/react';
import './App.css';
import openscadEditorOptions from './language/openscad-editor-options';
import { writeStateInFragment } from './state';
export function App({initialState}: {initialState: State}) {
const [state, rawSetState] = useState(initialState);
const setState = (state: State) => {
rawSetState(state);
writeStateInFragment(state);
};
const value = state.source.content;
const setValue = (content?: string) => setState({...state, source: {...state.source, content: content ?? ''}});
export function App() {
return (
<div className="App">
<header className="App-header">
@ -20,9 +33,14 @@ export function App() {
>
Learn OpenSCAD
</a>
<SCADEditor height="50vh" value="if (true) sphere(10); else cube();"/>
</header>
<Editor
className="openscad-editor"
defaultLanguage="openscad"
value={value}
onChange={setValue}
options={openscadEditorOptions}
height="50vh"/>
</header>
</div>
);
}

View file

@ -1,36 +0,0 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import React from 'react';
import Editor from '@monaco-editor/react';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
const options: monaco.editor.IStandaloneEditorConstructionOptions = {
lineNumbers: 'on',
automaticLayout: true,
scrollBeyondLastLine: false,
fontSize: 12,
language: 'openscad',
wordWrap: 'on',
wrappingStrategy: 'advanced',
suggest: {
// snippetsPreventQuickSuggestions: false,
showStatusBar: true,
preview: true,
},
codeLens: true,
function SCADEditor({value, ...props}: {value: string, height: string}) {
// let editor: monaco.editor.IStandaloneCodeEditor;
// function editorDidMount(e) {
// editor = e;
// console.log('editorDidMount', monaco.languages.getLanguages(), editor);
<Editor {...props} className="openscad-editor" defaultLanguage="openscad" value={value} options={options} />
// onMount={editorDidMount} />
);
}
// export function createEditor() {
// monaco.editor.create(document.getElementById('openscad-editor') as any, options);
// }
export default SCADEditor;

14
src/app-state.ts Normal file
View file

@ -0,0 +1,14 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
export interface State {
source: {
content: string
},
output?: {
path: string,
timestamp: number,
sizeBytes: number,
formattedSize: string,
},
};

View file

@ -6,6 +6,8 @@ import reportWebVitals from './reportWebVitals';
import { createEditorFS } from './filesystem';
import { registerOpenSCADLanguage } from './language/openscad-register-language';
import { zipArchives } from './zip-archives';
import {readStateFromFragment} from './state'
import { State } from './app-state';
(async () => {
@ -13,12 +15,18 @@ import { zipArchives } from './zip-archives';
const fs = await createEditorFS(workingDir);
await registerOpenSCADLanguage(fs, workingDir, zipArchives);
const initialState = readStateFromFragment() ?? {
source: {
content: 'cube(1);\ntranslate([0.5, 0.5, 0.5])\n\tcube(1);',
}
} as State;
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
<App initialState={initialState} />
</React.StrictMode>
);

View file

@ -0,0 +1,50 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import React from 'react';
import Editor from '@monaco-editor/react';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
export default {
lineNumbers: 'on',
automaticLayout: true,
scrollBeyondLastLine: false,
fontSize: 12,
language: 'openscad',
tabSize: 2,
wordWrap: 'on',
wrappingStrategy: 'advanced',
suggest: {
// snippetsPreventQuickSuggestions: false,
localityBonus: true,
showStatusBar: true,
preview: true,
},
codeLens: true,
// language: 'javascript',
wordBasedSuggestions: false,
} as monaco.editor.IStandaloneEditorConstructionOptions;
// monaco.editor.IModelContentChangedEvent
// function SCADEditor({input, onInputChanged, ...props}: {input: string, onInputChanged: (value?: string) => void, height: string}) {
// // let editor: monaco.editor.IStandaloneCodeEditor;
// // function editorDidMount(e) {
// // editor = e;
// // console.log('editorDidMount', monaco.languages.getLanguages(), editor);
// // // editor.
// // editor.setModel(monaco.editor.createModel('sphere(123);', 'openscad'));
// // // editor.trigger('anything', 'editor.action.triggerSuggest', {});
// // }
// return (
// <Editor {...props}
// className="openscad-editor"
// defaultLanguage="openscad"
// value={n}
// onChange={setValue}
// options={options} />
// // onMount={editorDidMount} />
// );
// }

17
src/state.ts Normal file
View file

@ -0,0 +1,17 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import { State } from "./app-state";
export function writeStateInFragment(state: State) {
window.location.hash = encodeURIComponent(JSON.stringify(state));
}
export function readStateFromFragment() {
if (window.location.hash.startsWith('#') && window.location.hash.length > 1) {
try {
return JSON.parse(decodeURIComponent(window.location.hash.substring(1)));
} catch (e) {
console.error(e);
return null;
}
}
}