diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index e6e47016671..c46f9ae8764 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -38,8 +38,8 @@ import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { URI } from 'vs/base/common/uri'; -import { WorkspacesChannel } from 'vs/platform/workspaces/electron-main/workspacesIpc'; -import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces'; +import { hasWorkspaceFileExtension, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; +import { WorkspacesService } from 'vs/platform/workspaces/electron-main/workspacesService'; 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'; @@ -457,6 +457,7 @@ export class CodeApplication extends Disposable { services.set(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv])); services.set(IElectronService, new SyncDescriptor(ElectronMainService)); + services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService)); services.set(IMenubarService, new SyncDescriptor(MenubarMainService)); const storageMainService = new StorageMainService(this.logService, this.environmentService); @@ -551,8 +552,8 @@ export class CodeApplication extends Disposable { const sharedProcessChannel = createChannelReceiver(sharedProcessMainService); electronIpcServer.registerChannel('sharedProcess', sharedProcessChannel); - const workspacesMainService = accessor.get(IWorkspacesMainService); - const workspacesChannel = new WorkspacesChannel(workspacesMainService, accessor.get(IWindowsMainService)); + const workspacesService = accessor.get(IWorkspacesService); + const workspacesChannel = createChannelReceiver(workspacesService); electronIpcServer.registerChannel('workspaces', workspacesChannel); const menubarService = accessor.get(IMenubarService); diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index edd5095c49d..4a1ee2679cf 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -25,10 +25,9 @@ import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import product from 'vs/platform/product/common/product'; import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; -import { IRecent } from 'vs/platform/workspaces/common/workspacesHistory'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; -import { IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IEnterWorkspaceResult } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IEnterWorkspaceResult, IRecent } 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'; diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 7fa032eb514..362bc9b26ae 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -14,9 +14,6 @@ import { IElectronService } from 'vs/platform/electron/node/electron'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { AddFirstParameterToFunctions } from 'vs/base/common/types'; -import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; -import { IRecentlyOpened, IRecent } from 'vs/platform/workspaces/common/workspacesHistory'; -import { URI } from 'vs/base/common/uri'; export class ElectronMainService implements AddFirstParameterToFunctions /* only methods, not events */, number /* window ID */> { @@ -25,8 +22,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions { - const window = this.windowsMainService.getWindowById(windowId); - if (window) { - return this.workspacesHistoryMainService.getRecentlyOpened(window.config.workspace, window.config.folderUri, window.config.filesToOpenOrCreate); - } - - return this.workspacesHistoryMainService.getRecentlyOpened(); - } - - async addRecentlyOpened(windowId: number, recents: IRecent[]): Promise { - return this.workspacesHistoryMainService.addRecentlyOpened(recents); - } - - async removeFromRecentlyOpened(windowId: number, paths: URI[]): Promise { - return this.workspacesHistoryMainService.removeFromRecentlyOpened(paths); - } - - async clearRecentlyOpened(windowId: number): Promise { - return this.workspacesHistoryMainService.clearRecentlyOpened(); - } - - //#endregion - //#region Debug // TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060) diff --git a/src/vs/platform/electron/node/electron.ts b/src/vs/platform/electron/node/electron.ts index 49b0134bfa4..749c3d79110 100644 --- a/src/vs/platform/electron/node/electron.ts +++ b/src/vs/platform/electron/node/electron.ts @@ -9,8 +9,6 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { IWindowOpenable, IOpenInWindowOptions, IOpenEmptyWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; -import { IRecentlyOpened, IRecent } from 'vs/platform/workspaces/common/workspacesHistory'; -import { URI } from 'vs/base/common/uri'; import { ParsedArgs } from 'vscode-minimist'; import { IProcessEnvironment } from 'vs/base/common/platform'; @@ -89,13 +87,6 @@ export interface IElectronService { // Connectivity resolveProxy(url: string): Promise; - // Workspaces History - readonly onRecentlyOpenedChange: Event; - getRecentlyOpened(): Promise; - addRecentlyOpened(recents: IRecent[]): Promise; - removeFromRecentlyOpened(paths: URI[]): Promise; - clearRecentlyOpened(): Promise; - // Debug (TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060) openExtensionDevelopmentHostWindow(args: ParsedArgs, env: IProcessEnvironment): Promise; } diff --git a/src/vs/platform/workspaces/common/workspaces.ts b/src/vs/platform/workspaces/common/workspaces.ts index 01846dbcea5..3a2793a4d1e 100644 --- a/src/vs/platform/workspaces/common/workspaces.ts +++ b/src/vs/platform/workspaces/common/workspaces.ts @@ -17,11 +17,68 @@ import { normalizeDriveLetter } from 'vs/base/common/labels'; import { toSlashes } from 'vs/base/common/extpath'; import { FormattingOptions } from 'vs/base/common/jsonFormatter'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; +import { ILogService } from 'vs/platform/log/common/log'; +import { Event as CommonEvent } from 'vs/base/common/event'; 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'; +export const IWorkspacesService = createDecorator('workspacesService'); + +export interface IWorkspacesService { + + _serviceBrand: undefined; + + readonly onRecentlyOpenedChange: CommonEvent; + + // Management + enterWorkspace(path: URI): Promise; + createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise; + deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise; + getWorkspaceIdentifier(workspacePath: URI): Promise; + + // History + addRecentlyOpened(recents: IRecent[]): Promise; + removeFromRecentlyOpened(workspaces: URI[]): Promise; + clearRecentlyOpened(): Promise; + getRecentlyOpened(): Promise; +} + +export interface IRecentlyOpened { + workspaces: Array; + files: IRecentFile[]; +} + +export type IRecent = IRecentWorkspace | IRecentFolder | IRecentFile; + +export interface IRecentWorkspace { + workspace: IWorkspaceIdentifier; + label?: string; +} + +export interface IRecentFolder { + folderUri: ISingleFolderWorkspaceIdentifier; + label?: string; +} + +export interface IRecentFile { + fileUri: URI; + label?: string; +} + +export function isRecentWorkspace(curr: IRecent): curr is IRecentWorkspace { + return curr.hasOwnProperty('workspace'); +} + +export function isRecentFolder(curr: IRecent): curr is IRecentFolder { + return curr.hasOwnProperty('folderUri'); +} + +export function isRecentFile(curr: IRecent): curr is IRecentFile { + return curr.hasOwnProperty('fileUri'); +} + /** * A single folder workspace identifier is just the path to the folder. */ @@ -96,21 +153,6 @@ export interface IEnterWorkspaceResult { backupPath?: string; } -export const IWorkspacesService = createDecorator('workspacesService'); - -export interface IWorkspacesService { - - _serviceBrand: undefined; - - enterWorkspace(path: URI): Promise; - - createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise; - - deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise; - - getWorkspaceIdentifier(workspacePath: URI): Promise; -} - export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolderWorkspaceIdentifier { return obj instanceof URI; } @@ -267,3 +309,129 @@ export function useSlashForPath(storedFolders: IStoredWorkspaceFolder[]): boolea } return true; } + +//#region Workspace Storage + +interface ISerializedRecentlyOpened { + workspaces3: Array; // workspace or URI.toString() // added in 1.32 + workspaceLabels?: Array; // added in 1.33 + files2: string[]; // files as URI.toString() // added in 1.32 + fileLabels?: Array; // added in 1.33 +} + +interface ILegacySerializedRecentlyOpened { + workspaces2: Array; // legacy, configPath as file path + workspaces: Array; // legacy (UriComponents was also supported for a few insider builds) + files: string[]; // files as paths +} + +interface ISerializedWorkspace { id: string; configURIPath: string; } +interface ILegacySerializedWorkspace { id: string; configPath: string; } + +function isLegacySerializedWorkspace(curr: any): curr is ILegacySerializedWorkspace { + return typeof curr === 'object' && typeof curr['id'] === 'string' && typeof curr['configPath'] === 'string'; +} + +function isUriComponents(curr: any): curr is UriComponents { + return curr && typeof curr['path'] === 'string' && typeof curr['scheme'] === 'string'; +} + +export type RecentlyOpenedStorageData = object; + +export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefined, logService: ILogService): IRecentlyOpened { + const result: IRecentlyOpened = { workspaces: [], files: [] }; + if (data) { + const restoreGracefully = function (entries: T[], func: (entry: T, index: number) => void) { + for (let i = 0; i < entries.length; i++) { + try { + func(entries[i], i); + } catch (e) { + logService.warn(`Error restoring recent entry ${JSON.stringify(entries[i])}: ${e.toString()}. Skip entry.`); + } + } + }; + + const storedRecents = data as ISerializedRecentlyOpened & ILegacySerializedRecentlyOpened; + if (Array.isArray(storedRecents.workspaces3)) { + restoreGracefully(storedRecents.workspaces3, (workspace, i) => { + const label: string | undefined = (Array.isArray(storedRecents.workspaceLabels) && storedRecents.workspaceLabels[i]) || undefined; + if (typeof workspace === 'object' && typeof workspace.id === 'string' && typeof workspace.configURIPath === 'string') { + result.workspaces.push({ label, workspace: { id: workspace.id, configPath: URI.parse(workspace.configURIPath) } }); + } else if (typeof workspace === 'string') { + result.workspaces.push({ label, folderUri: URI.parse(workspace) }); + } + }); + } else if (Array.isArray(storedRecents.workspaces2)) { + restoreGracefully(storedRecents.workspaces2, workspace => { + if (typeof workspace === 'object' && typeof workspace.id === 'string' && typeof workspace.configPath === 'string') { + result.workspaces.push({ workspace: { id: workspace.id, configPath: URI.file(workspace.configPath) } }); + } else if (typeof workspace === 'string') { + result.workspaces.push({ folderUri: URI.parse(workspace) }); + } + }); + } else if (Array.isArray(storedRecents.workspaces)) { + // TODO@martin legacy support can be removed at some point (6 month?) + // format of 1.25 and before + restoreGracefully(storedRecents.workspaces, workspace => { + if (typeof workspace === 'string') { + result.workspaces.push({ folderUri: URI.file(workspace) }); + } else if (isLegacySerializedWorkspace(workspace)) { + result.workspaces.push({ workspace: { id: workspace.id, configPath: URI.file(workspace.configPath) } }); + } else if (isUriComponents(workspace)) { + // added by 1.26-insiders + result.workspaces.push({ folderUri: URI.revive(workspace) }); + } + }); + } + if (Array.isArray(storedRecents.files2)) { + restoreGracefully(storedRecents.files2, (file, i) => { + const label: string | undefined = (Array.isArray(storedRecents.fileLabels) && storedRecents.fileLabels[i]) || undefined; + if (typeof file === 'string') { + result.files.push({ label, fileUri: URI.parse(file) }); + } + }); + } else if (Array.isArray(storedRecents.files)) { + restoreGracefully(storedRecents.files, file => { + if (typeof file === 'string') { + result.files.push({ fileUri: URI.file(file) }); + } + }); + } + } + + return result; +} + +export function toStoreData(recents: IRecentlyOpened): RecentlyOpenedStorageData { + const serialized: ISerializedRecentlyOpened = { workspaces3: [], files2: [] }; + + let hasLabel = false; + const workspaceLabels: (string | null)[] = []; + for (const recent of recents.workspaces) { + if (isRecentFolder(recent)) { + serialized.workspaces3.push(recent.folderUri.toString()); + } else { + serialized.workspaces3.push({ id: recent.workspace.id, configURIPath: recent.workspace.configPath.toString() }); + } + workspaceLabels.push(recent.label || null); + hasLabel = hasLabel || !!recent.label; + } + if (hasLabel) { + serialized.workspaceLabels = workspaceLabels; + } + + hasLabel = false; + const fileLabels: (string | null)[] = []; + for (const recent of recents.files) { + serialized.files2.push(recent.fileUri.toString()); + fileLabels.push(recent.label || null); + hasLabel = hasLabel || !!recent.label; + } + if (hasLabel) { + serialized.fileLabels = fileLabels; + } + + return serialized; +} + +//#endregion diff --git a/src/vs/platform/workspaces/common/workspacesHistory.ts b/src/vs/platform/workspaces/common/workspacesHistory.ts deleted file mode 100644 index e2c725ab6cb..00000000000 --- a/src/vs/platform/workspaces/common/workspacesHistory.ts +++ /dev/null @@ -1,41 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; -import { URI } from 'vs/base/common/uri'; - -export interface IRecentlyOpened { - workspaces: Array; - files: IRecentFile[]; -} - -export type IRecent = IRecentWorkspace | IRecentFolder | IRecentFile; - -export interface IRecentWorkspace { - workspace: IWorkspaceIdentifier; - label?: string; -} - -export interface IRecentFolder { - folderUri: ISingleFolderWorkspaceIdentifier; - label?: string; -} - -export interface IRecentFile { - fileUri: URI; - label?: string; -} - -export function isRecentWorkspace(curr: IRecent): curr is IRecentWorkspace { - return curr.hasOwnProperty('workspace'); -} - -export function isRecentFolder(curr: IRecent): curr is IRecentFolder { - return curr.hasOwnProperty('folderUri'); -} - -export function isRecentFile(curr: IRecent): curr is IRecentFile { - return curr.hasOwnProperty('fileUri'); -} diff --git a/src/vs/platform/workspaces/common/workspacesHistoryStorage.ts b/src/vs/platform/workspaces/common/workspacesHistoryStorage.ts deleted file mode 100644 index 5cb8920e670..00000000000 --- a/src/vs/platform/workspaces/common/workspacesHistoryStorage.ts +++ /dev/null @@ -1,129 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { UriComponents, URI } from 'vs/base/common/uri'; -import { IRecentlyOpened, isRecentFolder } from 'vs/platform/workspaces/common/workspacesHistory'; -import { ILogService } from 'vs/platform/log/common/log'; - -interface ISerializedRecentlyOpened { - workspaces3: Array; // workspace or URI.toString() // added in 1.32 - workspaceLabels?: Array; // added in 1.33 - files2: string[]; // files as URI.toString() // added in 1.32 - fileLabels?: Array; // added in 1.33 -} - -interface ILegacySerializedRecentlyOpened { - workspaces2: Array; // legacy, configPath as file path - workspaces: Array; // legacy (UriComponents was also supported for a few insider builds) - files: string[]; // files as paths -} - -interface ISerializedWorkspace { id: string; configURIPath: string; } -interface ILegacySerializedWorkspace { id: string; configPath: string; } - -function isLegacySerializedWorkspace(curr: any): curr is ILegacySerializedWorkspace { - return typeof curr === 'object' && typeof curr['id'] === 'string' && typeof curr['configPath'] === 'string'; -} - -function isUriComponents(curr: any): curr is UriComponents { - return curr && typeof curr['path'] === 'string' && typeof curr['scheme'] === 'string'; -} - -export type RecentlyOpenedStorageData = object; - -export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefined, logService: ILogService): IRecentlyOpened { - const result: IRecentlyOpened = { workspaces: [], files: [] }; - if (data) { - const restoreGracefully = function (entries: T[], func: (entry: T, index: number) => void) { - for (let i = 0; i < entries.length; i++) { - try { - func(entries[i], i); - } catch (e) { - logService.warn(`Error restoring recent entry ${JSON.stringify(entries[i])}: ${e.toString()}. Skip entry.`); - } - } - }; - - const storedRecents = data as ISerializedRecentlyOpened & ILegacySerializedRecentlyOpened; - if (Array.isArray(storedRecents.workspaces3)) { - restoreGracefully(storedRecents.workspaces3, (workspace, i) => { - const label: string | undefined = (Array.isArray(storedRecents.workspaceLabels) && storedRecents.workspaceLabels[i]) || undefined; - if (typeof workspace === 'object' && typeof workspace.id === 'string' && typeof workspace.configURIPath === 'string') { - result.workspaces.push({ label, workspace: { id: workspace.id, configPath: URI.parse(workspace.configURIPath) } }); - } else if (typeof workspace === 'string') { - result.workspaces.push({ label, folderUri: URI.parse(workspace) }); - } - }); - } else if (Array.isArray(storedRecents.workspaces2)) { - restoreGracefully(storedRecents.workspaces2, workspace => { - if (typeof workspace === 'object' && typeof workspace.id === 'string' && typeof workspace.configPath === 'string') { - result.workspaces.push({ workspace: { id: workspace.id, configPath: URI.file(workspace.configPath) } }); - } else if (typeof workspace === 'string') { - result.workspaces.push({ folderUri: URI.parse(workspace) }); - } - }); - } else if (Array.isArray(storedRecents.workspaces)) { - // TODO@martin legacy support can be removed at some point (6 month?) - // format of 1.25 and before - restoreGracefully(storedRecents.workspaces, workspace => { - if (typeof workspace === 'string') { - result.workspaces.push({ folderUri: URI.file(workspace) }); - } else if (isLegacySerializedWorkspace(workspace)) { - result.workspaces.push({ workspace: { id: workspace.id, configPath: URI.file(workspace.configPath) } }); - } else if (isUriComponents(workspace)) { - // added by 1.26-insiders - result.workspaces.push({ folderUri: URI.revive(workspace) }); - } - }); - } - if (Array.isArray(storedRecents.files2)) { - restoreGracefully(storedRecents.files2, (file, i) => { - const label: string | undefined = (Array.isArray(storedRecents.fileLabels) && storedRecents.fileLabels[i]) || undefined; - if (typeof file === 'string') { - result.files.push({ label, fileUri: URI.parse(file) }); - } - }); - } else if (Array.isArray(storedRecents.files)) { - restoreGracefully(storedRecents.files, file => { - if (typeof file === 'string') { - result.files.push({ fileUri: URI.file(file) }); - } - }); - } - } - - return result; -} - -export function toStoreData(recents: IRecentlyOpened): RecentlyOpenedStorageData { - const serialized: ISerializedRecentlyOpened = { workspaces3: [], files2: [] }; - - let hasLabel = false; - const workspaceLabels: (string | null)[] = []; - for (const recent of recents.workspaces) { - if (isRecentFolder(recent)) { - serialized.workspaces3.push(recent.folderUri.toString()); - } else { - serialized.workspaces3.push({ id: recent.workspace.id, configURIPath: recent.workspace.configPath.toString() }); - } - workspaceLabels.push(recent.label || null); - hasLabel = hasLabel || !!recent.label; - } - if (hasLabel) { - serialized.workspaceLabels = workspaceLabels; - } - - hasLabel = false; - const fileLabels: (string | null)[] = []; - for (const recent of recents.files) { - serialized.files2.push(recent.fileUri.toString()); - fileLabels.push(recent.label || null); - hasLabel = hasLabel || !!recent.label; - } - if (hasLabel) { - serialized.fileLabels = fileLabels; - } - - return serialized; -} diff --git a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts index 80208bb9e1c..56d47f09421 100644 --- a/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts +++ b/src/vs/platform/workspaces/electron-main/workspacesHistoryMainService.ts @@ -12,16 +12,14 @@ 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, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile, toStoreData, restoreRecentlyOpened, RecentlyOpenedStorageData } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; -import { IRecentlyOpened, isRecentWorkspace, isRecentFolder, IRecent, isRecentFile, IRecentFolder, IRecentWorkspace, IRecentFile } from 'vs/platform/workspaces/common/workspacesHistory'; import { ThrottledDelayer } from 'vs/base/common/async'; import { isEqual as areResourcesEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { getSimpleWorkspaceLabel } from 'vs/platform/label/common/label'; -import { toStoreData, restoreRecentlyOpened, RecentlyOpenedStorageData } from 'vs/platform/workspaces/common/workspacesHistoryStorage'; import { exists } from 'vs/base/node/pfs'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/platform/workspaces/electron-main/workspacesIpc.ts b/src/vs/platform/workspaces/electron-main/workspacesIpc.ts deleted file mode 100644 index eee7aa30655..00000000000 --- a/src/vs/platform/workspaces/electron-main/workspacesIpc.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -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'; -import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; - -export class WorkspacesChannel implements IServerChannel { - - constructor( - private workspacesMainService: IWorkspacesMainService, - private windowsMainService: IWindowsMainService - ) { } - - listen(_: unknown, event: string): Event { - throw new Error(`Event not found: ${event}`); - } - - call(_: unknown, command: string, arg?: any): Promise { - switch (command) { - case 'createUntitledWorkspace': { - const rawFolders: IWorkspaceFolderCreationData[] = arg[0]; - const remoteAuthority: string = arg[1]; - let folders: IWorkspaceFolderCreationData[] | undefined = undefined; - if (Array.isArray(rawFolders)) { - folders = rawFolders.map(rawFolder => { - return { - uri: URI.revive(rawFolder.uri), // convert raw URI back to real URI - name: rawFolder.name - }; - }); - } - - return this.workspacesMainService.createUntitledWorkspace(folders, remoteAuthority); - } - case 'deleteUntitledWorkspace': { - const identifier: IWorkspaceIdentifier = arg; - return this.workspacesMainService.deleteUntitledWorkspace({ id: identifier.id, configPath: URI.revive(identifier.configPath) }); - } - case 'getWorkspaceIdentifier': { - return this.workspacesMainService.getWorkspaceIdentifier(URI.revive(arg)); - } - case 'enterWorkspace': { - const window = this.windowsMainService.getWindowById(arg[0]); - if (window) { - return this.windowsMainService.enterWorkspace(window, URI.revive(arg[1])); - } - } - } - - throw new Error(`Call not found: ${command}`); - } -} diff --git a/src/vs/platform/workspaces/electron-main/workspacesService.ts b/src/vs/platform/workspaces/electron-main/workspacesService.ts new file mode 100644 index 00000000000..86ef92cf2b6 --- /dev/null +++ b/src/vs/platform/workspaces/electron-main/workspacesService.ts @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { AddFirstParameterToFunctions } from 'vs/base/common/types'; +import { IWorkspacesService, IEnterWorkspaceResult, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IRecentlyOpened, IRecent } from 'vs/platform/workspaces/common/workspaces'; +import { URI } from 'vs/base/common/uri'; +import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; +import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; +import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; + +export class WorkspacesService implements AddFirstParameterToFunctions /* only methods, not events */, number /* window ID */> { + + _serviceBrand: undefined; + + constructor( + @IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService, + @IWindowsMainService private readonly windowsMainService: IWindowsMainService, + @IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService + ) { + } + + //#region Workspace Management + + async enterWorkspace(windowId: number, path: URI): Promise { + const window = this.windowsMainService.getWindowById(windowId); + if (window) { + return this.windowsMainService.enterWorkspace(window, path); + } + + return undefined; + } + + createUntitledWorkspace(windowId: number, folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise { + return this.workspacesMainService.createUntitledWorkspace(folders, remoteAuthority); + } + + deleteUntitledWorkspace(windowId: number, workspace: IWorkspaceIdentifier): Promise { + return this.workspacesMainService.deleteUntitledWorkspace(workspace); + } + + getWorkspaceIdentifier(windowId: number, workspacePath: URI): Promise { + return this.workspacesMainService.getWorkspaceIdentifier(workspacePath); + } + + //#endregion + + //#region Workspaces History + + readonly onRecentlyOpenedChange = this.workspacesHistoryMainService.onRecentlyOpenedChange; + + async getRecentlyOpened(windowId: number): Promise { + const window = this.windowsMainService.getWindowById(windowId); + if (window) { + return this.workspacesHistoryMainService.getRecentlyOpened(window.config.workspace, window.config.folderUri, window.config.filesToOpenOrCreate); + } + + return this.workspacesHistoryMainService.getRecentlyOpened(); + } + + async addRecentlyOpened(windowId: number, recents: IRecent[]): Promise { + return this.workspacesHistoryMainService.addRecentlyOpened(recents); + } + + async removeFromRecentlyOpened(windowId: number, paths: URI[]): Promise { + return this.workspacesHistoryMainService.removeFromRecentlyOpened(paths); + } + + async clearRecentlyOpened(windowId: number): Promise { + return this.workspacesHistoryMainService.clearRecentlyOpened(); + } + + //#endregion +} diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesHistoryStorage.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesHistoryStorage.test.ts index c72e6c3af36..ecdc561c986 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesHistoryStorage.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesHistoryStorage.test.ts @@ -2,14 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ + import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; - -import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceIdentifier, IRecentlyOpened, isRecentFolder, IRecentFolder, IRecentWorkspace, toStoreData, restoreRecentlyOpened } from 'vs/platform/workspaces/common/workspaces'; import { URI } from 'vs/base/common/uri'; -import { IRecentlyOpened, isRecentFolder, IRecentFolder, IRecentWorkspace } from 'vs/platform/workspaces/common/workspacesHistory'; -import { toStoreData, restoreRecentlyOpened } from 'vs/platform/workspaces/common/workspacesHistoryStorage'; import { NullLogService } from 'vs/platform/log/common/log'; function toWorkspace(uri: URI): IWorkspaceIdentifier { diff --git a/src/vs/workbench/api/common/apiCommands.ts b/src/vs/workbench/api/common/apiCommands.ts index f6f6262fd89..3ea4db4364f 100644 --- a/src/vs/workbench/api/common/apiCommands.ts +++ b/src/vs/workbench/api/common/apiCommands.ts @@ -12,9 +12,7 @@ import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IOpenInWindowOptions, IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; -import { IWorkspacesService, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces'; -import { IRecent } from 'vs/platform/workspaces/common/workspacesHistory'; +import { IWorkspacesService, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces'; import { Schemas } from 'vs/base/common/network'; // ----------------------------------------------------------------- @@ -133,8 +131,8 @@ export class OpenAPICommand { CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute)); CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, uri: URI) { - const workspacesHistoryService = accessor.get(IWorkspacesHistoryService); - return workspacesHistoryService.removeFromRecentlyOpened([uri]); + const workspacesService = accessor.get(IWorkspacesService); + return workspacesService.removeFromRecentlyOpened([uri]); }); export class RemoveFromRecentlyOpenedAPICommand { @@ -164,7 +162,6 @@ interface RecentEntry { } CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async function (accessor: ServicesAccessor, recentEntry: RecentEntry) { - const workspacesHistoryService = accessor.get(IWorkspacesHistoryService); const workspacesService = accessor.get(IWorkspacesService); let recent: IRecent | undefined = undefined; const uri = recentEntry.uri; @@ -177,12 +174,12 @@ CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async functio } else { recent = { fileUri: uri, label }; } - return workspacesHistoryService.addRecentlyOpened([recent]); + return workspacesService.addRecentlyOpened([recent]); }); CommandsRegistry.registerCommand('_workbench.getRecentlyOpened', async function (accessor: ServicesAccessor) { - const workspacesHistoryService = accessor.get(IWorkspacesHistoryService); - return workspacesHistoryService.getRecentlyOpened(); + const workspacesService = accessor.get(IWorkspacesService); + return workspacesService.getRecentlyOpened(); }); export class SetEditorLayoutAPICommand { diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index 93c49e2338d..af1e57bc60a 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -8,7 +8,6 @@ import 'vs/css!./media/actions'; import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -22,7 +21,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; -import { IRecentWorkspace, IRecentFolder, IRecentFile, IRecent, isRecentFolder, isRecentWorkspace } from 'vs/platform/workspaces/common/workspacesHistory'; +import { IRecentWorkspace, IRecentFolder, IRecentFile, IRecent, isRecentFolder, isRecentWorkspace, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { URI } from 'vs/base/common/uri'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { FileKind } from 'vs/platform/files/common/files'; @@ -45,7 +44,7 @@ abstract class BaseOpenRecentAction extends Action { constructor( id: string, label: string, - private workspacesHistoryService: IWorkspacesHistoryService, + private workspacesService: IWorkspacesService, private quickInputService: IQuickInputService, private contextService: IWorkspaceContextService, private labelService: ILabelService, @@ -60,7 +59,7 @@ abstract class BaseOpenRecentAction extends Action { protected abstract isQuickNavigate(): boolean; async run(): Promise { - const { workspaces, files } = await this.workspacesHistoryService.getRecentlyOpened(); + const { workspaces, files } = await this.workspacesService.getRecentlyOpened(); this.openRecent(workspaces, files); } @@ -130,7 +129,7 @@ abstract class BaseOpenRecentAction extends Action { onKeyMods: mods => keyMods = mods, quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined, onDidTriggerItemButton: async context => { - await this.workspacesHistoryService.removeFromRecentlyOpened([context.item.resource]); + await this.workspacesService.removeFromRecentlyOpened([context.item.resource]); context.removeItem(); } }); @@ -149,7 +148,7 @@ export class OpenRecentAction extends BaseOpenRecentAction { constructor( id: string, label: string, - @IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService workspacesService: IWorkspacesService, @IQuickInputService quickInputService: IQuickInputService, @IWorkspaceContextService contextService: IWorkspaceContextService, @IKeybindingService keybindingService: IKeybindingService, @@ -158,7 +157,7 @@ export class OpenRecentAction extends BaseOpenRecentAction { @ILabelService labelService: ILabelService, @IHostService hostService: IHostService ) { - super(id, label, workspacesHistoryService, quickInputService, contextService, labelService, keybindingService, modelService, modeService, hostService); + super(id, label, workspacesService, quickInputService, contextService, labelService, keybindingService, modelService, modeService, hostService); } protected isQuickNavigate(): boolean { @@ -174,7 +173,7 @@ class QuickOpenRecentAction extends BaseOpenRecentAction { constructor( id: string, label: string, - @IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService workspacesService: IWorkspacesService, @IQuickInputService quickInputService: IQuickInputService, @IWorkspaceContextService contextService: IWorkspaceContextService, @IKeybindingService keybindingService: IKeybindingService, @@ -183,7 +182,7 @@ class QuickOpenRecentAction extends BaseOpenRecentAction { @ILabelService labelService: ILabelService, @IHostService hostService: IHostService ) { - super(id, label, workspacesHistoryService, quickInputService, contextService, labelService, keybindingService, modelService, modeService, hostService); + super(id, label, workspacesService, quickInputService, contextService, labelService, keybindingService, modelService, modeService, hostService); } protected isQuickNavigate(): boolean { diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 6d7633b28e1..9d29e798442 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -3,12 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { hasWorkspaceFileExtension, IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; +import { hasWorkspaceFileExtension, IWorkspaceFolderCreationData, IRecentFile, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { normalize } from 'vs/base/common/path'; import { basename } from 'vs/base/common/resources'; import { IFileService } from 'vs/platform/files/common/files'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { URI } from 'vs/base/common/uri'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; @@ -29,7 +28,6 @@ import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/co import { Disposable } from 'vs/base/common/lifecycle'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { IRecentFile } from 'vs/platform/workspaces/common/workspacesHistory'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -162,7 +160,7 @@ export class ResourcesDropHandler { constructor( private options: IResourcesDropHandlerOptions, @IFileService private readonly fileService: IFileService, - @IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService private readonly workspacesService: IWorkspacesService, @ITextFileService private readonly textFileService: ITextFileService, @IBackupFileService private readonly backupFileService: IBackupFileService, @IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService, @@ -192,7 +190,7 @@ export class ResourcesDropHandler { // Add external ones to recently open list unless dropped resource is a workspace const recentFiles: IRecentFile[] = untitledOrFileResources.filter(d => d.isExternal && d.resource.scheme === Schemas.file).map(d => ({ fileUri: d.resource })); if (recentFiles.length) { - this.workspacesHistoryService.addRecentlyOpened(recentFiles); + this.workspacesService.addRecentlyOpened(recentFiles); } const editors: IResourceEditor[] = untitledOrFileResources.map(untitledOrFileResource => ({ diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 9d716c02b51..0aa5e53d0eb 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -16,12 +16,12 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { CLOSE_EDITOR_COMMAND_ID, NAVIGATE_ALL_EDITORS_GROUP_PREFIX, MOVE_ACTIVE_EDITOR_COMMAND_ID, NAVIGATE_IN_ACTIVE_GROUP_PREFIX, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups } from 'vs/workbench/browser/parts/editor/editorCommands'; import { IEditorGroupsService, IEditorGroup, GroupsArrangement, EditorsOrder, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; export class ExecuteCommandAction extends Action { @@ -1218,7 +1218,7 @@ export class ClearRecentFilesAction extends Action { constructor( id: string, label: string, - @IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService private readonly workspacesService: IWorkspacesService, @IHistoryService private readonly historyService: IHistoryService ) { super(id, label); @@ -1227,7 +1227,7 @@ export class ClearRecentFilesAction extends Action { run(): Promise { // Clear global recently opened - this.workspacesHistoryService.clearRecentlyOpened(); + this.workspacesService.clearRecentlyOpened(); // Clear workspace specific recently opened this.historyService.clearRecentlyOpened(); diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index db33a3383ea..5c67b37664a 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -7,7 +7,6 @@ import * as nls from 'vs/nls'; import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { registerThemingParticipant, ITheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService'; import { MenuBarVisibility, getTitleBarStyle, IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IAction, Action } from 'vs/base/common/actions'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -17,7 +16,7 @@ import { isMacintosh, isWeb } from 'vs/base/common/platform'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IRecentlyOpened, isRecentFolder, IRecent, isRecentWorkspace } from 'vs/platform/workspaces/common/workspacesHistory'; +import { IRecentlyOpened, isRecentFolder, IRecent, isRecentWorkspace, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { RunOnceScheduler } from 'vs/base/common/async'; import { MENUBAR_SELECTION_FOREGROUND, MENUBAR_SELECTION_BACKGROUND, MENUBAR_SELECTION_BORDER, TITLE_BAR_ACTIVE_FOREGROUND, TITLE_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND } from 'vs/workbench/common/theme'; import { URI } from 'vs/base/common/uri'; @@ -86,7 +85,7 @@ export abstract class MenubarControl extends Disposable { constructor( protected readonly menuService: IMenuService, - protected readonly workspacesHistoryService: IWorkspacesHistoryService, + protected readonly workspacesService: IWorkspacesService, protected readonly contextKeyService: IContextKeyService, protected readonly keybindingService: IKeybindingService, protected readonly configurationService: IConfigurationService, @@ -128,7 +127,7 @@ export abstract class MenubarControl extends Disposable { this.updateService.onStateChange(() => this.updateMenubar()); // Listen for changes in recently opened menu - this._register(this.workspacesHistoryService.onRecentlyOpenedChange(() => { this.onRecentlyOpenedChange(); })); + this._register(this.workspacesService.onRecentlyOpenedChange(() => { this.onRecentlyOpenedChange(); })); // Listen to keybindings change this._register(this.keybindingService.onDidUpdateKeybindings(() => this.updateMenubar())); @@ -190,7 +189,7 @@ export abstract class MenubarControl extends Disposable { } private onRecentlyOpenedChange(): void { - this.workspacesHistoryService.getRecentlyOpened().then(recentlyOpened => { + this.workspacesService.getRecentlyOpened().then(recentlyOpened => { this.recentlyOpened = recentlyOpened; this.updateMenubar(); }); @@ -270,7 +269,7 @@ export class CustomMenubarControl extends MenubarControl { constructor( @IMenuService menuService: IMenuService, - @IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService workspacesService: IWorkspacesService, @IContextKeyService contextKeyService: IContextKeyService, @IKeybindingService keybindingService: IKeybindingService, @IConfigurationService configurationService: IConfigurationService, @@ -290,7 +289,7 @@ export class CustomMenubarControl extends MenubarControl { super( menuService, - workspacesHistoryService, + workspacesService, contextKeyService, keybindingService, configurationService, @@ -307,7 +306,7 @@ export class CustomMenubarControl extends MenubarControl { this._onVisibilityChange = this._register(new Emitter()); this._onFocusStateChange = this._register(new Emitter()); - this.workspacesHistoryService.getRecentlyOpened().then((recentlyOpened) => { + this.workspacesService.getRecentlyOpened().then((recentlyOpened) => { this.recentlyOpened = recentlyOpened; }); diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts index 5ef09e54474..51a01b4c23c 100644 --- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts @@ -15,7 +15,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { localize } from 'vs/nls'; @@ -41,7 +40,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { IFileService } from 'vs/platform/files/common/files'; import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { joinPath } from 'vs/base/common/resources'; -import { IRecentlyOpened, isRecentWorkspace, IRecentWorkspace, IRecentFolder, isRecentFolder } from 'vs/platform/workspaces/common/workspacesHistory'; +import { IRecentlyOpened, isRecentWorkspace, IRecentWorkspace, IRecentFolder, isRecentFolder, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IHostService } from 'vs/workbench/services/host/browser/host'; @@ -253,7 +252,7 @@ class WelcomePage extends Disposable { constructor( @IEditorService private readonly editorService: IEditorService, @IInstantiationService private readonly instantiationService: IInstantiationService, - @IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService private readonly workspacesService: IWorkspacesService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IConfigurationService private readonly configurationService: IConfigurationService, @ILabelService private readonly labelService: ILabelService, @@ -270,7 +269,7 @@ class WelcomePage extends Disposable { super(); this._register(lifecycleService.onShutdown(() => this.dispose())); - const recentlyOpened = this.workspacesHistoryService.getRecentlyOpened(); + const recentlyOpened = this.workspacesService.getRecentlyOpened(); const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions); const resource = URI.parse(require.toUrl('./vs_code_welcome_page')) .with({ diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 5882ba5feec..0d4aa329659 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -30,7 +30,7 @@ import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/men import { RunOnceScheduler } from 'vs/base/common/async'; import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { LifecyclePhase, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspaceFolderCreationData, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity'; import { isRootUser, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import product from 'vs/platform/product/common/product'; @@ -61,7 +61,6 @@ import { ITunnelService, extractLocalHostUriMetaDataForPortMapping } from 'vs/pl import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; const TextInputActions: IAction[] = [ new Action('undo', nls.localize('undo', "Undo"), undefined, true, () => Promise.resolve(document.execCommand('undo'))), @@ -681,7 +680,7 @@ export class ElectronWindow extends Disposable { class NativeMenubarControl extends MenubarControl { constructor( @IMenuService menuService: IMenuService, - @IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService workspacesService: IWorkspacesService, @IContextKeyService contextKeyService: IContextKeyService, @IKeybindingService keybindingService: IKeybindingService, @IConfigurationService configurationService: IConfigurationService, @@ -698,7 +697,7 @@ class NativeMenubarControl extends MenubarControl { ) { super( menuService, - workspacesHistoryService, + workspacesService, contextKeyService, keybindingService, configurationService, @@ -725,7 +724,7 @@ class NativeMenubarControl extends MenubarControl { } (async () => { - this.recentlyOpened = await this.workspacesHistoryService.getRecentlyOpened(); + this.recentlyOpened = await this.workspacesService.getRecentlyOpened(); this.doUpdateMenubar(true); })(); diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 24bfb28d197..de6fad7d5fd 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -19,7 +19,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Event } from 'vs/base/common/event'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { getExcludes, ISearchConfiguration } from 'vs/workbench/services/search/common/search'; import { IExpression } from 'vs/base/common/glob'; @@ -33,6 +32,7 @@ import { coalesce } from 'vs/base/common/arrays'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { withNullAsUndefined } from 'vs/base/common/types'; import { addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom'; +import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; /** * Stores the selection & view state of an editor and allows to compare it to other selection states. @@ -138,7 +138,7 @@ export class HistoryService extends Disposable implements IHistoryService { @IStorageService private readonly storageService: IStorageService, @IConfigurationService private readonly configurationService: IConfigurationService, @IFileService private readonly fileService: IFileService, - @IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, + @IWorkspacesService private readonly workspacesService: IWorkspacesService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @@ -781,7 +781,7 @@ export class HistoryService extends Disposable implements IHistoryService { const input = arg1 as IResourceInput; - this.workspacesHistoryService.removeFromRecentlyOpened([input.resource]); + this.workspacesService.removeFromRecentlyOpened([input.resource]); } private isFileOpened(resource: URI, group: IEditorGroup): boolean { diff --git a/src/vs/workbench/services/workspace/browser/workspacesHistoryService.ts b/src/vs/workbench/services/workspace/browser/workspacesHistoryService.ts deleted file mode 100644 index d92d1eafec2..00000000000 --- a/src/vs/workbench/services/workspace/browser/workspacesHistoryService.ts +++ /dev/null @@ -1,113 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event, Emitter } from 'vs/base/common/event'; -import { URI } from 'vs/base/common/uri'; -import { IRecent, IRecentlyOpened, isRecentFolder, isRecentFile } from 'vs/platform/workspaces/common/workspacesHistory'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; -import { restoreRecentlyOpened, toStoreData } from 'vs/platform/workspaces/common/workspacesHistoryStorage'; -import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage'; -import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { ILogService } from 'vs/platform/log/common/log'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { Disposable } from 'vs/base/common/lifecycle'; - -export class BrowserWorkspacesHistoryService extends Disposable implements IWorkspacesHistoryService { - - static readonly RECENTLY_OPENED_KEY = 'recently.opened'; - - _serviceBrand: undefined; - - private readonly _onRecentlyOpenedChange: Emitter = this._register(new Emitter()); - readonly onRecentlyOpenedChange: Event = this._onRecentlyOpenedChange.event; - - constructor( - @IStorageService private readonly storageService: IStorageService, - @IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService, - @ILogService private readonly logService: ILogService, - ) { - super(); - - this.addWorkspaceToRecentlyOpened(); - - this.registerListeners(); - } - - private registerListeners(): void { - this._register(this.storageService.onDidChangeStorage(event => { - if (event.key === BrowserWorkspacesHistoryService.RECENTLY_OPENED_KEY && event.scope === StorageScope.GLOBAL) { - this._onRecentlyOpenedChange.fire(); - } - })); - } - - private addWorkspaceToRecentlyOpened(): void { - const workspace = this.workspaceService.getWorkspace(); - switch (this.workspaceService.getWorkbenchState()) { - case WorkbenchState.FOLDER: - this.addRecentlyOpened([{ folderUri: workspace.folders[0].uri }]); - break; - case WorkbenchState.WORKSPACE: - this.addRecentlyOpened([{ workspace: { id: workspace.id, configPath: workspace.configuration! } }]); - break; - } - } - - async getRecentlyOpened(): Promise { - const recentlyOpenedRaw = this.storageService.get(BrowserWorkspacesHistoryService.RECENTLY_OPENED_KEY, StorageScope.GLOBAL); - if (recentlyOpenedRaw) { - return restoreRecentlyOpened(JSON.parse(recentlyOpenedRaw), this.logService); - } - - return { workspaces: [], files: [] }; - } - - async addRecentlyOpened(recents: IRecent[]): Promise { - const recentlyOpened = await this.getRecentlyOpened(); - - recents.forEach(recent => { - if (isRecentFile(recent)) { - this.doRemoveFromRecentlyOpened(recentlyOpened, [recent.fileUri]); - recentlyOpened.files.unshift(recent); - } else if (isRecentFolder(recent)) { - this.doRemoveFromRecentlyOpened(recentlyOpened, [recent.folderUri]); - recentlyOpened.workspaces.unshift(recent); - } else { - this.doRemoveFromRecentlyOpened(recentlyOpened, [recent.workspace.configPath]); - recentlyOpened.workspaces.unshift(recent); - } - }); - - return this.saveRecentlyOpened(recentlyOpened); - } - - async removeFromRecentlyOpened(paths: URI[]): Promise { - const recentlyOpened = await this.getRecentlyOpened(); - - this.doRemoveFromRecentlyOpened(recentlyOpened, paths); - - return this.saveRecentlyOpened(recentlyOpened); - } - - private doRemoveFromRecentlyOpened(recentlyOpened: IRecentlyOpened, paths: URI[]): void { - recentlyOpened.files = recentlyOpened.files.filter(file => { - return !paths.some(path => path.toString() === file.fileUri.toString()); - }); - - recentlyOpened.workspaces = recentlyOpened.workspaces.filter(workspace => { - return !paths.some(path => path.toString() === (isRecentFolder(workspace) ? workspace.folderUri.toString() : workspace.workspace.configPath.toString())); - }); - } - - private async saveRecentlyOpened(data: IRecentlyOpened): Promise { - return this.storageService.store(BrowserWorkspacesHistoryService.RECENTLY_OPENED_KEY, JSON.stringify(toStoreData(data)), StorageScope.GLOBAL); - } - - async clearRecentlyOpened(): Promise { - this.storageService.remove(BrowserWorkspacesHistoryService.RECENTLY_OPENED_KEY, StorageScope.GLOBAL); - } -} - -registerSingleton(IWorkspacesHistoryService, BrowserWorkspacesHistoryService, true); diff --git a/src/vs/workbench/services/workspace/browser/workspacesService.ts b/src/vs/workbench/services/workspace/browser/workspacesService.ts index b919b06a94e..96c681e7976 100644 --- a/src/vs/workbench/services/workspace/browser/workspacesService.ts +++ b/src/vs/workbench/services/workspace/browser/workspacesService.ts @@ -4,13 +4,115 @@ *--------------------------------------------------------------------------------------------*/ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IWorkspacesService, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IEnterWorkspaceResult } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspacesService, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IEnterWorkspaceResult, IRecentlyOpened, restoreRecentlyOpened, IRecent, isRecentFile, isRecentFolder, toStoreData } 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'; -export class WorkspacesService implements IWorkspacesService { +export class BrowserWorkspacesService extends Disposable implements IWorkspacesService { + + static readonly RECENTLY_OPENED_KEY = 'recently.opened'; _serviceBrand: undefined; + private readonly _onRecentlyOpenedChange: Emitter = this._register(new Emitter()); + readonly onRecentlyOpenedChange: Event = this._onRecentlyOpenedChange.event; + + constructor( + @IStorageService private readonly storageService: IStorageService, + @IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService, + @ILogService private readonly logService: ILogService, + ) { + super(); + + this.addWorkspaceToRecentlyOpened(); + + this.registerListeners(); + } + + private registerListeners(): void { + this._register(this.storageService.onDidChangeStorage(event => { + if (event.key === BrowserWorkspacesService.RECENTLY_OPENED_KEY && event.scope === StorageScope.GLOBAL) { + this._onRecentlyOpenedChange.fire(); + } + })); + } + + private addWorkspaceToRecentlyOpened(): void { + const workspace = this.workspaceService.getWorkspace(); + switch (this.workspaceService.getWorkbenchState()) { + case WorkbenchState.FOLDER: + this.addRecentlyOpened([{ folderUri: workspace.folders[0].uri }]); + break; + case WorkbenchState.WORKSPACE: + this.addRecentlyOpened([{ workspace: { id: workspace.id, configPath: workspace.configuration! } }]); + break; + } + } + + //#region Workspaces History + + async getRecentlyOpened(): Promise { + const recentlyOpenedRaw = this.storageService.get(BrowserWorkspacesService.RECENTLY_OPENED_KEY, StorageScope.GLOBAL); + if (recentlyOpenedRaw) { + return restoreRecentlyOpened(JSON.parse(recentlyOpenedRaw), this.logService); + } + + return { workspaces: [], files: [] }; + } + + async addRecentlyOpened(recents: IRecent[]): Promise { + const recentlyOpened = await this.getRecentlyOpened(); + + recents.forEach(recent => { + if (isRecentFile(recent)) { + this.doRemoveFromRecentlyOpened(recentlyOpened, [recent.fileUri]); + recentlyOpened.files.unshift(recent); + } else if (isRecentFolder(recent)) { + this.doRemoveFromRecentlyOpened(recentlyOpened, [recent.folderUri]); + recentlyOpened.workspaces.unshift(recent); + } else { + this.doRemoveFromRecentlyOpened(recentlyOpened, [recent.workspace.configPath]); + recentlyOpened.workspaces.unshift(recent); + } + }); + + return this.saveRecentlyOpened(recentlyOpened); + } + + async removeFromRecentlyOpened(paths: URI[]): Promise { + const recentlyOpened = await this.getRecentlyOpened(); + + this.doRemoveFromRecentlyOpened(recentlyOpened, paths); + + return this.saveRecentlyOpened(recentlyOpened); + } + + private doRemoveFromRecentlyOpened(recentlyOpened: IRecentlyOpened, paths: URI[]): void { + recentlyOpened.files = recentlyOpened.files.filter(file => { + return !paths.some(path => path.toString() === file.fileUri.toString()); + }); + + recentlyOpened.workspaces = recentlyOpened.workspaces.filter(workspace => { + return !paths.some(path => path.toString() === (isRecentFolder(workspace) ? workspace.folderUri.toString() : workspace.workspace.configPath.toString())); + }); + } + + private async saveRecentlyOpened(data: IRecentlyOpened): Promise { + return this.storageService.store(BrowserWorkspacesService.RECENTLY_OPENED_KEY, JSON.stringify(toStoreData(data)), StorageScope.GLOBAL); + } + + async clearRecentlyOpened(): Promise { + this.storageService.remove(BrowserWorkspacesService.RECENTLY_OPENED_KEY, StorageScope.GLOBAL); + } + + //#endregion + + //#region Workspace Management + enterWorkspace(path: URI): Promise { throw new Error('Untitled workspaces are currently unsupported in Web'); } @@ -26,6 +128,8 @@ export class WorkspacesService implements IWorkspacesService { getWorkspaceIdentifier(workspacePath: URI): Promise { throw new Error('Untitled workspaces are currently unsupported in Web'); } + + //#endregion } -registerSingleton(IWorkspacesService, WorkspacesService, true); +registerSingleton(IWorkspacesService, BrowserWorkspacesService, true); diff --git a/src/vs/workbench/services/workspace/common/workspacesHistoryService.ts b/src/vs/workbench/services/workspace/common/workspacesHistoryService.ts deleted file mode 100644 index 2d07184a4ae..00000000000 --- a/src/vs/workbench/services/workspace/common/workspacesHistoryService.ts +++ /dev/null @@ -1,25 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { Event } from 'vs/base/common/event'; -import { URI } from 'vs/base/common/uri'; -import { IRecent, IRecentlyOpened } from 'vs/platform/workspaces/common/workspacesHistory'; - -export const IWorkspacesHistoryService = createDecorator('workspacesHistoryService'); - -export interface IWorkspacesHistoryService { - - _serviceBrand: undefined; - - readonly onRecentlyOpenedChange: Event; - - addRecentlyOpened(recents: IRecent[]): Promise; - - removeFromRecentlyOpened(workspaces: URI[]): Promise; - clearRecentlyOpened(): Promise; - - getRecentlyOpened(): Promise; -} diff --git a/src/vs/workbench/services/workspace/electron-browser/workspaceEditingService.ts b/src/vs/workbench/services/workspace/electron-browser/workspaceEditingService.ts index a477221e2fb..6e5ddf801e3 100644 --- a/src/vs/workbench/services/workspace/electron-browser/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspace/electron-browser/workspaceEditingService.ts @@ -7,7 +7,6 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService'; @@ -47,7 +46,6 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi @ICommandService commandService: ICommandService, @IFileService fileService: IFileService, @ITextFileService textFileService: ITextFileService, - @IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService workspacesService: IWorkspacesService, @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IFileDialogService fileDialogService: IFileDialogService, @@ -135,7 +133,7 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi const newWorkspaceIdentifier = await this.workspacesService.getWorkspaceIdentifier(newWorkspacePath); const label = this.labelService.getWorkspaceLabel(newWorkspaceIdentifier, { verbose: true }); - this.workspacesHistoryService.addRecentlyOpened([{ label, workspace: newWorkspaceIdentifier }]); + this.workspacesService.addRecentlyOpened([{ label, workspace: newWorkspaceIdentifier }]); this.workspacesService.deleteUntitledWorkspace(workspaceIdentifier); } catch (error) { diff --git a/src/vs/workbench/services/workspace/electron-browser/workspacesHistoryService.ts b/src/vs/workbench/services/workspace/electron-browser/workspacesHistoryService.ts deleted file mode 100644 index ccc758eacd1..00000000000 --- a/src/vs/workbench/services/workspace/electron-browser/workspacesHistoryService.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { URI } from 'vs/base/common/uri'; -import { IRecent, IRecentlyOpened } from 'vs/platform/workspaces/common/workspacesHistory'; -import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IElectronService } from 'vs/platform/electron/node/electron'; - -export class NativeWorkspacesHistoryService implements IWorkspacesHistoryService { - - _serviceBrand: undefined; - - readonly onRecentlyOpenedChange = this.electronService.onRecentlyOpenedChange; - - constructor( - @IElectronService private readonly electronService: IElectronService - ) { } - - async getRecentlyOpened(): Promise { - return this.electronService.getRecentlyOpened(); - } - - async addRecentlyOpened(recents: IRecent[]): Promise { - return this.electronService.addRecentlyOpened(recents); - } - - async removeFromRecentlyOpened(paths: URI[]): Promise { - return this.electronService.removeFromRecentlyOpened(paths); - } - - async clearRecentlyOpened(): Promise { - return this.electronService.clearRecentlyOpened(); - } -} - -registerSingleton(IWorkspacesHistoryService, NativeWorkspacesHistoryService, true); diff --git a/src/vs/workbench/services/workspace/electron-browser/workspacesService.ts b/src/vs/workbench/services/workspace/electron-browser/workspacesService.ts index d333784c86c..61fc335fb36 100644 --- a/src/vs/workbench/services/workspace/electron-browser/workspacesService.ts +++ b/src/vs/workbench/services/workspace/electron-browser/workspacesService.ts @@ -3,46 +3,22 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IWorkspacesService, IWorkspaceIdentifier, IWorkspaceFolderCreationData, reviveWorkspaceIdentifier, IEnterWorkspaceResult } from 'vs/platform/workspaces/common/workspaces'; +import { IWorkspacesService } 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'; import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService'; +import { createChannelSender } from 'vs/base/parts/ipc/node/ipcChannelCreator'; -export class WorkspacesService implements IWorkspacesService { +export class NativeWorkspacesService { _serviceBrand: undefined; - private channel: IChannel; - constructor( @IMainProcessService mainProcessService: IMainProcessService, - @IElectronEnvironmentService private readonly electronEnvironmentService: IElectronEnvironmentService + @IElectronEnvironmentService electronEnvironmentService: IElectronEnvironmentService ) { - this.channel = mainProcessService.getChannel('workspaces'); - } - - async enterWorkspace(path: URI): Promise { - const result: IEnterWorkspaceResult = await this.channel.call('enterWorkspace', [this.electronEnvironmentService.windowId, path]); - if (result) { - result.workspace = reviveWorkspaceIdentifier(result.workspace); - } - - return result; - } - - createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise { - return this.channel.call('createUntitledWorkspace', [folders, remoteAuthority]).then(reviveWorkspaceIdentifier); - } - - deleteUntitledWorkspace(workspaceIdentifier: IWorkspaceIdentifier): Promise { - return this.channel.call('deleteUntitledWorkspace', workspaceIdentifier); - } - - getWorkspaceIdentifier(configPath: URI): Promise { - return this.channel.call('getWorkspaceIdentifier', configPath).then(reviveWorkspaceIdentifier); + return createChannelSender(mainProcessService.getChannel('workspaces'), { context: electronEnvironmentService.windowId }); } } -registerSingleton(IWorkspacesService, WorkspacesService, true); +registerSingleton(IWorkspacesService, NativeWorkspacesService, true); diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index b94b576f068..2da63811006 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -55,7 +55,6 @@ import 'vs/workbench/services/request/electron-browser/requestService'; import 'vs/workbench/services/lifecycle/electron-browser/lifecycleService'; import 'vs/workbench/services/sharedProcess/electron-browser/sharedProcessService'; import 'vs/workbench/services/electron/electron-browser/electronService'; -import 'vs/workbench/services/workspace/electron-browser/workspacesHistoryService'; import 'vs/workbench/services/workspace/electron-browser/workspaceEditingService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 2a27c5272fc..cd8d3017b16 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -45,7 +45,6 @@ import 'vs/workbench/services/dialogs/browser/dialogService'; import 'vs/workbench/services/dialogs/browser/fileDialogService'; import 'vs/workbench/services/host/browser/browserHostService'; import 'vs/workbench/services/request/browser/requestService'; -import 'vs/workbench/services/workspace/browser/workspacesHistoryService'; import 'vs/workbench/services/workspace/browser/workspaceEditingService'; import 'vs/workbench/services/lifecycle/browser/lifecycleService';