Skip to content

Commit

Permalink
Open/Save local commands should only be contributed in remote
Browse files Browse the repository at this point in the history
Fixes #75737
  • Loading branch information
alexr00 committed Jun 24, 2019
1 parent b40dbda commit f3c3d0a
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 101 deletions.
82 changes: 0 additions & 82 deletions src/vs/workbench/browser/actions/workspaceActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Schemas } from 'vs/base/common/network';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { toResource } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';

export class OpenFileAction extends Action {

Expand All @@ -39,47 +35,6 @@ export class OpenFileAction extends Action {
}
}

export class OpenLocalFileAction extends Action {

static readonly ID = 'workbench.action.files.openLocalFile';
static LABEL = nls.localize('openLocalFile', "Open Local File...");

constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}

run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFileAndOpen({ forceNewWindow: false, telemetryExtraData: data, availableFileSystems: [Schemas.file] });
}
}

export class SaveLocalFileAction extends Action {

static readonly ID = 'workbench.action.files.saveLocalFile';
static LABEL = nls.localize('saveLocalFile', "Save Local File...");

constructor(
id: string,
label: string,
@ITextFileService private readonly textFileService: ITextFileService,
@IEditorService private readonly editorService: IEditorService
) {
super(id, label);
}

async run(event?: any, data?: ITelemetryData): Promise<any> {
let resource: URI | undefined = toResource(this.editorService.activeEditor);
const options: ISaveOptions = { force: true, availableFileSystems: [Schemas.file] };
if (resource) {
return this.textFileService.saveAs(resource, undefined, options);
}
}
}

export class OpenFolderAction extends Action {

static readonly ID = 'workbench.action.files.openFolder';
Expand All @@ -98,25 +53,6 @@ export class OpenFolderAction extends Action {
}
}

export class OpenLocalFolderAction extends Action {

static readonly ID = 'workbench.action.files.openLocalFolder';
static LABEL = nls.localize('openLocalFolder', "Open Local Folder...");

constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}

run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data, availableFileSystems: [Schemas.file] });
}
}


export class OpenFileFolderAction extends Action {

static readonly ID = 'workbench.action.files.openFileFolder';
Expand All @@ -135,24 +71,6 @@ export class OpenFileFolderAction extends Action {
}
}

export class OpenLocalFileFolderAction extends Action {

static readonly ID = 'workbench.action.files.openLocalFileFolder';
static LABEL = nls.localize('openLocalFileFolder', "Open Local...");

constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}

run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFileFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data, availableFileSystems: [Schemas.file] });
}
}

export class AddRootFolderAction extends Action {

static readonly ID = 'workbench.action.addRootFolder';
Expand Down
2 changes: 0 additions & 2 deletions src/vs/workbench/browser/contextkeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ export const WorkbenchStateContext = new RawContextKey<string>('workbenchState',

export const WorkspaceFolderCountContext = new RawContextKey<number>('workspaceFolderCount', 0);

export const RemoteFileDialogContext = new RawContextKey<boolean>('remoteFileDialogVisible', false);

export const IsFullscreenContext = new RawContextKey<boolean>('isFullscreen', false);

export class WorkbenchContextKeysHandler extends Disposable {
Expand Down
91 changes: 91 additions & 0 deletions src/vs/workbench/common/actions/workspaceActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { Schemas } from 'vs/base/common/network';
import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { toResource } from 'vs/workbench/common/editor';
import { URI } from 'vs/base/common/uri';

export class OpenLocalFileAction extends Action {

static readonly ID = 'workbench.action.files.openLocalFile';
static LABEL = nls.localize('openLocalFile', "Open Local File...");

constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}

run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFileAndOpen({ forceNewWindow: false, telemetryExtraData: data, availableFileSystems: [Schemas.file] });
}
}

export class SaveLocalFileAction extends Action {

static readonly ID = 'workbench.action.files.saveLocalFile';
static LABEL = nls.localize('saveLocalFile', "Save Local File...");

constructor(
id: string,
label: string,
@ITextFileService private readonly textFileService: ITextFileService,
@IEditorService private readonly editorService: IEditorService
) {
super(id, label);
}

async run(event?: any, data?: ITelemetryData): Promise<any> {
let resource: URI | undefined = toResource(this.editorService.activeEditor);
const options: ISaveOptions = { force: true, availableFileSystems: [Schemas.file] };
if (resource) {
return this.textFileService.saveAs(resource, undefined, options);
}
}
}

export class OpenLocalFolderAction extends Action {

static readonly ID = 'workbench.action.files.openLocalFolder';
static LABEL = nls.localize('openLocalFolder', "Open Local Folder...");

constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}

run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data, availableFileSystems: [Schemas.file] });
}
}

