diff --git a/src/components/App.tsx b/src/components/App.tsx index 3c5509cf..86a94de2 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -129,6 +129,7 @@ type AppState = { export: boolean debug: boolean } + fileHandle: FileSystemFileHandle | null } export default class App extends React.Component { @@ -284,6 +285,7 @@ export default class App extends React.Component { openlayersDebugOptions: { debugToolbox: false, }, + fileHandle: null, } this.layerWatcher = new LayerWatcher({ @@ -611,7 +613,8 @@ export default class App extends React.Component { } } - openStyle = (styleObj: StyleSpecification & {id: string}) => { + openStyle = (styleObj: StyleSpecification & {id: string}, fileHandle: FileSystemFileHandle | null) => { + this.setState({fileHandle: fileHandle}); styleObj = this.setDefaultValues(styleObj) this.onStyleChanged(styleObj) } @@ -847,6 +850,10 @@ export default class App extends React.Component { this.setModal(modalName, !this.state.isOpen[modalName]); } + onSetFileHandle(fileHandle: FileSystemFileHandle | null) { + this.setState({fileHandle: fileHandle}); + } + onChangeOpenlayersDebug = (key: keyof AppState["openlayersDebugOptions"], value: boolean) => { this.setState({ openlayersDebugOptions: { @@ -949,11 +956,14 @@ export default class App extends React.Component { onStyleChanged={this.onStyleChanged} isOpen={this.state.isOpen.export} onOpenToggle={this.toggleModal.bind(this, 'export')} + fileHandle={this.state.fileHandle} + onSetFileHandle={this.onSetFileHandle} /> { } async saveStyle() { - let fileHandle: FileSystemFileHandle; const tokenStyle = this.tokenizedStyle(); - if (fileHandle != null) { - const writable = await fileHandle.createWritable(); - await writable.write(tokenStyle); - await writable.close(); - } else { - await this.saveStyleAs(); + let fileHandle = this.props.fileHandle; + if (fileHandle == null) { + fileHandle = await this.createFileHandle(); + this.props.onSetFileHandle(fileHandle) + if (fileHandle == null) return; } + + const writable = await fileHandle.createWritable(); + await writable.write(tokenStyle); + await writable.close(); + this.props.onOpenToggle(); } async saveStyleAs() { const tokenStyle = this.tokenizedStyle(); - const root = await navigator.storage.getDirectory(); - const draftHandle = await root.getFileHandle(this.exportName(), { create: true }); - const writeable = await draftHandle.createWritable(); + const fileHandle = await this.createFileHandle(); + this.props.onSetFileHandle(fileHandle) + if (fileHandle == null) return; - await writeable.write(tokenStyle); - await writeable.close(); - // TODO close existing fileHandle - // TODO this.props.fileHandle = accessHandle; + const writable = await fileHandle.createWritable(); + await writable.write(tokenStyle); + await writable.close(); + this.props.onOpenToggle(); + } + + async createFileHandle() : Promise { + const pickerOpts = { + types: [ + { + description: "Style JSON", + accept: {"application/json": [".json"]}, + suggestedName: this.exportName(), + }, + ], + excludeAcceptAllOption: true, + multiple: false, + }; + + const fileHandle = await window.showSaveFilePicker(pickerOpts) as FileSystemFileHandle; + this.props.onSetFileHandle(fileHandle) + return fileHandle; } changeMetadataProperty(property: string, value: any) { diff --git a/src/components/ModalOpen.tsx b/src/components/ModalOpen.tsx index 4415175c..7007adcd 100644 --- a/src/components/ModalOpen.tsx +++ b/src/components/ModalOpen.tsx @@ -1,7 +1,6 @@ import React, { FormEvent } from 'react' import {MdFileUpload} from 'react-icons/md' import {MdAddCircleOutline} from 'react-icons/md' -import FileReaderInput, { Result } from 'react-file-reader-input' import { Trans, WithTranslation, withTranslation } from 'react-i18next'; import ModalLoading from './ModalLoading' @@ -47,6 +46,7 @@ type ModalOpenInternalProps = { isOpen: boolean onOpenToggle(...args: unknown[]): unknown onStyleOpen(...args: unknown[]): unknown + fileHandle: FileSystemFileHandle | null } & WithTranslation; type ModalOpenState = { @@ -137,7 +137,6 @@ class ModalOpenInternal extends React.Component { this.clearError(); - // TODO close existing file handles const pickerOpts = { types: [ @@ -164,7 +163,8 @@ class ModalOpenInternal extends React.Component