explorer: implement duplicate file feature

This commit is contained in:
David Lechner
2022-04-08 18:11:09 -05:00
parent 30741b13ef
commit e0a6926d01
25 changed files with 693 additions and 37 deletions
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { Button, Classes, Dialog } from '@blueprintjs/core';
import { useI18n } from '@shopify/react-i18n';
import React, { useCallback, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import {
FileNameValidationResult,
validateFileName,
} from '../../pybricksMicropython/lib';
import { useSelector } from '../../reducers';
import FileNameFormGroup from '../fileNameFormGroup/FileNameFormGroup';
import { duplicateFileDialogDidAccept, duplicateFileDialogDidCancel } from './actions';
import { I18nId } from './i18n';
const DuplicateFileDialog: React.VFC = () => {
// istanbul ignore next: babel-loader rewrites this line
const [i18n] = useI18n();
const dispatch = useDispatch();
const isOpen = useSelector((s) => s.explorer.duplicateFileDialog.isOpen);
const oldName = useSelector((s) => s.explorer.duplicateFileDialog.fileName);
const [baseName, extension] = oldName.split(/(\.\w+)$/);
const [newName, setNewName] = useState(baseName);
const files = useSelector((s) => s.explorer.files);
const result = validateFileName(
newName,
extension,
files.map((f) => f.name),
);
const inputRef = useRef<HTMLInputElement>(null);
const handleSubmit = useCallback<React.FormEventHandler>(
(e) => {
e.preventDefault();
dispatch(duplicateFileDialogDidAccept(oldName, `${newName}${extension}`));
},
[dispatch, oldName, newName, extension],
);
const handleClose = useCallback(() => {
dispatch(duplicateFileDialogDidCancel());
}, [dispatch]);
return (
<Dialog
title={i18n.translate(I18nId.Title, {
fileName: oldName,
})}
isOpen={isOpen}
onOpening={() => setNewName(baseName)}
onOpened={() => {
inputRef.current?.select();
inputRef.current?.focus();
}}
onClose={handleClose}
>
<form onSubmit={handleSubmit}>
<div className={Classes.DIALOG_BODY}>
<FileNameFormGroup
fileName={newName}
fileExtension={extension}
validationResult={result}
inputRef={inputRef}
onChange={setNewName}
/>
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button
intent="primary"
disabled={result !== FileNameValidationResult.IsOk}
type="submit"
>
{i18n.translate(I18nId.ActionAccept)}
</Button>
</div>
</div>
</form>
</Dialog>
);
};
export default DuplicateFileDialog;