export class OpenLocalFileFolderAction extends Action {

static readonly ID = 'workbench.action.files.openLocalFileFolder';
static LABEL = nls.localize('openLocalFileFolder', "Open Local...");

constructor(
id: string,
label: string,
@IFileDialogService private readonly dialogService: IFileDialogService
) {
super(id, label);
}

run(event?: any, data?: ITelemetryData): Promise<any> {
return this.dialogService.pickFileFolderAndOpen({ forceNewWindow: false, telemetryExtraData: data, availableFileSystems: [Schemas.file] });
}
}
8 changes: 8 additions & 0 deletions src/vs/workbench/common/contextkeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';

export const RemoteFileDialogContext = new RawContextKey<boolean>('remoteFileDialogVisible', false);
13 changes: 3 additions & 10 deletions src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { openWindowCommand, REVEAL_IN_OS_COMMAND_ID, COPY_PATH_COMMAND_ID, REVEA
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { isWindows, isMacintosh, isWeb } from 'vs/base/common/platform';
import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { FilesExplorerFocusCondition, ExplorerRootContext, ExplorerFolderContext, ExplorerResourceNotReadonlyContext, ExplorerResourceCut, IExplorerService, ExplorerResourceMoveableToTrash } from 'vs/workbench/contrib/files/common/files';
import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL } from 'vs/workbench/browser/actions/workspaceCommands';
import { CLOSE_SAVED_EDITORS_COMMAND_ID, CLOSE_EDITORS_IN_GROUP_COMMAND_ID, CLOSE_EDITOR_COMMAND_ID, CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands';
Expand All @@ -23,9 +23,9 @@ import { ResourceContextKey } from 'vs/workbench/common/resources';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { SupportsWorkspacesContext, IsWebContext, RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
import { SupportsWorkspacesContext, IsWebContext } from 'vs/workbench/browser/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { OpenFileFolderAction, OpenLocalFileFolderAction, OpenFileAction, OpenFolderAction, OpenLocalFileAction, OpenLocalFolderAction, OpenWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { OpenFileFolderAction, OpenFileAction, OpenFolderAction, OpenWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';

// Contribute Global Actions
const category = { value: nls.localize('filesCategory', "File"), original: 'File' };
Expand All @@ -47,16 +47,9 @@ const fileCategory = nls.localize('file', "File");

if (isMacintosh) {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenFileFolderAction, OpenFileFolderAction.ID, OpenFileFolderAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }), 'File: Open...', fileCategory);
if (!isWeb) {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFileFolderAction, OpenLocalFileFolderAction.ID, OpenLocalFileFolderAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }, RemoteFileDialogContext), 'File: Open Local...', fileCategory);
}
} else {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenFileAction, OpenFileAction.ID, OpenFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }), 'File: Open File...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenFolderAction, OpenFolderAction.ID, OpenFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }), 'File: Open Folder...', fileCategory);
if (!isWeb) {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFileAction, OpenLocalFileAction.ID, OpenLocalFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }, RemoteFileDialogContext), 'File: Open Local File...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFolderAction, OpenLocalFolderAction.ID, OpenLocalFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }, RemoteFileDialogContext), 'File: Open Local Folder...', fileCategory);
}
}

