diff --git a/README.md b/README.md index b31b932..be2b125 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Licenses: see [LICENSES](./LICENSE). - Autocomplete of imports - Autocomplete of symbols / function calls (pseudo-parses file and its transitive imports) - Responsive layout (but editing on iOS is still a pain, will address that soon). On small screens editor and viewer are stacked onto each other, while on larger screens they can be side-by-side +- Installable as a PWA (then persists edits in localStorage instead of the hash fragment). On iOS just open the sharing panel and tap "Add to Home Screen". ## Roadmap @@ -31,7 +32,7 @@ Licenses: see [LICENSES](./LICENSE). - Better names for downloads (matching source) - Model /home fs in shared state. have two clear paths: /libraries for builtins, and /home for user data. State pointing to /libraries paths needs not store the data except if there's overrides (flagged as modifications in the file picker) - Drag and drop of files (SCAD, STL, etc) and Zip archives. For assets, auto insert the corresponding import. -- Proper PWA w/ File opening / association to *.scad files +- Fuller PWA support w/ link Sharing, File opening / association to *.scad files... - Look into accessibility - Setup [OPENSCADPATH](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Libraries#Setting_OPENSCADPATH) env var w/ Emscripten to ensure examples that include assets / import local files will run fine. - Bundle more examples (ask users to contribute) diff --git a/src/components/App.tsx b/src/components/App.tsx index ff699fd..357bb70 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,7 +1,7 @@ // Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING. import React, { CSSProperties, useEffect, useState } from 'react'; -import {MultiLayoutComponentId, State} from '../state/app-state' +import {MultiLayoutComponentId, State, StatePersister} from '../state/app-state' import { Model } from '../state/model'; import EditorPanel from './EditorPanel'; import ViewerPanel from './ViewerPanel'; @@ -13,10 +13,10 @@ import PanelSwitcher from './PanelSwitcher'; // import "primereact/resources/primereact.min.css"; // import "primeicons/primeicons.css"; -export function App({initialState, fs}: {initialState: State, fs: FS}) { +export function App({initialState, statePersister, fs}: {initialState: State, statePersister: StatePersister, fs: FS}) { const [state, setState] = useState(initialState); - const model = new Model(fs, state, setState); + const model = new Model(fs, state, setState, statePersister); useEffect(() => model.init()); const zIndexOfPanelsDependingOnFocus = { diff --git a/src/components/SettingsMenu.tsx b/src/components/SettingsMenu.tsx index 89b646e..aff816e 100644 --- a/src/components/SettingsMenu.tsx +++ b/src/components/SettingsMenu.tsx @@ -5,6 +5,8 @@ import { Button } from 'primereact/button'; import { MenuItem } from 'primereact/menuitem'; import { Menu } from 'primereact/menu'; import { ModelContext } from './contexts'; +import { isInStandaloneMode } from '../utils'; +import { ConfirmDialog, confirmDialog } from 'primereact/confirmdialog'; export default function SettingsMenu({className, style}: {className?: string, style?: CSSProperties}) { const model = useContext(ModelContext); @@ -44,7 +46,34 @@ export default function SettingsMenu({className, style}: {className?: string, st // disabled: true, command: () => model.mutate(s => s.view.lineNumbers = !s.view.lineNumbers) }, + ...(isInStandaloneMode ? [ + { + separator: true + }, + { + label: 'Clear local storage', + icon: 'pi pi-list', + // disabled: true, + command: () => { + confirmDialog({ + message: "This will clear all the edits you've made and files you've created in this playground " + + "and will reset it to factory defaults. " + + "Are you sure you wish to proceed? (you might lose your models!)", + header: 'Clear local storage', + icon: 'pi pi-exclamation-triangle', + accept: () => { + localStorage.clear(); + location.reload(); + }, + acceptLabel: `Clear all files!`, + rejectLabel: 'Cancel' + }); + }, + }, + ] : []), ] as MenuItem[]} popup ref={settingsMenu} /> + +