diff --git a/src/explorer/Explorer.test.tsx b/src/explorer/Explorer.test.tsx index ebf4f674..1bdf09d4 100644 --- a/src/explorer/Explorer.test.tsx +++ b/src/explorer/Explorer.test.tsx @@ -13,7 +13,6 @@ import { explorerDeleteFile, explorerExportFile, explorerImportFiles, - explorerRenameFile, } from './actions'; import { ExplorerFileInfo } from './reducers'; @@ -102,38 +101,6 @@ describe('tree item', () => { expect(dispatch).toHaveBeenCalledWith(explorerActivateFile('test.file')); }); - describe('rename', () => { - it('should dispatch action when button is clicked', async () => { - const [explorer, dispatch] = testRender(, { - explorer: { files: [testFile] }, - }); - - // NB: this button is intentionally not accessible (by role) since - // there is a keyboard shortcut. - const button = explorer.getByTitle('Rename test.file'); - - userEvent.click(button); - - expect(dispatch).toHaveBeenCalledWith(explorerRenameFile('test.file')); - - // should not propagate to treeitem - expect(dispatch).toHaveBeenCalledTimes(1); - }); - - it('should dispatch action when key is pressed', async () => { - const [explorer, dispatch] = testRender(, { - explorer: { files: [testFile] }, - }); - - const treeItem = explorer.getByRole('treeitem', { name: 'test.file' }); - - userEvent.click(treeItem); - userEvent.keyboard('{f2}'); - - expect(dispatch).toHaveBeenCalledWith(explorerRenameFile('test.file')); - }); - }); - describe('export', () => { it('should dispatch export action when button is clicked', async () => { const [explorer, dispatch] = testRender(, { diff --git a/src/explorer/Explorer.tsx b/src/explorer/Explorer.tsx index 8397cb1e..d080f4c4 100644 --- a/src/explorer/Explorer.tsx +++ b/src/explorer/Explorer.tsx @@ -35,12 +35,10 @@ import { explorerDeleteFile, explorerExportFile, explorerImportFiles, - explorerRenameFile, } from './actions'; import DeleteFileAlert from './deleteFileAlert/DeleteFileAlert'; import { I18nId } from './i18n'; import NewFileWizard from './newFileWizard/NewFileWizard'; -import RenameFileDialog from './renameFileDialog/RenameFileDialog'; type ActionButtonProps = { /** The icon to use for the button. */ @@ -109,12 +107,6 @@ const FileActionButtonGroup: React.VoidFunctionComponent className="pb-explorer-file-action-button-group" minimal={true} > - dispatch(explorerRenameFile(fileName))} - /> -
  • ${i18n.translate( - I18nId.TreeLiveDescriptorIntroKeybindingsRename, - { key: 'f2' }, - )}
  • ${i18n.translate( I18nId.TreeLiveDescriptorIntroKeybindingsExport, { key: `${isMacOS() ? 'cmd' : 'ctrl'}+e` }, @@ -228,13 +216,6 @@ const renderTreeContainer: typeof renderers.renderTreeContainer = (props) => { const hotKeyActive = isActiveTree; /* && !dnd.isProgrammaticallyDragging && !isRenaming */ - const handleRenameKeyDown = useCallback(() => { - if (focusedItem !== undefined) { - const fileName = environment.getItemTitle(environment.items[focusedItem]); - dispatch(explorerRenameFile(fileName)); - } - }, [environment]); - const handleDeleteKeyDown = useCallback(() => { if (focusedItem !== undefined) { const fileName = environment.getItemTitle(environment.items[focusedItem]); @@ -251,13 +232,6 @@ const renderTreeContainer: typeof renderers.renderTreeContainer = (props) => { const hotkeys = useMemo( () => [ - { - combo: 'f2', - label: 'Rename', - disabled: !hotKeyActive, - preventDefault: true, - onKeyDown: handleRenameKeyDown, - }, { combo: 'del', label: 'Delete', @@ -380,7 +354,6 @@ const Explorer: React.VFC = () => { - ); diff --git a/src/explorer/actions.ts b/src/explorer/actions.ts index 62b58829..1f730ca2 100644 --- a/src/explorer/actions.ts +++ b/src/explorer/actions.ts @@ -102,29 +102,6 @@ export const explorerDidFailToActivateFile = createAction( }), ); -/** - * Action that requests to rename a file. - * @param fileName The file name. - */ -export const explorerRenameFile = createAction((fileName: string) => ({ - type: 'explorer.action.renameFile', - fileName, -})); - -/** - * Action that indicates that {@link explorerRenameFile} succeeded. - */ -export const explorerDidRenameFile = createAction(() => ({ - type: 'explorer.action.didRenameFile', -})); - -/** - * Action that indicates that {@link explorerRenameFile} failed. - */ -export const explorerDidFailToRenameFile = createAction(() => ({ - type: 'explorer.action.didFailToRenameFile', -})); - /** * Request to export (download) a file. * @param fileName The file name. diff --git a/src/explorer/i18n.ts b/src/explorer/i18n.ts index 7bd079bf..4e64f97d 100644 --- a/src/explorer/i18n.ts +++ b/src/explorer/i18n.ts @@ -11,11 +11,9 @@ export enum I18nId { TreeLiveDescriptorIntroAccessibilityGuide = 'tree.liveDescriptor.intro.accessibilityGuide', TreeLiveDescriptorIntroNavigation = 'tree.liveDescriptor.intro.navigation', TreeLiveDescriptorIntroKeybindingsPrimaryAction = 'tree.liveDescriptor.intro.keybindings.primaryAction', - TreeLiveDescriptorIntroKeybindingsRename = 'tree.liveDescriptor.intro.keybindings.rename', TreeLiveDescriptorIntroKeybindingsExport = 'tree.liveDescriptor.intro.keybindings.export', TreeLiveDescriptorIntroKeybindingsDelete = 'tree.liveDescriptor.intro.keybindings.delete', TreeLiveDescriptorSearching = 'tree.liveDescriptor.searching', TreeItemDeleteTooltip = 'treeItem.deleteTooltip', TreeItemExportTooltip = 'treeItem.exportTooltip', - TreeItemRenameTooltip = 'treeItem.renameTooltip', } diff --git a/src/explorer/sagas.test.ts b/src/explorer/sagas.test.ts index c022cd54..bec97f98 100644 --- a/src/explorer/sagas.test.ts +++ b/src/explorer/sagas.test.ts @@ -19,14 +19,11 @@ import { fileStorageDidFailToDeleteFile, fileStorageDidFailToDumpAllFiles, fileStorageDidFailToReadFile, - fileStorageDidFailToRenameFile, fileStorageDidReadFile, fileStorageDidRemoveItem, - fileStorageDidRenameFile, fileStorageDidWriteFile, fileStorageDumpAllFiles, fileStorageReadFile, - fileStorageRenameFile, fileStorageWriteFile, } from '../fileStorage/actions'; import { pythonFileExtension } from '../pybricksMicropython/lib'; @@ -46,12 +43,9 @@ import { explorerDidFailToDeleteFile, explorerDidFailToExportFile, explorerDidFailToImportFiles, - explorerDidFailToRenameFile, explorerDidImportFiles, - explorerDidRenameFile, explorerExportFile, explorerImportFiles, - explorerRenameFile, } from './actions'; import { deleteFileAlertDidAccept, @@ -64,11 +58,6 @@ import { newFileWizardDidCancel, newFileWizardShow, } from './newFileWizard/actions'; -import { - renameFileDialogDidAccept, - renameFileDialogDidCancel, - renameFileDialogShow, -} from './renameFileDialog/actions'; import explorer from './sagas'; jest.mock('browser-fs-access'); @@ -263,52 +252,6 @@ describe('handleExplorerActivateFile', () => { }); }); -describe('handleExplorerRenameFile', () => { - let saga: AsyncSaga; - - beforeEach(async () => { - saga = new AsyncSaga(explorer); - - saga.put(explorerRenameFile('old.file')); - - await expect(saga.take()).resolves.toEqual(renameFileDialogShow('old.file')); - }); - - it('should dispatch action if canceled', async () => { - saga.put(renameFileDialogDidCancel()); - - await expect(saga.take()).resolves.toEqual(explorerDidFailToRenameFile()); - }); - - describe('should dispatch fileStorageOpenFile action if accepted', () => { - beforeEach(async () => { - saga.put(renameFileDialogDidAccept('old.file', 'new.file')); - - await expect(saga.take()).resolves.toEqual( - fileStorageRenameFile('old.file', 'new.file'), - ); - }); - - it('should dispatch action on fileStorageRenameFile failure', async () => { - saga.put( - fileStorageDidFailToRenameFile('old.file', new Error('test error')), - ); - - await expect(saga.take()).resolves.toEqual(explorerDidFailToRenameFile()); - }); - - it('should dispatch action on fileStorageRenameFile success', async () => { - saga.put(fileStorageDidRenameFile('old.file')); - - await expect(saga.take()).resolves.toEqual(explorerDidRenameFile()); - }); - }); - - afterEach(async () => { - await saga.end(); - }); -}); - describe('handleExplorerExportFile', () => { let saga: AsyncSaga; const testFile = 'test.file'; diff --git a/src/explorer/sagas.ts b/src/explorer/sagas.ts index 9f890822..97563e6e 100644 --- a/src/explorer/sagas.ts +++ b/src/explorer/sagas.ts @@ -3,15 +3,7 @@ import { fileOpen, fileSave } from 'browser-fs-access'; import JSZip from 'jszip'; -import { - call, - put, - race, - select, - take, - takeEvery, - takeLatest, -} from 'typed-redux-saga/macro'; +import { call, put, race, select, take, takeEvery } from 'typed-redux-saga/macro'; import { editorActivateFile, editorCloseFile, @@ -27,15 +19,12 @@ import { fileStorageDidFailToDeleteFile, fileStorageDidFailToDumpAllFiles, fileStorageDidFailToReadFile, - fileStorageDidFailToRenameFile, fileStorageDidFailToWriteFile, fileStorageDidReadFile, fileStorageDidRemoveItem, - fileStorageDidRenameFile, fileStorageDidWriteFile, fileStorageDumpAllFiles, fileStorageReadFile, - fileStorageRenameFile, fileStorageWriteFile, } from '../fileStorage/actions'; import { @@ -63,12 +52,9 @@ import { explorerDidFailToDeleteFile, explorerDidFailToExportFile, explorerDidFailToImportFiles, - explorerDidFailToRenameFile, explorerDidImportFiles, - explorerDidRenameFile, explorerExportFile, explorerImportFiles, - explorerRenameFile, } from './actions'; import { deleteFileAlertDidAccept, @@ -80,11 +66,6 @@ import { newFileWizardDidCancel, newFileWizardShow, } from './newFileWizard/actions'; -import { - renameFileDialogDidAccept, - renameFileDialogDidCancel, - renameFileDialogShow, -} from './renameFileDialog/actions'; function* handleExplorerArchiveAllFiles(): Generator { try { @@ -265,43 +246,6 @@ function* handleExplorerActivateFile( yield* put(explorerDidActivateFile(didActivate.fileName)); } -/** Connects user initiate rename file actions to the rename file dialog. */ -function* handleExplorerRenameFile( - action: ReturnType, -): Generator { - yield* put(renameFileDialogShow(action.fileName)); - - const { accepted, canceled } = yield* race({ - accepted: take(renameFileDialogDidAccept), - canceled: take(renameFileDialogDidCancel), - }); - - if (canceled) { - yield* put(explorerDidFailToRenameFile()); - return; - } - - defined(accepted); - - yield* put(fileStorageRenameFile(action.fileName, accepted.newName)); - - const didRename = yield* race({ - succeeded: take( - fileStorageDidRenameFile.when((a) => a.fileName === action.fileName), - ), - failed: take( - fileStorageDidFailToRenameFile.when((a) => a.fileName === action.fileName), - ), - }); - - if (didRename.failed) { - yield* put(explorerDidFailToRenameFile()); - return; - } - - yield* put(explorerDidRenameFile()); -} - function* handleExplorerExportFile( action: ReturnType, ): Generator { @@ -397,10 +341,6 @@ export default function* (): Generator { yield* takeEvery(explorerImportFiles, handleExplorerImportFiles); yield* takeEvery(explorerCreateNewFile, handleExplorerCreateNewFile); yield* takeEvery(explorerActivateFile, handleExplorerActivateFile); - // takeLatest should ensure that if we trigger a new rename before the - // previous one is finished, the old one will be canceled. We don't expect - // this to happen in practice though. - yield* takeLatest(explorerRenameFile, handleExplorerRenameFile); - yield* takeLatest(explorerExportFile, handleExplorerExportFile); - yield* takeLatest(explorerDeleteFile, handleExplorerDeleteFile); + yield* takeEvery(explorerExportFile, handleExplorerExportFile); + yield* takeEvery(explorerDeleteFile, handleExplorerDeleteFile); } diff --git a/src/explorer/translations/en.json b/src/explorer/translations/en.json index c8ee59b8..84551b6d 100644 --- a/src/explorer/translations/en.json +++ b/src/explorer/translations/en.json @@ -12,7 +12,6 @@ "navigation": "Navigate the tree with the arrow keys. Start typing the name of a file to search for a file. Additional keybindings are available:", "keybindings": { "primaryAction": "{key} to open the file in the code editor", - "rename": "{key} to start renaming the focused file", "export": "{key} to export the focused file", "delete": "{key} to delete the focused file" } @@ -22,7 +21,6 @@ }, "treeItem": { "deleteTooltip": "Delete {fileName}", - "exportTooltip": "Export {fileName}", - "renameTooltip": "Rename {fileName}" + "exportTooltip": "Export {fileName}" } }