const workspacesCategory = nls.localize('workspaces', "Workspaces");
Expand Down
5 changes: 2 additions & 3 deletions src/vs/workbench/electron-browser/main.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenTwitterUrlAction, OpenRequestFeatureUrlAction, OpenPrivacyStatementUrlAction, OpenLicenseUrlAction, OpenNewsletterSignupUrlAction } from 'vs/workbench/electron-browser/actions/helpActions';
import { ToggleSharedProcessAction, InspectContextKeysAction, ToggleScreencastModeAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
import { ShowAboutDialogAction, ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, OpenRecentAction, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ReloadWindowAction, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, CloseWorkspaceAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, CloseWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ADD_ROOT_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
import { SupportsWorkspacesContext, IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext, WorkbenchStateContext, WorkspaceFolderCountContext, RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
import { SupportsWorkspacesContext, IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext, WorkbenchStateContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import { LogStorageAction } from 'vs/platform/storage/node/storageService';
Expand All @@ -35,7 +35,6 @@ import product from 'vs/platform/product/node/product';
(function registerFileActions(): void {
const fileCategory = nls.localize('file', "File");

registry.registerWorkbenchAction(new SyncActionDescriptor(SaveLocalFileAction, SaveLocalFileAction.ID, SaveLocalFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S }, RemoteFileDialogContext), 'File: Save Local File...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory);
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/electron-browser/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class CodeRendererMain extends Disposable {
serviceCollection.set(IRemoteAgentService, remoteAgentService);

// Files
const fileService = this._register(new FileService(logService));
const fileService = this._register(new FileService(logService, remoteAgentService));
serviceCollection.set(IFileService, fileService);

const diskFileSystemProvider = this._register(new DiskFileSystemProvider(logService));
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings';
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction, SaveLocalFileAction } from 'vs/workbench/common/actions/workspaceActions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
import { isValidBasename } from 'vs/base/common/extpath';
import { RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys';
import { RemoteFileDialogContext } from 'vs/workbench/common/contextkeys';
import { Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';

Expand Down
27 changes: 26 additions & 1 deletion src/vs/workbench/services/files/common/fileService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,40 @@ import { VSBuffer, VSBufferReadable, readableToBuffer, bufferToReadable, streamT
import { Queue } from 'vs/base/common/async';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { Schemas } from 'vs/base/common/network';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { isWeb, isMacintosh } from 'vs/base/common/platform';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
import { RemoteFileDialogContext } from 'vs/workbench/common/contextkeys';
import { SaveLocalFileAction, OpenLocalFileFolderAction, OpenLocalFileAction, OpenLocalFolderAction } from 'vs/workbench/common/actions/workspaceActions';

export class FileService extends Disposable implements IFileService {

_serviceBrand: ServiceIdentifier<any>;

private readonly BUFFER_SIZE = 64 * 1024;

constructor(@ILogService private logService: ILogService) {
constructor(
@ILogService private logService: ILogService,
@IRemoteAgentService remoteAgentService?: IRemoteAgentService) {
super();
if (!isWeb && remoteAgentService) {
const connection = remoteAgentService.getConnection();
if (connection && connection.remoteAuthority) {
const fileCategory = localize('file', "File");
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(SaveLocalFileAction, SaveLocalFileAction.ID, SaveLocalFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S }, RemoteFileDialogContext), 'File: Save Local File...', fileCategory);

if (isMacintosh) {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFileFolderAction, OpenLocalFileFolderAction.ID, OpenLocalFileFolderAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }, RemoteFileDialogContext), 'File: Open Local...', fileCategory);
} else {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFileAction, OpenLocalFileAction.ID, OpenLocalFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_O }, RemoteFileDialogContext), 'File: Open Local File...', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFolderAction, OpenLocalFolderAction.ID, OpenLocalFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }, RemoteFileDialogContext), 'File: Open Local Folder...', fileCategory);
}
}
}
}

//#region File System Provider
Expand Down

0 comments on commit f3c3d0a

Please sign in to comment.