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

Web: support for untitled workspaces (fixes #82599)

上级 030af951
{
"name": "code-oss-dev",
"version": "1.40.0",
"distro": "c4406f67d23097ea3ddc5e388290c06ad37021eb",
"distro": "6864b7d5658c713e1a5d54baefafe5ff90818aee",
"author": {
"name": "Microsoft Corporation"
},
......
......@@ -206,6 +206,8 @@ class WorkspaceProvider implements IWorkspaceProvider {
static QUERY_PARAM_FOLDER = 'folder';
static QUERY_PARAM_WORKSPACE = 'workspace';
static QUERY_PARAM_PAYLOAD = 'payload';
constructor(
public readonly workspace: IWorkspace,
public readonly payload: object
......@@ -216,6 +218,22 @@ class WorkspaceProvider implements IWorkspaceProvider {
return; // return early if workspace and environment is not changing and we are reusing window
}
const targetHref = this.createTargetUrl(workspace, options);
if (targetHref) {
if (options?.reuse) {
window.location.href = targetHref;
} else {
if (isStandalone) {
window.open(targetHref, '_blank', 'toolbar=no'); // ensures to open another 'standalone' window!
} else {
window.open(targetHref);
}
}
}
}
private createTargetUrl(workspace: IWorkspace, options?: { reuse?: boolean, payload?: object }): string | undefined {
// Empty
let targetHref: string | undefined = undefined;
if (!workspace) {
......@@ -224,30 +242,20 @@ class WorkspaceProvider implements IWorkspaceProvider {
// Folder
else if (isFolderToOpen(workspace)) {
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_FOLDER}=${workspace.folderUri.path}`;
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_FOLDER}=${encodeURIComponent(workspace.folderUri.toString())}`;
}
// Workspace
else if (isWorkspaceToOpen(workspace)) {
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_WORKSPACE}=${workspace.workspaceUri.path}`;
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_WORKSPACE}=${encodeURIComponent(workspace.workspaceUri.toString())}`;
}
// Environment
// Append payload if any
if (options?.payload) {
targetHref += `&payload=${encodeURIComponent(JSON.stringify(options.payload))}`;
targetHref += `&${WorkspaceProvider.QUERY_PARAM_PAYLOAD}=${encodeURIComponent(JSON.stringify(options.payload))}`;
}
if (targetHref) {
if (options?.reuse) {
window.location.href = targetHref;
} else {
if (isStandalone) {
window.open(targetHref, '_blank', 'toolbar=no'); // ensures to open another 'standalone' window!
} else {
window.open(targetHref);
}
}
}
return targetHref;
}
private isSame(workspaceA: IWorkspace, workspaceB: IWorkspace): boolean {
......@@ -276,32 +284,49 @@ class WorkspaceProvider implements IWorkspaceProvider {
throw new Error('Missing web configuration element');
}
const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
// Determine workspace to open
// Find workspace to open and payload
let foundWorkspace = false;
let workspace: IWorkspace;
if (options.folderUri) {
workspace = { folderUri: URI.revive(options.folderUri) };
} else if (options.workspaceUri) {
workspace = { workspaceUri: URI.revive(options.workspaceUri) };
} else {
workspace = undefined;
}
// Find payload
let payload = Object.create(null);
if (document.location.search) {
const query = document.location.search.substring(1);
const vars = query.split('&');
for (let p of vars) {
const pair = p.split('=');
if (pair.length === 2) {
const [key, value] = pair;
if (key === 'payload') {
payload = JSON.parse(decodeURIComponent(value));
break;
}
}
const query = new URL(document.location.href).searchParams;
query.forEach((value, key) => {
switch (key) {
// Folder
case WorkspaceProvider.QUERY_PARAM_FOLDER:
workspace = { folderUri: URI.parse(value) };
foundWorkspace = true;
break;
// Workspace
case WorkspaceProvider.QUERY_PARAM_WORKSPACE:
workspace = { workspaceUri: URI.parse(value) };
foundWorkspace = true;
break;
// Empty
case WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW:
workspace = undefined;
foundWorkspace = true;
break;
// Payload
case WorkspaceProvider.QUERY_PARAM_PAYLOAD:
payload = JSON.parse(value);
break;
}
});
// If no workspace is provided through the URL, check for config attribute from server
const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
if (!foundWorkspace) {
if (options.folderUri) {
workspace = { folderUri: URI.revive(options.folderUri) };
} else if (options.workspaceUri) {
workspace = { workspaceUri: URI.revive(options.workspaceUri) };
} else {
workspace = undefined;
}
}
......
......@@ -13,7 +13,7 @@ import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/c
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 { MenuRegistry, MenuId, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { WorkbenchStateContext, SupportsWorkspacesContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { WorkbenchStateContext, WorkspaceFolderCountContext } 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';
......@@ -22,6 +22,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
export class OpenFileAction extends Action {
......@@ -195,14 +196,74 @@ export class GlobalRemoveRootFolderAction extends Action {
}
}
export class SaveWorkspaceAsAction extends Action {
static readonly ID = 'workbench.action.saveWorkspaceAs';
static readonly 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,
@IHostService private readonly hostService: IHostService,
@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.hostService.openWindow([{ workspaceUri: newWorkspace.configPath }], { forceNewWindow: true });
}
}
// --- 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);
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory, SupportsWorkspacesContext);
registry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(DuplicateWorkspaceInNewWindowAction, DuplicateWorkspaceInNewWindowAction.ID, DuplicateWorkspaceInNewWindowAction.LABEL), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
// --- Menu Registration
......@@ -216,8 +277,16 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
id: ADD_ROOT_FOLDER_COMMAND_ID,
title: nls.localize({ key: 'miAddFolderToWorkspace', comment: ['&& denotes a mnemonic'] }, "A&&dd Folder to Workspace...")
},
order: 1,
when: SupportsWorkspacesContext
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '3_workspace',
command: {
id: SaveWorkspaceAsAction.ID,
title: nls.localize('miSaveWorkspaceAs', "Save Workspace As...")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
......@@ -246,5 +315,5 @@ MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
title: nls.localize({ key: 'miCloseWorkspace', comment: ['&& denotes a mnemonic'] }, "Close &&Workspace")
},
order: 3,
when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'), SupportsWorkspacesContext)
when: ContextKeyExpr.and(WorkbenchStateContext.isEqualTo('workspace'))
});
......@@ -38,8 +38,6 @@ export const RemoteConnectionState = new RawContextKey<'' | 'initializing' | 'di
export const HasMacNativeTabsContext = new RawContextKey<boolean>('hasMacNativeTabs', false);
export const SupportsWorkspacesContext = new RawContextKey<boolean>('supportsWorkspaces', true);
export const IsDevelopmentContext = new RawContextKey<boolean>('isDevelopment', false);
export const WorkbenchStateContext = new RawContextKey<string>('workbenchState', undefined);
......@@ -107,11 +105,6 @@ export class WorkbenchContextKeysHandler extends Disposable {
// Development
IsDevelopmentContext.bindTo(this.contextKeyService).set(!this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment);
// 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);
this.activeEditorIsSaveable = ActiveEditorIsSaveableContext.bindTo(this.contextKeyService);
......
......@@ -48,6 +48,7 @@ import { toLocalISOString } from 'vs/base/common/date';
import { IndexedDBLogProvider } from 'vs/workbench/services/log/browser/indexedDBLogProvider';
import { InMemoryLogProvider } from 'vs/workbench/services/log/common/inMemoryLogProvider';
import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows';
import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces';
class BrowserMain extends Disposable {
......@@ -292,7 +293,7 @@ class BrowserMain extends Disposable {
// Multi-root workspace
if (workspace && isWorkspaceToOpen(workspace)) {
return { id: hash(workspace.workspaceUri.toString()).toString(16), configPath: workspace.workspaceUri };
return getWorkspaceIdentifier(workspace.workspaceUri);
}
// Single-folder workspace
......
......@@ -23,7 +23,7 @@ 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, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { IsWebContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { OpenFileFolderAction, OpenFileAction, OpenFolderAction, OpenWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ActiveEditorIsSaveableContext } from 'vs/workbench/common/editor';
......@@ -496,7 +496,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
id: ADD_ROOT_FOLDER_COMMAND_ID,
title: ADD_ROOT_FOLDER_LABEL
},
when: ContextKeyExpr.and(ExplorerRootContext, SupportsWorkspacesContext)
when: ContextKeyExpr.and(ExplorerRootContext)
});
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
......@@ -506,7 +506,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
id: REMOVE_ROOT_FOLDER_COMMAND_ID,
title: REMOVE_ROOT_FOLDER_LABEL
},
when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext, SupportsWorkspacesContext)
when: ContextKeyExpr.and(ExplorerRootContext, ExplorerFolderContext)
});
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
......
/*---------------------------------------------------------------------------------------------
* 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 { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
export class SaveWorkspaceAsAction extends Action {
static readonly ID = 'workbench.action.saveWorkspaceAs';
static readonly 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,
@IHostService private readonly hostService: IHostService,
@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.hostService.openWindow([{ workspaceUri: newWorkspace.configPath }], { forceNewWindow: true });
}
}
......@@ -13,12 +13,11 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
import { ToggleSharedProcessAction, ToggleDevToolsAction, ConfigureRuntimeArgumentsAction } from 'vs/workbench/electron-browser/actions/developerActions';
import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
import { SaveWorkspaceAsAction, DuplicateWorkspaceInNewWindowAction } 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 { SupportsWorkspacesContext, IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext } from 'vs/workbench/browser/contextkeys';
import { IsMacContext, HasMacNativeTabsContext, IsDevelopmentContext } from 'vs/workbench/browser/contextkeys';
import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
......@@ -66,14 +65,6 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat
});
})();
// Actions: Workspaces
(function registerWorkspaceActions(): void {
const workspacesCategory = nls.localize('workspaces', "Workspaces");
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, SupportsWorkspacesContext);
})();
// Actions: macOS Native Tabs
(function registerMacOSNativeTabsActions(): void {
if (isMacintosh) {
......@@ -115,16 +106,6 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat
// Menu
(function registerMenu(): void {
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '3_workspace',
command: {
id: SaveWorkspaceAsAction.ID,
title: nls.localize('miSaveWorkspaceAs', "Save Workspace As...")
},
order: 2,
when: SupportsWorkspacesContext
});
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
group: '6_close',
command: {
......
......@@ -91,6 +91,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
this.keyboardLayoutResource = joinPath(this.userRoamingDataHome, 'keyboardLayout.json');
this.argvResource = joinPath(this.userRoamingDataHome, 'argv.json');
this.backupHome = joinPath(this.userRoamingDataHome, BACKUPS);
this.untitledWorkspacesHome = joinPath(this.userRoamingDataHome, 'Workspaces');
this.configuration.backupWorkspaceResource = joinPath(this.backupHome, options.workspaceId);
this.configuration.connectionToken = options.connectionToken || getCookieValue('vscode-tkn');
......@@ -99,8 +100,6 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
break: false
};
this.untitledWorkspacesHome = URI.from({ scheme: Schemas.untitled, path: 'Workspaces' });
// Fill in selected extra environmental properties
if (options.workspaceProvider && Array.isArray(options.workspaceProvider.payload)) {
const environment = serializableToMap(options.workspaceProvider.payload);
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { hash } from 'vs/base/common/hash';
export function getWorkspaceIdentifier(workspacePath: URI): IWorkspaceIdentifier {
return {
id: hash(workspacePath.toString()).toString(16),
configPath: workspacePath
};
}
......@@ -4,13 +4,19 @@
*--------------------------------------------------------------------------------------------*/
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkspacesService, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IEnterWorkspaceResult, IRecentlyOpened, restoreRecentlyOpened, IRecent, isRecentFile, isRecentFolder, toStoreData } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspacesService, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IEnterWorkspaceResult, IRecentlyOpened, restoreRecentlyOpened, IRecent, isRecentFile, isRecentFolder, toStoreData, IStoredWorkspaceFolder, getStoredWorkspaceFolder, WORKSPACE_EXTENSION, IStoredWorkspace } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { ILogService } from 'vs/platform/log/common/log';
import { Disposable } from 'vs/base/common/lifecycle';
import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { joinPath } from 'vs/base/common/resources';
import { VSBuffer } from 'vs/base/common/buffer';
export class BrowserWorkspacesService extends Disposable implements IWorkspacesService {
......@@ -25,6 +31,9 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS
@IStorageService private readonly storageService: IStorageService,
@IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService,
@ILogService private readonly logService: ILogService,
@IHostService private readonly hostService: IHostService,
@IFileService private readonly fileService: IFileService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
) {
super();
......@@ -113,20 +122,41 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS
//#region Workspace Management
enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | null> {
throw new Error('Untitled workspaces are currently unsupported in Web');
async enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | null> {
// Open workspace in same window
await this.hostService.openWindow([{ workspaceUri: path }], { forceReuseWindow: true });
return {
workspace: await this.getWorkspaceIdentifier(path)
};
}
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
throw new Error('Untitled workspaces are currently unsupported in Web');
async createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
const randomId = (Date.now() + Math.round(Math.random() * 1000)).toString();
const newUntitledWorkspacePath = joinPath(this.environmentService.untitledWorkspacesHome, `${randomId}.${WORKSPACE_EXTENSION}`);
// Build array of workspace folders to store
const storedWorkspaceFolder: IStoredWorkspaceFolder[] = [];
if (folders) {
for (const folder of folders) {
storedWorkspaceFolder.push(getStoredWorkspaceFolder(folder.uri, folder.name, this.environmentService.untitledWorkspacesHome));
}
}
// Store at untitled workspaces location
const storedWorkspace: IStoredWorkspace = { folders: storedWorkspaceFolder, remoteAuthority };
await this.fileService.writeFile(newUntitledWorkspacePath, VSBuffer.fromString(JSON.stringify(storedWorkspace, null, '\t')));
return this.getWorkspaceIdentifier(newUntitledWorkspacePath);
}
deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise<void> {
throw new Error('Untitled workspaces are currently unsupported in Web');
return this.fileService.del(workspace.configPath);
}
getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier> {
throw new Error('Untitled workspaces are currently unsupported in Web');
async getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier> {
return getWorkspaceIdentifier(workspacePath);
}
//#endregion
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册