Files
pybricks-code/src/explorer/newFileWizard/NewFileWizard.tsx
T
David Lechner 3953816350 components/hubPicker: back state with localStorage
This saves the selected hub in localStorage. This will "remember" the
state between app launches and also synchronize the state between
various users of the component. Both of these should mean fewer clicks
required by the user.
2022-07-27 15:30:39 -05:00

95 lines
3.4 KiB
TypeScript

// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { Button, Classes, Dialog, FormGroup } from '@blueprintjs/core';
import React, { useCallback, useRef, useState } from 'react';
import { useId } from 'react-aria';
import { useDispatch } from 'react-redux';
import { HubPicker } from '../../components/hubPicker/HubPicker';
import { useHubPickerSelectedHub } from '../../components/hubPicker/hooks';
import { useFileStorageMetadata } from '../../fileStorage/hooks';
import {
FileNameValidationResult,
pythonFileExtension,
validateFileName,
} from '../../pybricksMicropython/lib';
import { useSelector } from '../../reducers';
import FileNameFormGroup from '../fileNameFormGroup/FileNameFormGroup';
import { newFileWizardDidAccept, newFileWizardDidCancel } from './actions';
import { useI18n } from './i18n';
const NewFileWizard: React.VoidFunctionComponent = () => {
const i18n = useI18n();
const dispatch = useDispatch();
const isOpen = useSelector((s) => s.explorer.newFileWizard.isOpen);
const [fileName, setFileName] = useState('');
const files = useFileStorageMetadata() ?? [];
const fileNameValidation = validateFileName(
fileName,
pythonFileExtension,
files.map((f) => f.path),
);
const [hubType] = useHubPickerSelectedHub();
const fileNameInputRef = useRef<HTMLInputElement>(null);
const handleSubmit = useCallback<React.FormEventHandler>(
(e) => {
e.preventDefault();
dispatch(newFileWizardDidAccept(fileName, pythonFileExtension, hubType));
},
[dispatch, fileName, pythonFileExtension, hubType],
);
const handleClose = useCallback(() => {
dispatch(newFileWizardDidCancel());
}, [dispatch]);
const acceptButtonLabelId = useId();
return (
<Dialog
icon="plus"
title={i18n.translate('title')}
isOpen={isOpen}
onOpening={() => setFileName('')}
onOpened={() => fileNameInputRef.current?.focus()}
onClose={handleClose}
>
<form onSubmit={handleSubmit}>
<div className={Classes.DIALOG_BODY}>
<FileNameFormGroup
fileName={fileName}
fileExtension={pythonFileExtension}
validationResult={fileNameValidation}
inputRef={fileNameInputRef}
onChange={setFileName}
/>
<FormGroup label={i18n.translate('smartHub.label')}>
<HubPicker />
</FormGroup>
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button
aria-labelledby={acceptButtonLabelId}
intent="primary"
disabled={
fileNameValidation !== FileNameValidationResult.IsOk
}
type="submit"
>
<span id={acceptButtonLabelId}>
{i18n.translate('action.create')}
</span>
</Button>
</div>
</div>
</form>
</Dialog>
);
};
export default NewFileWizard;