From ede6f80f49dd34f0bc261c183a4220e173729000 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 28 Oct 2022 13:48:55 -0500 Subject: [PATCH] explorer/newFileWizard: add empty file option Fixes: https://github.com/pybricks/pybricks-code/issues/771 --- CHANGELOG.md | 5 +++ src/components/hubPicker/HubPicker.tsx | 9 +++++- src/components/hubPicker/hubPicker.scss | 4 +++ src/editor/pybricksMicroPython.ts | 4 ++- src/explorer/newFileWizard/NewFileWizard.tsx | 32 ++++++++++++++++--- src/explorer/newFileWizard/actions.ts | 8 +++-- .../newFileWizard/translations/en.json | 7 ++-- 7 files changed, 58 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f2871c1..a44fe692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ## [Unreleased] +### Added +- Added feature create new empty file ([pybricks-code#771]). + +[pybricks-code#771]: https://github.com/pybricks/pybricks-code/issues/771 + ## [2.0.0-beta.9] - 2022-10-27 ### Added diff --git a/src/components/hubPicker/HubPicker.tsx b/src/components/hubPicker/HubPicker.tsx index c6ae1be6..acef5614 100644 --- a/src/components/hubPicker/HubPicker.tsx +++ b/src/components/hubPicker/HubPicker.tsx @@ -16,13 +16,20 @@ const HubIcon: React.VoidFunctionComponent = ({ url, label }) => { return ; }; -export const HubPicker: React.VoidFunctionComponent = () => { +type HubPickerProps = { + disabled?: boolean; +}; + +export const HubPicker: React.VoidFunctionComponent = ({ + disabled, +}) => { const [selectedHub, setSelectedHub] = useHubPickerSelectedHub(); return ( setSelectedHub(e.currentTarget.value as Hub)} > diff --git a/src/components/hubPicker/hubPicker.scss b/src/components/hubPicker/hubPicker.scss index 9f18ff15..4a80c324 100644 --- a/src/components/hubPicker/hubPicker.scss +++ b/src/components/hubPicker/hubPicker.scss @@ -11,5 +11,9 @@ .#{bp.$ns}-radio { display: flex; align-items: center; + + &.#{bp.$ns}-disabled img { + opacity: 50%; + } } } diff --git a/src/editor/pybricksMicroPython.ts b/src/editor/pybricksMicroPython.ts index 14c46ef7..863368f2 100644 --- a/src/editor/pybricksMicroPython.ts +++ b/src/editor/pybricksMicroPython.ts @@ -337,7 +337,9 @@ const templateSnippets: Array< * Gets the template text for a Pybricks MicroPython file. * @param hub The hub label. */ -export function getPybricksMicroPythonFileTemplate(hub: HubLabel): string | undefined { +export function getPybricksMicroPythonFileTemplate( + hub: HubLabel | undefined, +): string | undefined { return templateSnippets.find((t) => t.label === hub)?.insertText; } diff --git a/src/explorer/newFileWizard/NewFileWizard.tsx b/src/explorer/newFileWizard/NewFileWizard.tsx index ec4dc635..63227c21 100644 --- a/src/explorer/newFileWizard/NewFileWizard.tsx +++ b/src/explorer/newFileWizard/NewFileWizard.tsx @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2022 The Pybricks Authors -import { Button, Classes, Dialog, FormGroup } from '@blueprintjs/core'; +import { Button, Classes, Dialog, FormGroup, Switch } from '@blueprintjs/core'; import React, { useCallback, useRef, useState } from 'react'; import { useId } from 'react-aria'; import { useDispatch } from 'react-redux'; +import { useLocalStorage } from 'usehooks-ts'; import { HubPicker } from '../../components/hubPicker/HubPicker'; import { useHubPickerSelectedHub } from '../../components/hubPicker/hooks'; import { useFileStorageMetadata } from '../../fileStorage/hooks'; @@ -22,6 +23,10 @@ const NewFileWizard: React.VoidFunctionComponent = () => { const i18n = useI18n(); const dispatch = useDispatch(); + const [emptyFile, setEmptyFile] = useLocalStorage( + 'explorer.newFileWizard.emptyFile', + false, + ); const isOpen = useSelector((s) => s.explorer.newFileWizard.isOpen); const [fileName, setFileName] = useState(''); const files = useFileStorageMetadata() ?? []; @@ -37,9 +42,15 @@ const NewFileWizard: React.VoidFunctionComponent = () => { const handleSubmit = useCallback( (e) => { e.preventDefault(); - dispatch(newFileWizardDidAccept(fileName, pythonFileExtension, hubType)); + dispatch( + newFileWizardDidAccept( + fileName, + pythonFileExtension, + emptyFile ? undefined : hubType, + ), + ); }, - [dispatch, fileName, pythonFileExtension, hubType], + [dispatch, fileName, pythonFileExtension, hubType, emptyFile], ); const handleClose = useCallback(() => { @@ -66,9 +77,20 @@ const NewFileWizard: React.VoidFunctionComponent = () => { inputRef={fileNameInputRef} onChange={setFileName} /> - - + + + + setEmptyFile((e.target as HTMLInputElement).checked) + } + > + {i18n.translate('emptyFile.label')} +
diff --git a/src/explorer/newFileWizard/actions.ts b/src/explorer/newFileWizard/actions.ts index b8d9ab20..98cf1594 100644 --- a/src/explorer/newFileWizard/actions.ts +++ b/src/explorer/newFileWizard/actions.ts @@ -20,10 +20,14 @@ export const newFileWizardShow = createAction(() => ({ * Indicates that the use accepted the new file wizard dialog. * @param fileName The user-provided file name. * @param fileExtension The user-provided file extension. - * @param hubType The user-provided hub type. + * @param hubType The user-provided hub type or undefined for an empty file. */ export const newFileWizardDidAccept = createAction( - (fileName: string, fileExtension: SupportedFileExtension, hubType: Hub) => ({ + ( + fileName: string, + fileExtension: SupportedFileExtension, + hubType: Hub | undefined, + ) => ({ type: 'explorer.newFileWizard.action.didAccept', fileName, fileExtension, diff --git a/src/explorer/newFileWizard/translations/en.json b/src/explorer/newFileWizard/translations/en.json index 7c17058d..ac2695f6 100644 --- a/src/explorer/newFileWizard/translations/en.json +++ b/src/explorer/newFileWizard/translations/en.json @@ -1,7 +1,10 @@ { "title": "Create a new file", - "smartHub": { - "label": "Smart hub" + "template": { + "label": "Template" + }, + "emptyFile": { + "label": "Create an empty file" }, "action": { "create": "Create"