diff --git a/CHANGELOG.md b/CHANGELOG.md index e056cf55d72c7..e0464ffd25b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - [core] `ContextKeyService` is now an interface. Extenders should extend `ContextKeyServiceDummyImpl` [#10546](https://github.com/eclipse-theia/theia/pull/10546) - [plugin] Removed deprecated fields `id` and `label` from `theia.Command` [#10512](https://github.com/eclipse-theia/theia/pull/10512) - [plugin-ext] `ViewContextKeyService#with` method removed. Use `ContextKeyService#with` instead. `PluginViewWidget` and `PluginTreeWidget` inject the `ContextKeyService` rather than `ViewContextKeyService`. [#10546](https://github.com/eclipse-theia/theia/pull/10546) +- [navigator] added `Open Containing Folder` command [#10523](https://github.com/eclipse-theia/theia/pull/10523) ## v1.21.0 - 12/16/2021 diff --git a/packages/navigator/package.json b/packages/navigator/package.json index 2a934559112de..3e24438425c9e 100644 --- a/packages/navigator/package.json +++ b/packages/navigator/package.json @@ -14,6 +14,9 @@ "theiaExtensions": [ { "frontend": "lib/browser/navigator-frontend-module" + }, + { + "frontendElectron": "lib/electron-browser/electron-navigator-module" } ], "keywords": [ diff --git a/packages/navigator/src/electron-browser/electron-navigator-menu-contribution.ts b/packages/navigator/src/electron-browser/electron-navigator-menu-contribution.ts new file mode 100644 index 0000000000000..6fb0eb1c9db23 --- /dev/null +++ b/packages/navigator/src/electron-browser/electron-navigator-menu-contribution.ts @@ -0,0 +1,80 @@ +/******************************************************************************** + * Copyright (C) 2021 EclipseSource and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { Command, CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry } from '@theia/core'; +import { CommonCommands, KeybindingContribution, KeybindingRegistry } from '@theia/core/lib/browser'; +import { WidgetManager } from '@theia/core/lib/browser/widget-manager'; +import * as electron from '@theia/core/shared/electron'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { FileStatNode } from '@theia/filesystem/lib/browser'; +import { FileNavigatorWidget, FILE_NAVIGATOR_ID } from '../browser'; +import { NavigatorContextMenu } from '../browser/navigator-contribution'; +import { isWindows, isOSX } from '@theia/core/lib/common/os'; + +export const OPEN_CONTAINING_FOLDER = Command.toDefaultLocalizedCommand({ + id: 'revealFileInOS', + category: CommonCommands.FILE_CATEGORY, + label: isWindows ? 'Reveal in File Explorer' : + isOSX ? 'Reveal in Finder' : + /* linux */ 'Open Containing Folder' +}); + +@injectable() +export class ElectronNavigatorMenuContribution implements MenuContribution, CommandContribution, KeybindingContribution { + + @inject(WidgetManager) + protected readonly widgetManager: WidgetManager; + + registerCommands(commands: CommandRegistry): void { + commands.registerCommand(OPEN_CONTAINING_FOLDER, { + isEnabled: () => this.getSelectedFileStatNodes().length > 0, + isVisible: () => this.getSelectedFileStatNodes().length > 0, + execute: () => { + // workaround for https://github.com/electron/electron/issues/4349: + // use electron.remote.shell to open the window in the foreground on Windows + const shell = electron.remote?.shell ?? electron.shell; + this.getSelectedFileStatNodes().forEach(node => { + shell.showItemInFolder(node.uri['codeUri'].fsPath); + }); + } + }); + } + + registerMenus(menus: MenuModelRegistry): void { + menus.registerMenuAction(NavigatorContextMenu.NAVIGATION, { + commandId: OPEN_CONTAINING_FOLDER.id, + label: OPEN_CONTAINING_FOLDER.label + }); + } + + registerKeybindings(keybindings: KeybindingRegistry): void { + keybindings.registerKeybinding({ + command: OPEN_CONTAINING_FOLDER.id, + keybinding: 'ctrlcmd+alt+p', + when: 'filesExplorerFocus' + }); + } + + protected getSelectedFileStatNodes(): FileStatNode[] { + const navigator = this.tryGetNavigatorWidget(); + return navigator ? navigator.model.selectedNodes.filter(FileStatNode.is) : []; + } + + tryGetNavigatorWidget(): FileNavigatorWidget | undefined { + return this.widgetManager.tryGetWidget(FILE_NAVIGATOR_ID); + } + +} diff --git a/packages/navigator/src/electron-browser/electron-navigator-module.ts b/packages/navigator/src/electron-browser/electron-navigator-module.ts new file mode 100644 index 0000000000000..a85643509df6e --- /dev/null +++ b/packages/navigator/src/electron-browser/electron-navigator-module.ts @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (C) 2021 EclipseSource and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { CommandContribution, MenuContribution } from '@theia/core'; +import { ContainerModule } from '@theia/core/shared/inversify'; +import { KeybindingContribution } from '@theia/core/lib/browser'; +import { ElectronNavigatorMenuContribution } from './electron-navigator-menu-contribution'; + +export default new ContainerModule(bind => { + bind(MenuContribution).to(ElectronNavigatorMenuContribution).inSingletonScope(); + bind(CommandContribution).to(ElectronNavigatorMenuContribution).inSingletonScope(); + bind(KeybindingContribution).to(ElectronNavigatorMenuContribution).inSingletonScope(); +});