提交 b9bf66bb 编写于 作者: B Benjamin Pasero

web - limit workspace actions

上级 177b8b19
......@@ -39,8 +39,8 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { IHistoryMainService } from 'vs/platform/history/common/history';
import { URI } from 'vs/base/common/uri';
import { WorkspacesChannel } from 'vs/platform/workspaces/node/workspacesIpc';
import { IWorkspacesMainService, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { WorkspacesChannel } from 'vs/platform/workspaces/electron-main/workspacesIpc';
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { getMachineId } from 'vs/base/node/id';
import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32';
import { LinuxUpdateService } from 'vs/platform/update/electron-main/updateService.linux';
......@@ -69,7 +69,7 @@ import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainSe
import { IBackupMainService } from 'vs/platform/backup/common/backup';
import { HistoryMainService } from 'vs/platform/history/electron-main/historyMainService';
import { URLService } from 'vs/platform/url/node/urlService';
import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { WorkspacesMainService, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { statSync } from 'fs';
import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsIpc';
import { IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService';
......
......@@ -17,7 +17,8 @@ import { IWindowSettings, MenuBarVisibility, IWindowConfiguration, ReadyState, g
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { IBackupMainService } from 'vs/platform/backup/common/backup';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import * as perf from 'vs/base/common/performance';
......
......@@ -25,7 +25,7 @@ import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { IHistoryMainService, IRecent } from 'vs/platform/history/common/history';
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform';
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { Schemas } from 'vs/base/common/network';
......@@ -36,7 +36,7 @@ import { exists, dirExists } from 'vs/base/node/pfs';
import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
import { getWorkspaceIdentifier } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { once } from 'vs/base/common/functional';
import { Disposable } from 'vs/base/common/lifecycle';
......
......@@ -12,7 +12,8 @@ import { getBaseLabel, getPathLabel } from 'vs/base/common/labels';
import { IPath } from 'vs/platform/windows/common/windows';
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { IWorkspaceIdentifier, IWorkspacesMainService, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { IHistoryMainService, IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile } from 'vs/platform/history/common/history';
import { ThrottledDelayer } from 'vs/base/common/async';
import { isEqual as areResourcesEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources';
......
......@@ -12,7 +12,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { OpenContext, IWindowSettings } from 'vs/platform/windows/common/windows';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { whenDeleted } from 'vs/base/node/pfs';
import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { URI } from 'vs/base/common/uri';
import { BrowserWindow, ipcMain, Event as IpcEvent, app } from 'electron';
......
......@@ -150,7 +150,7 @@ export class BrowserStorageService extends Disposable implements IStorageService
}
async migrate(toWorkspace: IWorkspaceInitializationPayload): Promise<void> {
// TODO@ben implement storage migration in web
throw new Error('Migrating storage is currently unsupported in Web');
}
close(): void {
......
......@@ -5,7 +5,6 @@
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { localize } from 'vs/nls';
import { Event } from 'vs/base/common/event';
import { IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { URI, UriComponents } from 'vs/base/common/uri';
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
......@@ -19,9 +18,6 @@ import { toSlashes } from 'vs/base/common/extpath';
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService');
export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService');
export const WORKSPACE_EXTENSION = 'code-workspace';
export const WORKSPACE_FILTER = [{ name: localize('codeWorkspace', "Code Workspace"), extensions: [WORKSPACE_EXTENSION] }];
export const UNTITLED_WORKSPACE_NAME = 'workspace.json';
......@@ -95,23 +91,10 @@ export interface IUntitledWorkspaceInfo {
remoteAuthority?: string;
}
export interface IWorkspacesMainService extends IWorkspacesService {
_serviceBrand: undefined;
onUntitledWorkspaceDeleted: Event<IWorkspaceIdentifier>;
createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier;
resolveLocalWorkspaceSync(path: URI): IResolvedWorkspace | null;
isUntitledWorkspace(workspace: IWorkspaceIdentifier): boolean;
deleteUntitledWorkspaceSync(workspace: IWorkspaceIdentifier): void;
getUntitledWorkspacesSync(): IUntitledWorkspaceInfo[];
}
export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService');
export interface IWorkspacesService {
_serviceBrand: undefined;
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier>;
......@@ -276,4 +259,4 @@ export function useSlashForPath(storedFolders: IStoredWorkspaceFolder[]): boolea
return false;
}
return true;
}
\ No newline at end of file
}
......@@ -4,7 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkspacesMainService, IWorkspaceIdentifier, hasWorkspaceFileExtension, UNTITLED_WORKSPACE_NAME, IResolvedWorkspace, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, IUntitledWorkspaceInfo, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier, hasWorkspaceFileExtension, UNTITLED_WORKSPACE_NAME, IResolvedWorkspace, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, IUntitledWorkspaceInfo, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { join, dirname } from 'vs/base/common/path';
import { mkdirp, writeFile, rimrafSync, readdirSync, writeFileSync } from 'vs/base/node/pfs';
......@@ -18,12 +18,38 @@ import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { Disposable } from 'vs/base/common/lifecycle';
import { originalFSPath, isEqualOrParent, joinPath } from 'vs/base/common/resources';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export interface IStoredWorkspace {
folders: IStoredWorkspaceFolder[];
remoteAuthority?: string;
}
export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService');
export interface IWorkspacesMainService {
_serviceBrand: undefined;
onUntitledWorkspaceDeleted: Event<IWorkspaceIdentifier>;
createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier;
resolveLocalWorkspaceSync(path: URI): IResolvedWorkspace | null;
isUntitledWorkspace(workspace: IWorkspaceIdentifier): boolean;
deleteUntitledWorkspaceSync(workspace: IWorkspaceIdentifier): void;
getUntitledWorkspacesSync(): IUntitledWorkspaceInfo[];
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier>;
deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise<void>;
getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier>;
}
export class WorkspacesMainService extends Disposable implements IWorkspacesMainService {
_serviceBrand: undefined;
......
......@@ -5,24 +5,22 @@
import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ICommandService, ICommandHandler, CommandsRegistry } 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';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys';
import { MenuRegistry, MenuId, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { WorkbenchStateContext, SupportsWorkspacesContext } from 'vs/workbench/browser/contextkeys';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
export class OpenFileAction extends Action {
......@@ -102,7 +100,6 @@ export namespace OpenLocalFolderCommand {
}
}
export class OpenFileFolderAction extends Action {
static readonly ID = 'workbench.action.files.openFileFolder';
......@@ -134,84 +131,6 @@ export namespace OpenLocalFileFolderCommand {
}
}
export class AddRootFolderAction extends Action {
static readonly ID = 'workbench.action.addRootFolder';
static LABEL = ADD_ROOT_FOLDER_LABEL;
constructor(
id: string,
label: string,
@ICommandService private readonly commandService: ICommandService
) {
super(id, label);
}
run(): Promise<any> {
return this.commandService.executeCommand(ADD_ROOT_FOLDER_COMMAND_ID);
}
}
export class GlobalRemoveRootFolderAction extends Action {
static readonly ID = 'workbench.action.removeRootFolder';
static LABEL = nls.localize('globalRemoveFolderFromWorkspace', "Remove Folder from Workspace...");
constructor(
id: string,
label: string,
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@ICommandService private readonly commandService: ICommandService
) {
super(id, label);
}
async run(): Promise<any> {
const state = this.contextService.getWorkbenchState();
// Workspace / Folder
if (state === WorkbenchState.WORKSPACE || state === WorkbenchState.FOLDER) {
const folder = await this.commandService.executeCommand<IWorkspaceFolder>(PICK_WORKSPACE_FOLDER_COMMAND_ID);
if (folder) {
await this.workspaceEditingService.removeFolders([folder.uri]);
}
}
return true;
}
}
export class SaveWorkspaceAsAction extends Action {
static readonly ID = 'workbench.action.saveWorkspaceAs';
static LABEL = nls.localize('saveWorkspaceAsAction', "Save Workspace As...");
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService
) {
super(id, label);
}
async run(): Promise<any> {
const configPathUri = await this.workspaceEditingService.pickNewWorkspacePath();
if (configPathUri) {
switch (this.contextService.getWorkbenchState()) {
case WorkbenchState.EMPTY:
case WorkbenchState.FOLDER:
const folders = this.contextService.getWorkspace().folders.map(folder => ({ uri: folder.uri }));
return this.workspaceEditingService.createAndEnterWorkspace(folders, configPathUri);
case WorkbenchState.WORKSPACE:
return this.workspaceEditingService.saveAndEnterWorkspace(configPathUri);
}
}
}
}
export class OpenWorkspaceAction extends Action {
static readonly ID = 'workbench.action.openWorkspace';
......@@ -230,93 +149,103 @@ export class OpenWorkspaceAction extends Action {
}
}
export class CloseWorkspaceAction extends Action {
export class OpenWorkspaceConfigFileAction extends Action {
static readonly ID = 'workbench.action.closeFolder';
static LABEL = nls.localize('closeWorkspace', "Close Workspace");
static readonly ID = 'workbench.action.openWorkspaceConfigFile';
static readonly LABEL = nls.localize('openWorkspaceConfigFile', "Open Workspace Configuration File");
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IEditorService private readonly editorService: IEditorService
) {
super(id, label);
}
run(): Promise<void> {
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
this.enabled = !!this.workspaceContextService.getWorkspace().configuration;
}
return Promise.resolve(undefined);
run(): Promise<any> {
const configuration = this.workspaceContextService.getWorkspace().configuration;
if (configuration) {
return this.editorService.openEditor({ resource: configuration });
}
return this.windowService.closeWorkspace();
return Promise.resolve();
}
}
export class OpenWorkspaceConfigFileAction extends Action {
export class AddRootFolderAction extends Action {
static readonly ID = 'workbench.action.openWorkspaceConfigFile';
static readonly LABEL = nls.localize('openWorkspaceConfigFile', "Open Workspace Configuration File");
static readonly ID = 'workbench.action.addRootFolder';
static LABEL = ADD_ROOT_FOLDER_LABEL;
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IEditorService private readonly editorService: IEditorService
@ICommandService private readonly commandService: ICommandService
) {
super(id, label);
this.enabled = !!this.workspaceContextService.getWorkspace().configuration;
}
run(): Promise<any> {
const configuration = this.workspaceContextService.getWorkspace().configuration;
if (configuration) {
return this.editorService.openEditor({ resource: configuration });
}
return Promise.resolve();
return this.commandService.executeCommand(ADD_ROOT_FOLDER_COMMAND_ID);
}
}
export class DuplicateWorkspaceInNewWindowAction extends Action {
export class GlobalRemoveRootFolderAction extends Action {
static readonly ID = 'workbench.action.duplicateWorkspaceInNewWindow';
static readonly LABEL = nls.localize('duplicateWorkspaceInNewWindow', "Duplicate Workspace in New Window");
static readonly ID = 'workbench.action.removeRootFolder';
static LABEL = nls.localize('globalRemoveFolderFromWorkspace', "Remove Folder from Workspace...");
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
@IWindowService private readonly windowService: IWindowService,
@IWorkspacesService private readonly workspacesService: IWorkspacesService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@ICommandService private readonly commandService: ICommandService
) {
super(id, label);
}
async run(): Promise<any> {
const folders = this.workspaceContextService.getWorkspace().folders;
const remoteAuthority = this.environmentService.configuration.remoteAuthority;
const state = this.contextService.getWorkbenchState();
const newWorkspace = await this.workspacesService.createUntitledWorkspace(folders, remoteAuthority);
await this.workspaceEditingService.copyWorkspaceSettings(newWorkspace);
// Workspace / Folder
if (state === WorkbenchState.WORKSPACE || state === WorkbenchState.FOLDER) {
const folder = await this.commandService.executeCommand<IWorkspaceFolder>(PICK_WORKSPACE_FOLDER_COMMAND_ID);
if (folder) {
await this.workspaceEditingService.removeFolders([folder.uri]);
}
}
return this.windowService.openWindow([{ workspaceUri: newWorkspace.configPath }], { forceNewWindow: true });
return true;
}
}
// --- Menu Registration
// --- Actions Registration
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
const workspacesCategory = nls.localize('workspaces', "Workspaces");
registry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory, SupportsWorkspacesContext);
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory, SupportsWorkspacesContext);
// --- Menu Registration
CommandsRegistry.registerCommand(OpenWorkspaceConfigFileAction.ID, serviceAccessor => {
serviceAccessor.get(IInstantiationService).createInstance(OpenWorkspaceConfigFileAction, OpenWorkspaceConfigFileAction.ID, OpenWorkspaceConfigFileAction.LABEL).run();
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '3_workspace',
command: {
id: ADD_ROOT_FOLDER_COMMAND_ID,
title: nls.localize({ key: 'miAddFolderToWorkspace', comment: ['&& denotes a mnemonic'] }, "A&&dd Folder to Workspace...")
},
order: 1,
when: SupportsWorkspacesContext
});
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: OpenWorkspaceConfigFileAction.ID,
......
......@@ -141,8 +141,10 @@ export class WorkbenchContextKeysHandler extends Disposable {
// Development
IsDevelopmentContext.bindTo(this.contextKeyService).set(!this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment);
// File Pickers
SupportsWorkspacesContext.bindTo(this.contextKeyService);
// Workspaces Support
// - web: only if already in workspace state
// - desktop: always
SupportsWorkspacesContext.bindTo(this.contextKeyService).set(isWeb ? this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE : true);
// Editors
this.activeEditorContext = ActiveEditorContext.bindTo(this.contextKeyService);
......
......@@ -11,7 +11,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { Disposable } from 'vs/base/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IWindowService, INativeOpenDialogOptions, IEnterWorkspaceResult, IURIToOpen, IMessageBoxResult, IWindowsService, IOpenSettings, IWindowSettings } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened, IRecent, isRecentFile, isRecentFolder } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
......@@ -609,28 +609,3 @@ export class SimpleWindowsService implements IWindowsService {
registerSingleton(IWindowsService, SimpleWindowsService);
//#endregion
//#region Workspaces
export class SimpleWorkspacesService implements IWorkspacesService {
_serviceBrand: undefined;
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
// @ts-ignore
return Promise.resolve(undefined);
}
deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise<void> {
return Promise.resolve(undefined);
}
getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier> {
// @ts-ignore
return Promise.resolve(undefined);
}
}
registerSingleton(IWorkspacesService, SimpleWorkspacesService);
//#endregion
......@@ -47,7 +47,7 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleAutoSaveAction,
const workspacesCategory = nls.localize('workspaces', "Workspaces");
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory, SupportsWorkspacesContext);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory);
// Commands
CommandsRegistry.registerCommand('_files.windowOpen', openWindowCommand);
......@@ -520,7 +520,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
id: REMOVE_ROOT_FOLDER_COMMAND_ID,
title: REMOVE_ROOT_FOLDER_LABEL
},
when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext)
when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext, SupportsWorkspacesContext)
});
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
......@@ -640,8 +640,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
id: OpenWorkspaceAction.ID,
title: nls.localize({ key: 'miOpenWorkspace', comment: ['&& denotes a mnemonic'] }, "Open Wor&&kspace...")
},
order: 3,
when: SupportsWorkspacesContext
order: 3
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......
/*---------------------------------------------------------------------------------------------
* 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 { IWindowService } from 'vs/platform/windows/common/windows';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { INotificationService } from 'vs/platform/notification/common/notification';
export class SaveWorkspaceAsAction extends Action {
static readonly ID = 'workbench.action.saveWorkspaceAs';
static LABEL = nls.localize('saveWorkspaceAsAction', "Save Workspace As...");
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService
) {
super(id, label);
}
async run(): Promise<any> {
const configPathUri = await this.workspaceEditingService.pickNewWorkspacePath();
if (configPathUri) {
switch (this.contextService.getWorkbenchState()) {
case WorkbenchState.EMPTY:
case WorkbenchState.FOLDER:
const folders = this.contextService.getWorkspace().folders.map(folder => ({ uri: folder.uri }));
return this.workspaceEditingService.createAndEnterWorkspace(folders, configPathUri);
case WorkbenchState.WORKSPACE:
return this.workspaceEditingService.saveAndEnterWorkspace(configPathUri);
}
}
}
}
export class DuplicateWorkspaceInNewWindowAction extends Action {
static readonly ID = 'workbench.action.duplicateWorkspaceInNewWindow';
static readonly LABEL = nls.localize('duplicateWorkspaceInNewWindow', "Duplicate Workspace in New Window");
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IWorkspaceEditingService private readonly workspaceEditingService: IWorkspaceEditingService,
@IWindowService private readonly windowService: IWindowService,
@IWorkspacesService private readonly workspacesService: IWorkspacesService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
) {
super(id, label);
}
async run(): Promise<any> {
const folders = this.workspaceContextService.getWorkspace().folders;
const remoteAuthority = this.environmentService.configuration.remoteAuthority;
const newWorkspace = await this.workspacesService.createUntitledWorkspace(folders, remoteAuthority);
await this.workspaceEditingService.copyWorkspaceSettings(newWorkspace);
return this.windowService.openWindow([{ workspaceUri: newWorkspace.configPath }], { forceNewWindow: true });
}
}
export class CloseWorkspaceAction extends Action {
static readonly ID = 'workbench.action.closeFolder';
static LABEL = nls.localize('closeWorkspace', "Close Workspace");
constructor(
id: string,
label: string,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService
) {
super(id, label);
}
run(): Promise<void> {
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
return Promise.resolve(undefined);
}
return this.windowService.closeWorkspace();
}
}
......@@ -13,12 +13,11 @@ import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
import { ToggleSharedProcessAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, SaveWorkspaceAsAction, DuplicateWorkspaceInNewWindowAction, CloseWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { SaveWorkspaceAsAction, DuplicateWorkspaceInNewWindowAction, CloseWorkspaceAction } from 'vs/workbench/electron-browser/actions/workspaceActions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { 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 } from 'vs/workbench/browser/contextkeys';
import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
......@@ -31,7 +30,7 @@ import { IWindowService, IWindowsService } from 'vs/platform/windows/common/wind
(function registerFileActions(): void {
const fileCategory = nls.localize('file', "File");
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory, SupportsWorkspacesContext);
})();
// Actions: View
......@@ -78,10 +77,8 @@ import { IWindowService, IWindowsService } from 'vs/platform/windows/common/wind
(function registerWorkspaceActions(): void {
const workspacesCategory = nls.localize('workspaces', "Workspaces");
registry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory, SupportsWorkspacesContext);
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory, SupportsWorkspacesContext);
registry.registerWorkbenchAction(new SyncActionDescriptor(DuplicateWorkspaceInNewWindowAction, DuplicateWorkspaceInNewWindowAction.ID, DuplicateWorkspaceInNewWindowAction.LABEL), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(DuplicateWorkspaceInNewWindowAction, DuplicateWorkspaceInNewWindowAction.ID, DuplicateWorkspaceInNewWindowAction.LABEL), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory, SupportsWorkspacesContext);
})();
// Actions: macOS Native Tabs
......@@ -133,16 +130,6 @@ import { IWindowService, IWindowsService } from 'vs/platform/windows/common/wind
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '3_workspace',
command: {
id: ADD_ROOT_FOLDER_COMMAND_ID,
title: nls.localize({ key: 'miAddFolderToWorkspace', comment: ['&& denotes a mnemonic'] }, "A&&dd Folder to Workspace...")
},
order: 1,
when: SupportsWorkspacesContext
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '3_workspace',
command: {
......@@ -171,7 +158,7 @@ import { IWindowService, IWindowsService } from 'vs/platform/windows/common/wind
title: nls.localize({ key: 'miCloseWorkspace', comment: ['&& denotes a mnemonic'] }, "Close &&Workspace")
},
order: 3,
when: WorkbenchStateContext.isEqualTo('workspace')
when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), SupportsWorkspacesContext)
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkspacesService, IWorkspaceFolderCreationData, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
export class WorkspacesService implements IWorkspacesService {
_serviceBrand: undefined;
async createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
throw new Error('Untitled workspaces are currently unsupported in Web');
}
async deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise<void> {
throw new Error('Untitled workspaces are currently unsupported in Web');
}
async getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier> {
throw new Error('Untitled workspaces are currently unsupported in Web');
}
}
registerSingleton(IWorkspacesService, WorkspacesService, true);
......@@ -7,6 +7,7 @@ import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IWorkspacesService, IWorkspaceIdentifier, IWorkspaceFolderCreationData, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { URI } from 'vs/base/common/uri';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
export class WorkspacesService implements IWorkspacesService {
......@@ -30,3 +31,5 @@ export class WorkspacesService implements IWorkspacesService {
return this.channel.call('getWorkspaceIdentifier', configPath).then(reviveWorkspaceIdentifier);
}
}
registerSingleton(IWorkspacesService, WorkspacesService, true);
......@@ -48,6 +48,7 @@ import 'vs/workbench/services/remote/node/tunnelService';
import 'vs/workbench/services/backup/node/backupFileService';
import 'vs/workbench/services/credentials/node/credentialsService';
import 'vs/workbench/services/url/electron-browser/urlService';
import 'vs/workbench/services/workspace/electron-browser/workspacesService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
......@@ -65,8 +66,6 @@ import { IUpdateService } from 'vs/platform/update/common/update';
import { UpdateService } from 'vs/platform/update/electron-browser/updateService';
import { IIssueService } from 'vs/platform/issue/node/issue';
import { IssueService } from 'vs/platform/issue/electron-browser/issueService';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { WorkspacesService } from 'vs/platform/workspaces/electron-browser/workspacesService';
import { IMenubarService } from 'vs/platform/menubar/node/menubar';
import { MenubarService } from 'vs/platform/menubar/electron-browser/menubarService';
......@@ -78,7 +77,6 @@ registerSingleton(ISharedProcessService, SharedProcessService, true);
registerSingleton(IWindowsService, WindowsService);
registerSingleton(IUpdateService, UpdateService);
registerSingleton(IIssueService, IssueService);
registerSingleton(IWorkspacesService, WorkspacesService);
registerSingleton(IMenubarService, MenubarService);
//#endregion
......
......@@ -40,6 +40,7 @@ import 'vs/workbench/services/credentials/browser/credentialsService';
import 'vs/workbench/services/url/browser/urlService';
import 'vs/workbench/services/update/browser/updateService';
import 'vs/workbench/contrib/stats/browser/workspaceStatsService';
import 'vs/workbench/services/workspace/browser/workspacesService';
import 'vs/workbench/browser/web.simpleservices';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册