Merge from vscode f2d41726ba5a0e8abfe61b2c743022b1b6372010 (#7415)

* Merge from vscode f2d41726ba5a0e8abfe61b2c743022b1b6372010

* add missing files
This commit is contained in:
Anthony Dresser
2019-09-27 23:30:36 -07:00
committed by GitHub
parent d0fb6de390
commit bca7c8e6bd
123 changed files with 1704 additions and 1330 deletions

View File

@@ -271,7 +271,7 @@
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{ {
"name": "vs/workbench/services/workspace", "name": "vs/workbench/services/workspaces",
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{ {

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 0.6s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.075s; }
circle:nth-child(3) { animation-delay: 0.15s; }
circle:nth-child(4) { animation-delay: 0.225s; }
circle:nth-child(5) { animation-delay: 0.3s; }
circle:nth-child(6) { animation-delay: 0.375s; }
circle:nth-child(7) { animation-delay: 0.45s; }
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:grey;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 0.6s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.075s; }
circle:nth-child(3) { animation-delay: 0.15s; }
circle:nth-child(4) { animation-delay: 0.225s; }
circle:nth-child(5) { animation-delay: 0.3s; }
circle:nth-child(6) { animation-delay: 0.375s; }
circle:nth-child(7) { animation-delay: 0.45s; }
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:white;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,31 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 0.6s linear infinite;
}
circle:nth-child(2) { animation-delay: 0.075s; }
circle:nth-child(3) { animation-delay: 0.15s; }
circle:nth-child(4) { animation-delay: 0.225s; }
circle:nth-child(5) { animation-delay: 0.3s; }
circle:nth-child(6) { animation-delay: 0.375s; }
circle:nth-child(7) { animation-delay: 0.45s; }
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g>
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -62,11 +62,11 @@ body img {
margin: auto; margin: auto;
} }
.container.zoom-in { .container.ready.zoom-in {
cursor: zoom-in; cursor: zoom-in;
} }
.container.zoom-out { .container.ready.zoom-out {
cursor: zoom-out; cursor: zoom-out;
} }
@@ -76,3 +76,23 @@ body img {
text-decoration: underline; text-decoration: underline;
margin-left: 5px; margin-left: 5px;
} }
.loading {
position: fixed;
width: 30px;
height: 30px;
left: 50%;
top: 50%;
margin-top: -15px;
margin-left: -15px;
background-image: url('./loading.svg');
background-size: cover;
}
.vscode-dark .loading {
background-image: url('./loading-dark.svg');
}
.vscode-high-contrast .loading {
background-image: url('./loading-hc.svg');
}

View File

@@ -69,13 +69,14 @@
let scale = initialState.scale; let scale = initialState.scale;
let ctrlPressed = false; let ctrlPressed = false;
let altPressed = false; let altPressed = false;
let hasLoadedImage = false;
// Elements // Elements
const container = /** @type {HTMLElement} */(document.querySelector('body')); const container = /** @type {HTMLElement} */(document.querySelector('body'));
const image = document.createElement('img'); const image = document.createElement('img');
function updateScale(newScale) { function updateScale(newScale) {
if (!image || !image.parentElement) { if (!image || !hasLoadedImage || !image.parentElement) {
return; return;
} }
@@ -125,7 +126,7 @@
} }
function firstZoom() { function firstZoom() {
if (!image) { if (!image || !hasLoadedImage) {
return; return;
} }
@@ -134,7 +135,7 @@
} }
window.addEventListener('keydown', (/** @type {KeyboardEvent} */ e) => { window.addEventListener('keydown', (/** @type {KeyboardEvent} */ e) => {
if (!image) { if (!image || !hasLoadedImage) {
return; return;
} }
ctrlPressed = e.ctrlKey; ctrlPressed = e.ctrlKey;
@@ -147,7 +148,7 @@
}); });
window.addEventListener('keyup', (/** @type {KeyboardEvent} */ e) => { window.addEventListener('keyup', (/** @type {KeyboardEvent} */ e) => {
if (!image) { if (!image || !hasLoadedImage) {
return; return;
} }
@@ -161,7 +162,7 @@
}); });
container.addEventListener('click', (/** @type {MouseEvent} */ e) => { container.addEventListener('click', (/** @type {MouseEvent} */ e) => {
if (!image) { if (!image || !hasLoadedImage) {
return; return;
} }
@@ -194,7 +195,7 @@
}); });
container.addEventListener('wheel', (/** @type {WheelEvent} */ e) => { container.addEventListener('wheel', (/** @type {WheelEvent} */ e) => {
if (!image) { if (!image || !hasLoadedImage) {
return; return;
} }
@@ -215,7 +216,7 @@
}); });
window.addEventListener('scroll', () => { window.addEventListener('scroll', () => {
if (!image || !image.parentElement || scale === 'fit') { if (!image || !hasLoadedImage || !image.parentElement || scale === 'fit') {
return; return;
} }
@@ -229,9 +230,11 @@
container.classList.add('zoom-in'); container.classList.add('zoom-in');
image.classList.add('scale-to-fit'); image.classList.add('scale-to-fit');
image.style.visibility = 'hidden';
image.addEventListener('load', () => { image.addEventListener('load', () => {
document.querySelector('.loading').remove();
hasLoadedImage = true;
if (!image) { if (!image) {
return; return;
} }
@@ -241,7 +244,9 @@
value: `${image.naturalWidth}x${image.naturalHeight}`, value: `${image.naturalWidth}x${image.naturalHeight}`,
}); });
image.style.visibility = 'visible'; container.classList.add('ready');
document.body.append(image);
updateScale(scale); updateScale(scale);
if (initialState.scale !== 'fit') { if (initialState.scale !== 'fit') {
@@ -250,7 +255,6 @@
}); });
image.src = decodeURI(settings.src); image.src = decodeURI(settings.src);
document.body.append(image);
window.addEventListener('message', e => { window.addEventListener('message', e => {
switch (e.data.type) { switch (e.data.type) {

View File

@@ -96,6 +96,7 @@ export class Preview extends Disposable {
<meta id="image-preview-settings" data-settings="${escapeAttribute(JSON.stringify(settings))}"> <meta id="image-preview-settings" data-settings="${escapeAttribute(JSON.stringify(settings))}">
</head> </head>
<body class="container image scale-to-fit"> <body class="container image scale-to-fit">
<div class='loading'></div>
<script src="${escapeAttribute(this.extensionResource('/media/main.js'))}"></script> <script src="${escapeAttribute(this.extensionResource('/media/main.js'))}"></script>
</body> </body>
</html>`; </html>`;

View File

@@ -21,7 +21,7 @@ import { registerComponentType } from 'sql/workbench/parts/notebook/browser/outp
import { MimeRendererComponent } from 'sql/workbench/parts/notebook/browser/outputs/mimeRenderer.component'; import { MimeRendererComponent } from 'sql/workbench/parts/notebook/browser/outputs/mimeRenderer.component';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/browser/nodeContext'; import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/browser/nodeContext';
import { MssqlNodeContext } from 'sql/workbench/parts/dataExplorer/browser/mssqlNodeContext'; import { MssqlNodeContext } from 'sql/workbench/parts/dataExplorer/browser/mssqlNodeContext';

View File

@@ -781,6 +781,12 @@ export function createStyleSheet(container: HTMLElement = document.getElementsBy
return style; return style;
} }
export function createMetaElement(container: HTMLElement = document.getElementsByTagName('head')[0]): HTMLMetaElement {
let meta = document.createElement('meta');
container.appendChild(meta);
return meta;
}
let _sharedStyleSheet: HTMLStyleElement | null = null; let _sharedStyleSheet: HTMLStyleElement | null = null;
function getSharedStyleSheet(): HTMLStyleElement { function getSharedStyleSheet(): HTMLStyleElement {
if (!_sharedStyleSheet) { if (!_sharedStyleSheet) {

View File

@@ -698,7 +698,7 @@ export class MenuBar extends Disposable {
private focusPrevious(): void { private focusPrevious(): void {
if (!this.focusedMenu) { if (!this.focusedMenu || this.numMenusShown === 0) {
return; return;
} }
@@ -728,7 +728,7 @@ export class MenuBar extends Disposable {
} }
private focusNext(): void { private focusNext(): void {
if (!this.focusedMenu) { if (!this.focusedMenu || this.numMenusShown === 0) {
return; return;
} }

View File

@@ -4,16 +4,25 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc';
import { revive } from 'vs/base/common/marshalling'; import { revive } from 'vs/base/common/marshalling';
import { isUndefinedOrNull } from 'vs/base/common/types'; import { isUndefinedOrNull } from 'vs/base/common/types';
import { isUpperAsciiLetter } from 'vs/base/common/strings'; import { isUpperAsciiLetter } from 'vs/base/common/strings';
// /**
// Use both `createChannelReceiver` and `createChannelSender` * Use both `createChannelReceiver` and `createChannelSender`
// for automated process <=> process communication over methods * for automated process <=> process communication over methods
// and events. * and events. You do not need to spell out each method on both
// * sides, a proxy will take care of this.
*
* Rules:
* - if marshalling is enabled, only `URI` and `RegExp` is converted
* automatically for you
* - events must follow the naming convention `onUppercase`
* - `CancellationToken` is currently not supported
* - if a context is provided, you can use `AddFirstParameterToFunctions`
* utility to signal this in the receiving side type
*/
export interface IBaseChannelOptions { export interface IBaseChannelOptions {

View File

@@ -5,11 +5,14 @@
import * as assert from 'assert'; import * as assert from 'assert';
import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient } from 'vs/base/parts/ipc/common/ipc'; import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/node/ipc';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors'; import { canceled } from 'vs/base/common/errors';
import { timeout } from 'vs/base/common/async'; import { timeout } from 'vs/base/common/async';
import { VSBuffer } from 'vs/base/common/buffer'; import { VSBuffer } from 'vs/base/common/buffer';
import { URI } from 'vs/base/common/uri';
import { isEqual } from 'vs/base/common/resources';
class QueueProtocol implements IMessagePassingProtocol { class QueueProtocol implements IMessagePassingProtocol {
@@ -101,14 +104,16 @@ interface ITestService {
neverComplete(): Promise<void>; neverComplete(): Promise<void>;
neverCompleteCT(cancellationToken: CancellationToken): Promise<void>; neverCompleteCT(cancellationToken: CancellationToken): Promise<void>;
buffersLength(buffers: Buffer[]): Promise<number>; buffersLength(buffers: Buffer[]): Promise<number>;
marshall(uri: URI): Promise<URI>;
context(): Promise<unknown>;
pong: Event<string>; onPong: Event<string>;
} }
class TestService implements ITestService { class TestService implements ITestService {
private readonly _pong = new Emitter<string>(); private readonly _onPong = new Emitter<string>();
readonly pong = this._pong.event; readonly onPong = this._onPong.event;
marco(): Promise<string> { marco(): Promise<string> {
return Promise.resolve('polo'); return Promise.resolve('polo');
@@ -135,7 +140,15 @@ class TestService implements ITestService {
} }
ping(msg: string): void { ping(msg: string): void {
this._pong.fire(msg); this._onPong.fire(msg);
}
marshall(uri: URI): Promise<URI> {
return Promise.resolve(uri);
}
context(context?: unknown): Promise<unknown> {
return Promise.resolve(context);
} }
} }
@@ -156,7 +169,7 @@ class TestChannel implements IServerChannel {
listen(_: unknown, event: string, arg?: any): Event<any> { listen(_: unknown, event: string, arg?: any): Event<any> {
switch (event) { switch (event) {
case 'pong': return this.service.pong; case 'onPong': return this.service.onPong;
default: throw new Error('not implemented'); default: throw new Error('not implemented');
} }
} }
@@ -164,8 +177,8 @@ class TestChannel implements IServerChannel {
class TestChannelClient implements ITestService { class TestChannelClient implements ITestService {
get pong(): Event<string> { get onPong(): Event<string> {
return this.channel.listen('pong'); return this.channel.listen('onPong');
} }
constructor(private channel: IChannel) { } constructor(private channel: IChannel) { }
@@ -189,6 +202,14 @@ class TestChannelClient implements ITestService {
buffersLength(buffers: Buffer[]): Promise<number> { buffersLength(buffers: Buffer[]): Promise<number> {
return this.channel.call('buffersLength', buffers); return this.channel.call('buffersLength', buffers);
} }
marshall(uri: URI): Promise<URI> {
return this.channel.call('marshall', uri);
}
context(): Promise<unknown> {
return this.channel.call('context');
}
} }
suite('Base IPC', function () { suite('Base IPC', function () {
@@ -281,7 +302,7 @@ suite('Base IPC', function () {
test('listen to events', async function () { test('listen to events', async function () {
const messages: string[] = []; const messages: string[] = [];
ipcService.pong(msg => messages.push(msg)); ipcService.onPong(msg => messages.push(msg));
await timeout(0); await timeout(0);
assert.deepEqual(messages, []); assert.deepEqual(messages, []);
@@ -300,4 +321,98 @@ suite('Base IPC', function () {
return assert.equal(r, 5); return assert.equal(r, 5);
}); });
}); });
suite('one to one (proxy)', function () {
let server: IPCServer;
let client: IPCClient;
let service: TestService;
let ipcService: ITestService;
setup(function () {
service = new TestService();
const testServer = new TestIPCServer();
server = testServer;
server.registerChannel(TestChannelId, createChannelReceiver(service));
client = testServer.createConnection('client1');
ipcService = createChannelSender(client.getChannel(TestChannelId));
});
teardown(function () {
client.dispose();
server.dispose();
});
test('call success', async function () {
const r = await ipcService.marco();
return assert.equal(r, 'polo');
});
test('call error', async function () {
try {
await ipcService.error('nice error');
return assert.fail('should not reach here');
} catch (err) {
return assert.equal(err.message, 'nice error');
}
});
test('listen to events', async function () {
const messages: string[] = [];
ipcService.onPong(msg => messages.push(msg));
await timeout(0);
assert.deepEqual(messages, []);
service.ping('hello');
await timeout(0);
assert.deepEqual(messages, ['hello']);
service.ping('world');
await timeout(0);
assert.deepEqual(messages, ['hello', 'world']);
});
test('marshalling uri', async function () {
const uri = URI.file('foobar');
const r = await ipcService.marshall(uri);
assert.ok(r instanceof URI);
return assert.ok(isEqual(r, uri));
});
test('buffers in arrays', async function () {
const r = await ipcService.buffersLength([Buffer.allocUnsafe(2), Buffer.allocUnsafe(3)]);
return assert.equal(r, 5);
});
});
suite('one to one (proxy, extra context)', function () {
let server: IPCServer;
let client: IPCClient;
let service: TestService;
let ipcService: ITestService;
setup(function () {
service = new TestService();
const testServer = new TestIPCServer();
server = testServer;
server.registerChannel(TestChannelId, createChannelReceiver(service));
client = testServer.createConnection('client1');
ipcService = createChannelSender(client.getChannel(TestChannelId), { context: 'Super Context' });
});
teardown(function () {
client.dispose();
server.dispose();
});
test('call extra context', async function () {
const r = await ipcService.context();
return assert.equal(r, 'Super Context');
});
});
}); });

View File

@@ -3,12 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { IWorkbenchConstructionOptions, create, URI, Event, Emitter, UriComponents, ICredentialsProvider, IURLCallbackProvider } from 'vs/workbench/workbench.web.api'; import { IWorkbenchConstructionOptions, create, URI, Event, Emitter, UriComponents, ICredentialsProvider, IURLCallbackProvider, IWorkspaceProvider, IWorkspace } from 'vs/workbench/workbench.web.api';
import { generateUuid } from 'vs/base/common/uuid'; import { generateUuid } from 'vs/base/common/uuid';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { streamToBuffer } from 'vs/base/common/buffer'; import { streamToBuffer } from 'vs/base/common/buffer';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { request } from 'vs/base/parts/request/browser/request'; import { request } from 'vs/base/parts/request/browser/request';
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/windows/common/windows';
interface ICredential { interface ICredential {
service: string; service: string;
@@ -197,18 +198,43 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi
} }
} }
const options: IWorkbenchConstructionOptions = JSON.parse(document.getElementById('vscode-workbench-web-configuration')!.getAttribute('data-settings')!); class WorkspaceProvider implements IWorkspaceProvider {
constructor(public readonly workspace: IWorkspace) { }
async open(workspace: IWorkspace, options?: { reuse?: boolean }): Promise<void> {
let targetHref: string | undefined = undefined;
// Empty
if (!workspace) {
targetHref = `${document.location.origin}${document.location.pathname}?ew=true`;
}
// Folder
else if (isFolderToOpen(workspace)) {
targetHref = `${document.location.origin}${document.location.pathname}?folder=${workspace.folderUri.path}`;
}
// Workspace
else if (isWorkspaceToOpen(workspace)) {
targetHref = `${document.location.origin}${document.location.pathname}?workspace=${workspace.workspaceUri.path}`;
}
if (targetHref) {
if (options && options.reuse) {
window.location.href = targetHref;
} else {
window.open(targetHref);
}
}
}
}
const options: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(document.getElementById('vscode-workbench-web-configuration')!.getAttribute('data-settings')!);
options.workspaceProvider = new WorkspaceProvider(options.folderUri ? { folderUri: URI.revive(options.folderUri) } : options.workspaceUri ? { workspaceUri: URI.revive(options.workspaceUri) } : undefined);
options.urlCallbackProvider = new PollingURLCallbackProvider(); options.urlCallbackProvider = new PollingURLCallbackProvider();
options.credentialsProvider = new LocalStorageCredentialsProvider(); options.credentialsProvider = new LocalStorageCredentialsProvider();
if (options.folderUri) {
options.folderUri = URI.revive(options.folderUri);
}
if (options.workspaceUri) {
options.workspaceUri = URI.revive(options.workspaceUri);
}
if (Array.isArray(options.staticExtensions)) { if (Array.isArray(options.staticExtensions)) {
options.staticExtensions.forEach(extension => { options.staticExtensions.forEach(extension => {
extension.extensionLocation = URI.revive(extension.extensionLocation); extension.extensionLocation = URI.revive(extension.extensionLocation);

View File

@@ -16,6 +16,7 @@ import { debounce } from 'vs/base/common/decorators';
import * as platform from 'vs/base/common/platform'; import * as platform from 'vs/base/common/platform';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { createChannelSender } from 'vs/base/parts/ipc/node/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net'; import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
@@ -40,7 +41,6 @@ import { withUndefinedAsNull } from 'vs/base/common/types';
import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { SpdLogService } from 'vs/platform/log/node/spdlogService'; import { SpdLogService } from 'vs/platform/log/node/spdlogService';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { createChannelSender } from 'vs/base/parts/ipc/node/ipcChannelCreator';
const MAX_URL_LENGTH = 2045; const MAX_URL_LENGTH = 2045;

View File

@@ -32,11 +32,11 @@ import { ILogService, LogLevel, ILoggerService } from 'vs/platform/log/common/lo
import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsChannel } from 'vs/platform/localizations/node/localizationsIpc';
import { combinedDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { combinedDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { DownloadService } from 'vs/platform/download/common/downloadService'; import { DownloadService } from 'vs/platform/download/common/downloadService';
import { IDownloadService } from 'vs/platform/download/common/download'; import { IDownloadService } from 'vs/platform/download/common/download';
import { IChannel, IServerChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; import { IChannel, IServerChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
import { createChannelSender, createChannelReceiver } from 'vs/base/parts/ipc/node/ipc';
import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner'; import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner';
import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner'; import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner';
import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner'; import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner';
@@ -55,10 +55,14 @@ import { UserDataSyncService, UserDataAutoSync } from 'vs/platform/userDataSync/
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
import { SettingsMergeChannelClient } from 'vs/platform/userDataSync/common/settingsSyncIpc'; import { SettingsMergeChannelClient } from 'vs/platform/userDataSync/common/settingsSyncIpc';
import { createChannelSender } from 'vs/base/parts/ipc/node/ipcChannelCreator';
import { IElectronService } from 'vs/platform/electron/node/electron'; import { IElectronService } from 'vs/platform/electron/node/electron';
import { LoggerService } from 'vs/platform/log/node/loggerService'; import { LoggerService } from 'vs/platform/log/node/loggerService';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog'; import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { IAuthTokenService } from 'vs/platform/auth/common/auth';
import { AuthTokenService } from 'vs/platform/auth/common/authTokenService';
import { AuthTokenChannel } from 'vs/platform/auth/common/authTokenIpc';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService';
export interface ISharedProcessConfiguration { export interface ISharedProcessConfiguration {
readonly machineId: string; readonly machineId: string;
@@ -177,6 +181,8 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService)); services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService));
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService)); services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
services.set(ICredentialsService, new SyncDescriptor(KeytarCredentialsService));
services.set(IAuthTokenService, new SyncDescriptor(AuthTokenService));
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService)); services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
const settingsMergeChannel = server.getChannel('settingsMerge', activeWindowRouter); const settingsMergeChannel = server.getChannel('settingsMerge', activeWindowRouter);
services.set(ISettingsMergeService, new SettingsMergeChannelClient(settingsMergeChannel)); services.set(ISettingsMergeService, new SettingsMergeChannelClient(settingsMergeChannel));
@@ -193,13 +199,17 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
server.registerChannel('extensions', channel); server.registerChannel('extensions', channel);
const localizationsService = accessor.get(ILocalizationsService); const localizationsService = accessor.get(ILocalizationsService);
const localizationsChannel = new LocalizationsChannel(localizationsService); const localizationsChannel = createChannelReceiver(localizationsService);
server.registerChannel('localizations', localizationsChannel); server.registerChannel('localizations', localizationsChannel);
const diagnosticsService = accessor.get(IDiagnosticsService); const diagnosticsService = accessor.get(IDiagnosticsService);
const diagnosticsChannel = new DiagnosticsChannel(diagnosticsService); const diagnosticsChannel = new DiagnosticsChannel(diagnosticsService);
server.registerChannel('diagnostics', diagnosticsChannel); server.registerChannel('diagnostics', diagnosticsChannel);
const authTokenService = accessor.get(IAuthTokenService);
const authTokenChannel = new AuthTokenChannel(authTokenService);
server.registerChannel('authToken', authTokenChannel);
const userDataSyncService = accessor.get(IUserDataSyncService); const userDataSyncService = accessor.get(IUserDataSyncService);
const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService); const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService);
server.registerChannel('userDataSync', userDataSyncChannel); server.registerChannel('userDataSync', userDataSyncChannel);

View File

@@ -16,7 +16,7 @@ import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc
import { Client } from 'vs/base/parts/ipc/common/ipc.net'; import { Client } from 'vs/base/parts/ipc/common/ipc.net';
import { Server, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { Server, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { SharedProcess } from 'vs/code/electron-main/sharedProcess'; import { SharedProcess } from 'vs/code/electron-main/sharedProcess';
import { LaunchMainService, LaunchChannel, ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; import { LaunchMainService, ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
@@ -25,21 +25,21 @@ import { IStateService } from 'vs/platform/state/node/state';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IURLService } from 'vs/platform/url/common/url'; import { IURLService } from 'vs/platform/url/common/url';
import { URLHandlerChannelClient, URLServiceChannel, URLHandlerRouter } from 'vs/platform/url/common/urlIpc'; import { URLHandlerChannelClient, URLHandlerRouter } from 'vs/platform/url/common/urlIpc';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils'; import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc'; import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipcChannelCreator'; import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc';
import product from 'vs/platform/product/common/product'; import product from 'vs/platform/product/common/product';
import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { WorkspacesChannel } from 'vs/platform/workspaces/electron-main/workspacesIpc'; import { hasWorkspaceFileExtension, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces'; import { WorkspacesService } from 'vs/platform/workspaces/electron-main/workspacesService';
import { getMachineId } from 'vs/base/node/id'; import { getMachineId } from 'vs/base/node/id';
import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32'; import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32';
import { LinuxUpdateService } from 'vs/platform/update/electron-main/updateService.linux'; 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(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv]));
services.set(IElectronService, new SyncDescriptor(ElectronMainService)); services.set(IElectronService, new SyncDescriptor(ElectronMainService));
services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService));
services.set(IMenubarService, new SyncDescriptor(MenubarMainService)); services.set(IMenubarService, new SyncDescriptor(MenubarMainService));
const storageMainService = new StorageMainService(this.logService, this.environmentService); const storageMainService = new StorageMainService(this.logService, this.environmentService);
@@ -530,7 +531,7 @@ export class CodeApplication extends Disposable {
// Register more Main IPC services // Register more Main IPC services
const launchMainService = accessor.get(ILaunchMainService); const launchMainService = accessor.get(ILaunchMainService);
const launchChannel = new LaunchChannel(launchMainService); const launchChannel = createChannelReceiver(launchMainService, { disableMarshalling: true });
this.mainIpcServer.registerChannel('launch', launchChannel); this.mainIpcServer.registerChannel('launch', launchChannel);
// Register more Electron IPC services // Register more Electron IPC services
@@ -551,8 +552,8 @@ export class CodeApplication extends Disposable {
const sharedProcessChannel = createChannelReceiver(sharedProcessMainService); const sharedProcessChannel = createChannelReceiver(sharedProcessMainService);
electronIpcServer.registerChannel('sharedProcess', sharedProcessChannel); electronIpcServer.registerChannel('sharedProcess', sharedProcessChannel);
const workspacesMainService = accessor.get(IWorkspacesMainService); const workspacesService = accessor.get(IWorkspacesService);
const workspacesChannel = new WorkspacesChannel(workspacesMainService, accessor.get(IWindowsMainService)); const workspacesChannel = createChannelReceiver(workspacesService);
electronIpcServer.registerChannel('workspaces', workspacesChannel); electronIpcServer.registerChannel('workspaces', workspacesChannel);
const menubarService = accessor.get(IMenubarService); const menubarService = accessor.get(IMenubarService);
@@ -560,7 +561,7 @@ export class CodeApplication extends Disposable {
electronIpcServer.registerChannel('menubar', menubarChannel); electronIpcServer.registerChannel('menubar', menubarChannel);
const urlService = accessor.get(IURLService); const urlService = accessor.get(IURLService);
const urlChannel = new URLServiceChannel(urlService); const urlChannel = createChannelReceiver(urlService);
electronIpcServer.registerChannel('url', urlChannel); electronIpcServer.registerChannel('url', urlChannel);
const storageMainService = accessor.get(IStorageMainService); const storageMainService = accessor.get(IStorageMainService);

View File

@@ -14,7 +14,8 @@ import { mkdirp } from 'vs/base/node/pfs';
import { validatePaths } from 'vs/code/node/paths'; import { validatePaths } from 'vs/code/node/paths';
import { LifecycleMainService, ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { LifecycleMainService, ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { LaunchChannelClient } from 'vs/platform/launch/electron-main/launchMainService'; import { createChannelSender } from 'vs/base/parts/ipc/node/ipc';
import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
@@ -272,8 +273,7 @@ class CodeMain {
}, 10000); }, 10000);
} }
const channel = client.getChannel('launch'); const launchService = createChannelSender<ILaunchMainService>(client.getChannel('launch'), { disableMarshalling: true });
const launchClient = new LaunchChannelClient(channel);
// Process Info // Process Info
if (environmentService.args.status) { if (environmentService.args.status) {
@@ -282,8 +282,8 @@ class CodeMain {
const sharedProcessClient = await connect(environmentService.sharedIPCHandle, 'main'); const sharedProcessClient = await connect(environmentService.sharedIPCHandle, 'main');
const diagnosticsChannel = sharedProcessClient.getChannel('diagnostics'); const diagnosticsChannel = sharedProcessClient.getChannel('diagnostics');
const diagnosticsService = new DiagnosticsService(diagnosticsChannel); const diagnosticsService = new DiagnosticsService(diagnosticsChannel);
const mainProcessInfo = await launchClient.getMainProcessInfo(); const mainProcessInfo = await launchService.getMainProcessInfo();
const remoteDiagnostics = await launchClient.getRemoteDiagnostics({ includeProcesses: true, includeWorkspaceMetadata: true }); const remoteDiagnostics = await launchService.getRemoteDiagnostics({ includeProcesses: true, includeWorkspaceMetadata: true });
const diagnostics = await diagnosticsService.getDiagnostics(mainProcessInfo, remoteDiagnostics); const diagnostics = await diagnosticsService.getDiagnostics(mainProcessInfo, remoteDiagnostics);
console.log(diagnostics); console.log(diagnostics);
@@ -293,12 +293,12 @@ class CodeMain {
// Windows: allow to set foreground // Windows: allow to set foreground
if (platform.isWindows) { if (platform.isWindows) {
await this.windowsAllowSetForegroundWindow(launchClient, logService); await this.windowsAllowSetForegroundWindow(launchService, logService);
} }
// Send environment over... // Send environment over...
logService.trace('Sending env to running instance...'); logService.trace('Sending env to running instance...');
await launchClient.start(environmentService.args, process.env as platform.IProcessEnvironment); await launchService.start(environmentService.args, process.env as platform.IProcessEnvironment);
// Cleanup // Cleanup
await client.dispose(); await client.dispose();
@@ -360,9 +360,9 @@ class CodeMain {
}); });
} }
private async windowsAllowSetForegroundWindow(client: LaunchChannelClient, logService: ILogService): Promise<void> { private async windowsAllowSetForegroundWindow(launchService: ILaunchMainService, logService: ILogService): Promise<void> {
if (platform.isWindows) { if (platform.isWindows) {
const processId = await client.getMainProcessId(); const processId = await launchService.getMainProcessId();
logService.trace('Sending some foreground love to the running instance:', processId); logService.trace('Sending some foreground love to the running instance:', processId);

View File

@@ -25,10 +25,9 @@ import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
import product from 'vs/platform/product/common/product'; import product from 'vs/platform/product/common/product';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; 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 { 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 { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; 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 { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';

View File

@@ -241,7 +241,7 @@ export abstract class EditorAction extends EditorCommand {
// --- Registration of commands and actions // --- Registration of commands and actions
export function registerLanguageCommand(id: string, handler: (accessor: ServicesAccessor, args: { [n: string]: any }) => any) { export function registerLanguageCommand<Args extends { [n: string]: any }>(id: string, handler: (accessor: ServicesAccessor, args: Args) => any) {
CommandsRegistry.registerCommand(id, (accessor, args) => handler(accessor, args || {})); CommandsRegistry.registerCommand(id, (accessor, args) => handler(accessor, args || {}));
} }

View File

@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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';
export const enum AuthTokenStatus {
Disabled = 'Disabled',
Inactive = 'Inactive',
Active = 'Active'
}
export const IAuthTokenService = createDecorator<IAuthTokenService>('IAuthTokenService');
export interface IAuthTokenService {
_serviceBrand: undefined;
readonly status: AuthTokenStatus;
readonly onDidChangeStatus: Event<AuthTokenStatus>;
getToken(): Promise<string | null>;
updateToken(token: string): Promise<void>;
refreshToken(): Promise<void>;
deleteToken(): Promise<void>;
}

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
import { IAuthTokenService } from 'vs/platform/auth/common/auth';
export class AuthTokenChannel implements IServerChannel {
constructor(private readonly service: IAuthTokenService) { }
listen(_: unknown, event: string): Event<any> {
switch (event) {
case 'onDidChangeStatus': return this.service.onDidChangeStatus;
}
throw new Error(`Event not found: ${event}`);
}
call(context: any, command: string, args?: any): Promise<any> {
switch (command) {
case '_getInitialStatus': return Promise.resolve(this.service.status);
case 'getToken': return this.service.getToken();
case 'updateToken': return this.service.updateToken(args[0]);
case 'refreshToken': return this.service.refreshToken();
case 'deleteToken': return this.service.deleteToken();
}
throw new Error('Invalid call');
}
}

View File

@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event, Emitter } from 'vs/base/common/event';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { Disposable } from 'vs/base/common/lifecycle';
import { IProductService } from 'vs/platform/product/common/productService';
const SERVICE_NAME = 'VS Code';
const ACCOUNT = 'MyAccount';
export class AuthTokenService extends Disposable implements IAuthTokenService {
_serviceBrand: undefined;
private _status: AuthTokenStatus = AuthTokenStatus.Disabled;
get status(): AuthTokenStatus { return this._status; }
private _onDidChangeStatus: Emitter<AuthTokenStatus> = this._register(new Emitter<AuthTokenStatus>());
readonly onDidChangeStatus: Event<AuthTokenStatus> = this._onDidChangeStatus.event;
constructor(
@ICredentialsService private readonly credentialsService: ICredentialsService,
@IProductService productService: IProductService,
) {
super();
if (productService.settingsSyncStoreUrl) {
this._status = AuthTokenStatus.Inactive;
this.getToken().then(token => {
if (token) {
this.setStatus(AuthTokenStatus.Active);
}
});
}
}
getToken(): Promise<string | null> {
if (this.status === AuthTokenStatus.Disabled) {
throw new Error('Not enabled');
}
return this.credentialsService.getPassword(SERVICE_NAME, ACCOUNT);
}
async updateToken(token: string): Promise<void> {
if (this.status === AuthTokenStatus.Disabled) {
throw new Error('Not enabled');
}
await this.credentialsService.setPassword(SERVICE_NAME, ACCOUNT, token);
this.setStatus(AuthTokenStatus.Active);
}
async refreshToken(): Promise<void> {
if (this.status === AuthTokenStatus.Disabled) {
throw new Error('Not enabled');
}
await this.deleteToken();
}
async deleteToken(): Promise<void> {
if (this.status === AuthTokenStatus.Disabled) {
throw new Error('Not enabled');
}
await this.credentialsService.deletePassword(SERVICE_NAME, ACCOUNT);
this.setStatus(AuthTokenStatus.Inactive);
}
private setStatus(status: AuthTokenStatus): void {
if (this._status !== status) {
this._status = status;
this._onDidChangeStatus.fire(status);
}
}
}

View File

@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ICredentialsService = createDecorator<ICredentialsService>('ICredentialsService');
export interface ICredentialsService {
_serviceBrand: undefined;
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
findCredentials(service: string): Promise<Array<{ account: string, password: string }>>;
}

View File

@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { IdleValue } from 'vs/base/common/async';
type KeytarModule = typeof import('keytar');
export class KeytarCredentialsService implements ICredentialsService {
_serviceBrand: undefined;
private readonly _keytar = new IdleValue<Promise<KeytarModule>>(() => import('keytar'));
async getPassword(service: string, account: string): Promise<string | null> {
const keytar = await this._keytar.getValue();
return keytar.getPassword(service, account);
}
async setPassword(service: string, account: string, password: string): Promise<void> {
const keytar = await this._keytar.getValue();
return keytar.setPassword(service, account, password);
}
async deletePassword(service: string, account: string): Promise<boolean> {
const keytar = await this._keytar.getValue();
return keytar.deletePassword(service, account);
}
async findPassword(service: string): Promise<string | null> {
const keytar = await this._keytar.getValue();
return keytar.findPassword(service);
}
async findCredentials(service: string): Promise<Array<{ account: string, password: string }>> {
const keytar = await this._keytar.getValue();
return keytar.findCredentials(service);
}
}

View File

@@ -6,17 +6,15 @@
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron'; import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron';
import { INativeOpenInWindowOptions } from 'vs/platform/windows/node/window';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IOpenedWindow, OpenContext, IWindowOpenable, IOpenInWindowOptions, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IOpenedWindow, OpenContext, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform'; import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import { IElectronService } from 'vs/platform/electron/node/electron'; import { IElectronService } from 'vs/platform/electron/node/electron';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { AddFirstParameterToFunctions } from 'vs/base/common/types'; 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<IElectronService, Promise<any> /* only methods, not events */, number /* window ID */> { export class ElectronMainService implements AddFirstParameterToFunctions<IElectronService, Promise<any> /* only methods, not events */, number /* window ID */> {
@@ -25,8 +23,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
constructor( constructor(
@IWindowsMainService private readonly windowsMainService: IWindowsMainService, @IWindowsMainService private readonly windowsMainService: IWindowsMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IEnvironmentService private readonly environmentService: IEnvironmentService, @IEnvironmentService private readonly environmentService: IEnvironmentService
@IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService
) { ) {
} }
@@ -76,7 +73,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
this.windowsMainService.openEmptyWindow(OpenContext.API, options); this.windowsMainService.openEmptyWindow(OpenContext.API, options);
} }
async openInWindow(windowId: number, toOpen: IWindowOpenable[], options: IOpenInWindowOptions = Object.create(null)): Promise<void> { async openInWindow(windowId: number, toOpen: IWindowOpenable[], options: INativeOpenInWindowOptions = Object.create(null)): Promise<void> {
if (toOpen.length > 0) { if (toOpen.length > 0) {
this.windowsMainService.open({ this.windowsMainService.open({
context: OpenContext.API, context: OpenContext.API,
@@ -332,33 +329,6 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
//#endregion //#endregion
//#region Workspaces History
readonly onRecentlyOpenedChange = this.workspacesHistoryMainService.onRecentlyOpenedChange;
async getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
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<void> {
return this.workspacesHistoryMainService.addRecentlyOpened(recents);
}
async removeFromRecentlyOpened(windowId: number, paths: URI[]): Promise<void> {
return this.workspacesHistoryMainService.removeFromRecentlyOpened(paths);
}
async clearRecentlyOpened(windowId: number): Promise<void> {
return this.workspacesHistoryMainService.clearRecentlyOpened();
}
//#endregion
//#region Debug //#region Debug
// TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060) // TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060)

View File

@@ -6,13 +6,12 @@
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'electron'; import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'electron';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IWindowOpenable, IOpenInWindowOptions, IOpenEmptyWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows'; import { IWindowOpenable, IOpenEmptyWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; 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 { ParsedArgs } from 'vscode-minimist';
import { IProcessEnvironment } from 'vs/base/common/platform'; import { IProcessEnvironment } from 'vs/base/common/platform';
import { INativeOpenInWindowOptions } from 'vs/platform/windows/node/window';
export const IElectronService = createDecorator<IElectronService>('electronService'); export const IElectronService = createDecorator<IElectronService>('electronService');
@@ -35,7 +34,7 @@ export interface IElectronService {
getActiveWindowId(): Promise<number | undefined>; getActiveWindowId(): Promise<number | undefined>;
openEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void>; openEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
openInWindow(toOpen: IWindowOpenable[], options?: IOpenInWindowOptions): Promise<void>; openInWindow(toOpen: IWindowOpenable[], options?: INativeOpenInWindowOptions): Promise<void>;
toggleFullScreen(): Promise<void>; toggleFullScreen(): Promise<void>;
@@ -89,13 +88,6 @@ export interface IElectronService {
// Connectivity // Connectivity
resolveProxy(url: string): Promise<string | undefined>; resolveProxy(url: string): Promise<string | undefined>;
// Workspaces History
readonly onRecentlyOpenedChange: Event<void>;
getRecentlyOpened(): Promise<IRecentlyOpened>;
addRecentlyOpened(recents: IRecent[]): Promise<void>;
removeFromRecentlyOpened(paths: URI[]): Promise<void>;
clearRecentlyOpened(): Promise<void>;
// Debug (TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060) // Debug (TODO@Isidor move into debug IPC channel (https://github.com/microsoft/vscode/issues/81060)
openExtensionDevelopmentHostWindow(args: ParsedArgs, env: IProcessEnvironment): Promise<void>; openExtensionDevelopmentHostWindow(args: ParsedArgs, env: IProcessEnvironment): Promise<void>;
} }

View File

@@ -22,40 +22,42 @@ export namespace _util {
// --- interfaces ------ // --- interfaces ------
type BrandedService = { _serviceBrand: undefined };
export interface IConstructorSignature0<T> { export interface IConstructorSignature0<T> {
new(...services: { _serviceBrand: undefined; }[]): T; new(...services: BrandedService[]): T;
} }
export interface IConstructorSignature1<A1, T> { export interface IConstructorSignature1<A1, T> {
new(first: A1, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature2<A1, A2, T> { export interface IConstructorSignature2<A1, A2, T> {
new(first: A1, second: A2, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature3<A1, A2, A3, T> { export interface IConstructorSignature3<A1, A2, A3, T> {
new(first: A1, second: A2, third: A3, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, third: A3, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature4<A1, A2, A3, A4, T> { export interface IConstructorSignature4<A1, A2, A3, A4, T> {
new(first: A1, second: A2, third: A3, fourth: A4, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, third: A3, fourth: A4, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature5<A1, A2, A3, A4, A5, T> { export interface IConstructorSignature5<A1, A2, A3, A4, A5, T> {
new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature6<A1, A2, A3, A4, A5, A6, T> { export interface IConstructorSignature6<A1, A2, A3, A4, A5, A6, T> {
new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature7<A1, A2, A3, A4, A5, A6, A7, T> { export interface IConstructorSignature7<A1, A2, A3, A4, A5, A6, A7, T> {
new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, ...services: BrandedService[]): T;
} }
export interface IConstructorSignature8<A1, A2, A3, A4, A5, A6, A7, A8, T> { export interface IConstructorSignature8<A1, A2, A3, A4, A5, A6, A7, A8, T> {
new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8, ...services: { _serviceBrand: undefined; }[]): T; new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8, ...services: BrandedService[]): T;
} }
export interface ServicesAccessor { export interface ServicesAccessor {

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { IURLService } from 'vs/platform/url/common/url'; import { IURLService } from 'vs/platform/url/common/url';
import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform'; import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
@@ -16,7 +15,6 @@ import { IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/wor
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { BrowserWindow, ipcMain, Event as IpcEvent, app } from 'electron'; import { BrowserWindow, ipcMain, Event as IpcEvent, app } from 'electron';
import { Event } from 'vs/base/common/event';
import { coalesce } from 'vs/base/common/arrays'; import { coalesce } from 'vs/base/common/arrays';
import { IDiagnosticInfoOptions, IDiagnosticInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { IDiagnosticInfoOptions, IDiagnosticInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { IMainProcessInfo, IWindowInfo } from 'vs/platform/launch/common/launch'; import { IMainProcessInfo, IWindowInfo } from 'vs/platform/launch/common/launch';
@@ -60,64 +58,6 @@ export interface ILaunchMainService {
getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<(IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]>; getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<(IRemoteDiagnosticInfo | IRemoteDiagnosticError)[]>;
} }
export class LaunchChannel implements IServerChannel {
constructor(private service: ILaunchMainService) { }
listen<T>(_: unknown, event: string): Event<T> {
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, arg: any): Promise<any> {
switch (command) {
case 'start':
const { args, userEnv } = arg as IStartArguments;
return this.service.start(args, userEnv);
case 'get-main-process-id':
return this.service.getMainProcessId();
case 'get-main-process-info':
return this.service.getMainProcessInfo();
case 'get-logs-path':
return this.service.getLogsPath();
case 'get-remote-diagnostics':
return this.service.getRemoteDiagnostics(arg);
}
throw new Error(`Call not found: ${command}`);
}
}
export class LaunchChannelClient implements ILaunchMainService {
_serviceBrand: undefined;
constructor(private channel: IChannel) { }
start(args: ParsedArgs, userEnv: IProcessEnvironment): Promise<void> {
return this.channel.call('start', { args, userEnv });
}
getMainProcessId(): Promise<number> {
return this.channel.call('get-main-process-id', null);
}
getMainProcessInfo(): Promise<IMainProcessInfo> {
return this.channel.call('get-main-process-info', null);
}
getLogsPath(): Promise<string> {
return this.channel.call('get-logs-path', null);
}
getRemoteDiagnostics(options: IRemoteDiagnosticOptions): Promise<IRemoteDiagnosticInfo[]> {
return this.channel.call('get-remote-diagnostics', options);
}
}
export class LaunchMainService implements ILaunchMainService { export class LaunchMainService implements ILaunchMainService {
_serviceBrand: undefined; _serviceBrand: undefined;

View File

@@ -1,26 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
export class LocalizationsService implements ILocalizationsService {
_serviceBrand: undefined;
private channel: IChannel;
constructor(@ISharedProcessService sharedProcessService: ISharedProcessService) {
this.channel = sharedProcessService.getChannel('localizations');
}
get onDidLanguagesChange(): Event<void> { return this.channel.listen('onDidLanguagesChange'); }
getLanguageIds(type?: LanguageType): Promise<string[]> {
return this.channel.call('getLanguageIds', type);
}
}

View File

@@ -1,33 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
export class LocalizationsChannel implements IServerChannel {
onDidLanguagesChange: Event<void>;
constructor(private service: ILocalizationsService) {
this.onDidLanguagesChange = Event.buffer(service.onDidLanguagesChange, true);
}
listen(_: unknown, event: string): Event<any> {
switch (event) {
case 'onDidLanguagesChange': return this.onDidLanguagesChange;
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, arg?: any): Promise<any> {
switch (command) {
case 'getLanguageIds': return this.service.getLanguageIds(arg);
}
throw new Error(`Call not found: ${command}`);
}
}

View File

@@ -21,7 +21,7 @@ export interface IRequestService {
resolveProxy(url: string): Promise<string | undefined>; resolveProxy(url: string): Promise<string | undefined>;
} }
function isSuccess(context: IRequestContext): boolean { export function isSuccess(context: IRequestContext): boolean {
return (context.res.statusCode && context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223; return (context.res.statusCode && context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223;
} }

View File

@@ -4,49 +4,12 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel, IClientRouter, IConnectionHub, Client } from 'vs/base/parts/ipc/common/ipc'; import { IChannel, IServerChannel, IClientRouter, IConnectionHub, Client } from 'vs/base/parts/ipc/common/ipc';
import { URI, UriComponents } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; import { IURLHandler } from 'vs/platform/url/common/url';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { first } from 'vs/base/common/arrays'; import { first } from 'vs/base/common/arrays';
export class URLServiceChannel implements IServerChannel {
constructor(private service: IURLService) { }
listen<T>(_: unknown, event: string): Event<T> {
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, arg?: any): Promise<any> {
switch (command) {
case 'open': return this.service.open(URI.revive(arg));
}
throw new Error(`Call not found: ${command}`);
}
}
export class URLServiceChannelClient implements IURLService {
_serviceBrand: undefined;
constructor(private channel: IChannel) { }
open(url: URI): Promise<boolean> {
return this.channel.call('open', url.toJSON());
}
registerHandler(handler: IURLHandler): IDisposable {
throw new Error('Not implemented.');
}
create(_options?: Partial<UriComponents>): URI {
throw new Error('Method not implemented.');
}
}
export class URLHandlerChannel implements IServerChannel { export class URLHandlerChannel implements IServerChannel {
constructor(private handler: IURLHandler) { } constructor(private handler: IURLHandler) { }

View File

@@ -79,6 +79,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
return false; return false;
} }
this.logService.trace('Extensions: Started synchronising extensions...');
this.setStatus(SyncStatus.Syncing); this.setStatus(SyncStatus.Syncing);
try { try {
@@ -142,7 +143,9 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
remoteData = await this.writeToRemote(remote, remoteData.ref); remoteData = await this.writeToRemote(remote, remoteData.ref);
} }
if (remoteData.content) { if (remoteData.content
&& (!lastSyncData || lastSyncData.ref !== remoteData.ref)
) {
// update last sync // update last sync
this.logService.info('Extensions: Updating last synchronised extensions...'); this.logService.info('Extensions: Updating last synchronised extensions...');
await this.updateLastSyncValue(remoteData); await this.updateLastSyncValue(remoteData);

View File

@@ -177,6 +177,8 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
// Delete the preview // Delete the preview
await this.fileService.del(this.environmentService.settingsSyncPreviewResource); await this.fileService.del(this.environmentService.settingsSyncPreviewResource);
} else {
this.logService.trace('Settings: No changes found during synchronising settings.');
} }
this.logService.trace('Settings: Finised synchronising settings.'); this.logService.trace('Settings: Finised synchronising settings.');

View File

@@ -104,11 +104,6 @@ export interface IUserDataSyncStoreService {
readonly enabled: boolean; readonly enabled: boolean;
readonly loggedIn: boolean;
readonly onDidChangeLoggedIn: Event<boolean>;
login(): Promise<void>;
logout(): Promise<void>;
read(key: string, oldValue: IUserData | null): Promise<IUserData>; read(key: string, oldValue: IUserData | null): Promise<IUserData>;
write(key: string, content: string, ref: string | null): Promise<string>; write(key: string, content: string, ref: string | null): Promise<string>;
} }

View File

@@ -12,6 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { timeout } from 'vs/base/common/async'; import { timeout } from 'vs/base/common/async';
import { ExtensionsSynchroniser } from 'vs/platform/userDataSync/common/extensionsSync'; import { ExtensionsSynchroniser } from 'vs/platform/userDataSync/common/extensionsSync';
import { IExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
export class UserDataSyncService extends Disposable implements IUserDataSyncService { export class UserDataSyncService extends Disposable implements IUserDataSyncService {
@@ -35,6 +36,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
constructor( constructor(
@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService, @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
@IInstantiationService private readonly instantiationService: IInstantiationService, @IInstantiationService private readonly instantiationService: IInstantiationService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
) { ) {
super(); super();
this.settingsSynchroniser = this._register(this.instantiationService.createInstance(SettingsSynchroniser)); this.settingsSynchroniser = this._register(this.instantiationService.createInstance(SettingsSynchroniser));
@@ -43,12 +45,16 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
this.updateStatus(); this.updateStatus();
this._register(Event.any(...this.synchronisers.map(s => Event.map(s.onDidChangeStatus, () => undefined)))(() => this.updateStatus())); this._register(Event.any(...this.synchronisers.map(s => Event.map(s.onDidChangeStatus, () => undefined)))(() => this.updateStatus()));
this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => s.onDidChangeLocal)); this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => s.onDidChangeLocal));
this._register(authTokenService.onDidChangeStatus(() => this.onDidChangeAuthTokenStatus()));
} }
async sync(_continue?: boolean): Promise<boolean> { async sync(_continue?: boolean): Promise<boolean> {
if (!this.userDataSyncStoreService.enabled) { if (!this.userDataSyncStoreService.enabled) {
throw new Error('Not enabled'); throw new Error('Not enabled');
} }
if (this.authTokenService.status === AuthTokenStatus.Inactive) {
return Promise.reject('Not Authenticated. Please sign in to start sync.');
}
for (const synchroniser of this.synchronisers) { for (const synchroniser of this.synchronisers) {
if (!await synchroniser.sync(_continue)) { if (!await synchroniser.sync(_continue)) {
return false; return false;
@@ -105,36 +111,51 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return null; return null;
} }
private onDidChangeAuthTokenStatus(): void {
if (this.authTokenService.status === AuthTokenStatus.Inactive) {
this.stop();
}
}
} }
export class UserDataAutoSync extends Disposable { export class UserDataAutoSync extends Disposable {
private enabled: boolean = false;
constructor( constructor(
@IConfigurationService private readonly configurationService: IConfigurationService, @IConfigurationService private readonly configurationService: IConfigurationService,
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService, @IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
@IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService, @IUserDataSyncStoreService userDataSyncStoreService: IUserDataSyncStoreService,
@IUserDataSyncLogService private readonly userDataSyncLogService: IUserDataSyncLogService, @IUserDataSyncLogService private readonly userDataSyncLogService: IUserDataSyncLogService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
) { ) {
super(); super();
if (userDataSyncStoreService.enabled) { this.updateEnablement();
this.sync(true); this.sync(true);
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => { this._register(Event.any<any>(authTokenService.onDidChangeStatus, userDataSyncService.onDidChangeStatus)(() => this.updateEnablement()));
if (this.isSyncEnabled()) { this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => this.updateEnablement()));
userDataSyncLogService.info('Syncing configuration started...');
this.sync(true);
} else {
this.userDataSyncService.stop();
userDataSyncLogService.info('Syncing configuration stopped.');
}
}));
// Sync immediately if there is a local change. // Sync immediately if there is a local change.
this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false))); this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false)));
}
private updateEnablement(): void {
const enabled = this.isSyncEnabled();
if (this.enabled !== enabled) {
this.enabled = enabled;
if (this.enabled) {
this.userDataSyncLogService.info('Syncing configuration started');
this.sync(true);
} else {
this.userDataSyncService.stop();
this.userDataSyncLogService.info('Syncing configuration stopped.');
}
} }
} }
private async sync(loop: boolean): Promise<void> { private async sync(loop: boolean): Promise<void> {
if (this.isSyncEnabled()) { if (this.enabled) {
try { try {
await this.userDataSyncService.sync(); await this.userDataSyncService.sync();
} catch (e) { } catch (e) {
@@ -148,7 +169,9 @@ export class UserDataAutoSync extends Disposable {
} }
private isSyncEnabled(): boolean { private isSyncEnabled(): boolean {
return this.configurationService.getValue<boolean>('configurationSync.enable'); return this.configurationService.getValue<boolean>('configurationSync.enable')
&& this.userDataSyncService.status !== SyncStatus.Uninitialized
&& this.authTokenService.status !== AuthTokenStatus.Inactive;
} }
} }

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Disposable, } from 'vs/base/common/lifecycle'; import { Disposable, } from 'vs/base/common/lifecycle';
import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError } from 'vs/platform/userDataSync/common/userDataSync'; import { IUserData, IUserDataSyncStoreService, UserDataSyncStoreErrorCode, UserDataSyncStoreError, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
import { IProductService } from 'vs/platform/product/common/productService'; import { IProductService } from 'vs/platform/product/common/productService';
import { Emitter, Event } from 'vs/base/common/event'; import { IRequestService, asText, isSuccess } from 'vs/platform/request/common/request';
import { IRequestService, asText } from 'vs/platform/request/common/request';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { joinPath } from 'vs/base/common/resources'; import { joinPath } from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { IHeaders } from 'vs/base/parts/request/common/request'; import { IHeaders, IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
export class UserDataSyncStoreService extends Disposable implements IUserDataSyncStoreService { export class UserDataSyncStoreService extends Disposable implements IUserDataSyncStoreService {
@@ -19,24 +19,15 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
get enabled(): boolean { return !!this.productService.settingsSyncStoreUrl; } get enabled(): boolean { return !!this.productService.settingsSyncStoreUrl; }
private _loggedIn: boolean = false;
get loggedIn(): boolean { return this._loggedIn; }
private readonly _onDidChangeLoggedIn: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onDidChangeLoggedIn: Event<boolean> = this._onDidChangeLoggedIn.event;
constructor( constructor(
@IProductService private readonly productService: IProductService, @IProductService private readonly productService: IProductService,
@IRequestService private readonly requestService: IRequestService, @IRequestService private readonly requestService: IRequestService,
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
) { ) {
super(); super();
} }
async login(): Promise<void> {
}
async logout(): Promise<void> {
}
async read(key: string, oldValue: IUserData | null): Promise<IUserData> { async read(key: string, oldValue: IUserData | null): Promise<IUserData> {
if (!this.enabled) { if (!this.enabled) {
return Promise.reject(new Error('No settings sync store url configured.')); return Promise.reject(new Error('No settings sync store url configured.'));
@@ -48,13 +39,17 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
headers['If-None-Match'] = oldValue.ref; headers['If-None-Match'] = oldValue.ref;
} }
const context = await this.requestService.request({ type: 'GET', url, headers }, CancellationToken.None); const context = await this.request({ type: 'GET', url, headers }, CancellationToken.None);
if (context.res.statusCode === 304) { if (context.res.statusCode === 304) {
// There is no new value. Hence return the old value. // There is no new value. Hence return the old value.
return oldValue!; return oldValue!;
} }
if (!isSuccess(context)) {
throw new Error('Server returned ' + context.res.statusCode);
}
const ref = context.res.headers['etag']; const ref = context.res.headers['etag'];
if (!ref) { if (!ref) {
throw new Error('Server did not return the ref'); throw new Error('Server did not return the ref');
@@ -74,13 +69,17 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
headers['If-Match'] = ref; headers['If-Match'] = ref;
} }
const context = await this.requestService.request({ type: 'POST', url, data, headers }, CancellationToken.None); const context = await this.request({ type: 'POST', url, data, headers }, CancellationToken.None);
if (context.res.statusCode === 412) { if (context.res.statusCode === 412) {
// There is a new value. Throw Rejected Error // There is a new value. Throw Rejected Error
throw new UserDataSyncStoreError('New data exists', UserDataSyncStoreErrorCode.Rejected); throw new UserDataSyncStoreError('New data exists', UserDataSyncStoreErrorCode.Rejected);
} }
if (!isSuccess(context)) {
throw new Error('Server returned ' + context.res.statusCode);
}
const newRef = context.res.headers['etag']; const newRef = context.res.headers['etag'];
if (!newRef) { if (!newRef) {
throw new Error('Server did not return the ref'); throw new Error('Server did not return the ref');
@@ -88,4 +87,27 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
return newRef; return newRef;
} }
private async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
if (this.authTokenService.status !== AuthTokenStatus.Disabled) {
const authToken = await this.authTokenService.getToken();
if (!authToken) {
return Promise.reject(new Error('No Auth Token Available.'));
}
options.headers = options.headers || {};
options.headers['authorization'] = `Bearer ${authToken}`;
}
const context = await this.requestService.request(options, token);
if (context.res.statusCode === 401) {
// Not Authorized
this.logService.info('Authroization Failed.');
this.authTokenService.refreshToken();
Promise.reject('Authroization Failed.');
}
return context;
}
} }

View File

@@ -22,11 +22,8 @@ export interface IOpenedWindow {
export interface IOpenInWindowOptions { export interface IOpenInWindowOptions {
forceNewWindow?: boolean; forceNewWindow?: boolean;
forceReuseWindow?: boolean; forceReuseWindow?: boolean;
diffMode?: boolean;
addMode?: boolean;
gotoLineMode?: boolean;
noRecentEntry?: boolean; noRecentEntry?: boolean;
waitMarkerFileURI?: URI;
} }
export interface IOpenEmptyWindowOptions { export interface IOpenEmptyWindowOptions {

View File

@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IOpenInWindowOptions } from 'vs/platform/windows/common/windows';
import { URI } from 'vs/base/common/uri';
export interface INativeOpenInWindowOptions extends IOpenInWindowOptions {
diffMode?: boolean;
addMode?: boolean;
gotoLineMode?: boolean;
waitMarkerFileURI?: URI;
}

View File

@@ -12,35 +12,23 @@ import { IWorkspaceIdentifier, IStoredWorkspaceFolder, isRawFileWorkspaceFolder,
export const IWorkspaceContextService = createDecorator<IWorkspaceContextService>('contextService'); export const IWorkspaceContextService = createDecorator<IWorkspaceContextService>('contextService');
export const enum WorkbenchState {
EMPTY = 1,
FOLDER,
WORKSPACE
}
export interface IWorkspaceFoldersChangeEvent {
added: IWorkspaceFolder[];
removed: IWorkspaceFolder[];
changed: IWorkspaceFolder[];
}
export interface IWorkspaceContextService { export interface IWorkspaceContextService {
_serviceBrand: undefined; _serviceBrand: undefined;
/** /**
* An event which fires on workbench state changes. * An event which fires on workbench state changes.
*/ */
onDidChangeWorkbenchState: Event<WorkbenchState>; readonly onDidChangeWorkbenchState: Event<WorkbenchState>;
/** /**
* An event which fires on workspace name changes. * An event which fires on workspace name changes.
*/ */
onDidChangeWorkspaceName: Event<void>; readonly onDidChangeWorkspaceName: Event<void>;
/** /**
* An event which fires on workspace folders change. * An event which fires on workspace folders change.
*/ */
onDidChangeWorkspaceFolders: Event<IWorkspaceFoldersChangeEvent>; readonly onDidChangeWorkspaceFolders: Event<IWorkspaceFoldersChangeEvent>;
/** /**
* Provides access to the complete workspace object. * Provides access to the complete workspace object.
@@ -79,6 +67,18 @@ export interface IWorkspaceContextService {
isInsideWorkspace(resource: URI): boolean; isInsideWorkspace(resource: URI): boolean;
} }
export const enum WorkbenchState {
EMPTY = 1,
FOLDER,
WORKSPACE
}
export interface IWorkspaceFoldersChangeEvent {
added: IWorkspaceFolder[];
removed: IWorkspaceFolder[];
changed: IWorkspaceFolder[];
}
export namespace IWorkspace { export namespace IWorkspace {
export function isIWorkspace(thing: any): thing is IWorkspace { export function isIWorkspace(thing: any): thing is IWorkspace {
return thing && typeof thing === 'object' return thing && typeof thing === 'object'
@@ -106,6 +106,7 @@ export interface IWorkspace {
} }
export interface IWorkspaceFolderData { export interface IWorkspaceFolderData {
/** /**
* The associated URI for this workspace folder. * The associated URI for this workspace folder.
*/ */
@@ -264,5 +265,6 @@ export function toWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[],
} }
} }
} }
return result; return result;
} }

View File

@@ -17,11 +17,67 @@ import { normalizeDriveLetter } from 'vs/base/common/labels';
import { toSlashes } from 'vs/base/common/extpath'; import { toSlashes } from 'vs/base/common/extpath';
import { FormattingOptions } from 'vs/base/common/jsonFormatter'; import { FormattingOptions } from 'vs/base/common/jsonFormatter';
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; 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_EXTENSION = 'code-workspace';
export const WORKSPACE_FILTER = [{ name: localize('codeWorkspace', "Code Workspace"), extensions: [WORKSPACE_EXTENSION] }]; export const WORKSPACE_FILTER = [{ name: localize('codeWorkspace', "Code Workspace"), extensions: [WORKSPACE_EXTENSION] }];
export const UNTITLED_WORKSPACE_NAME = 'workspace.json'; export const UNTITLED_WORKSPACE_NAME = 'workspace.json';
export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService');
export interface IWorkspacesService {
_serviceBrand: undefined;
// Management
enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | undefined>;
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier>;
deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise<void>;
getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier>;
// History
readonly onRecentlyOpenedChange: CommonEvent<void>;
addRecentlyOpened(recents: IRecent[]): Promise<void>;
removeFromRecentlyOpened(workspaces: URI[]): Promise<void>;
clearRecentlyOpened(): Promise<void>;
getRecentlyOpened(): Promise<IRecentlyOpened>;
}
export interface IRecentlyOpened {
workspaces: Array<IRecentWorkspace | IRecentFolder>;
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. * A single folder workspace identifier is just the path to the folder.
*/ */
@@ -76,11 +132,6 @@ export interface IStoredWorkspace {
remoteAuthority?: string; remoteAuthority?: string;
} }
export interface IWorkspaceSavedEvent {
workspace: IWorkspaceIdentifier;
oldConfigPath: string;
}
export interface IWorkspaceFolderCreationData { export interface IWorkspaceFolderCreationData {
uri: URI; uri: URI;
name?: string; name?: string;
@@ -96,21 +147,6 @@ export interface IEnterWorkspaceResult {
backupPath?: string; backupPath?: string;
} }
export const IWorkspacesService = createDecorator<IWorkspacesService>('workspacesService');
export interface IWorkspacesService {
_serviceBrand: undefined;
enterWorkspace(path: URI): Promise<IEnterWorkspaceResult | undefined>;
createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier>;
deleteUntitledWorkspace(workspace: IWorkspaceIdentifier): Promise<void>;
getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier>;
}
export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolderWorkspaceIdentifier { export function isSingleFolderWorkspaceIdentifier(obj: any): obj is ISingleFolderWorkspaceIdentifier {
return obj instanceof URI; return obj instanceof URI;
} }
@@ -267,3 +303,129 @@ export function useSlashForPath(storedFolders: IStoredWorkspaceFolder[]): boolea
} }
return true; return true;
} }
//#region Workspace Storage
interface ISerializedRecentlyOpened {
workspaces3: Array<ISerializedWorkspace | string>; // workspace or URI.toString() // added in 1.32
workspaceLabels?: Array<string | null>; // added in 1.33
files2: string[]; // files as URI.toString() // added in 1.32
fileLabels?: Array<string | null>; // added in 1.33
}
interface ILegacySerializedRecentlyOpened {
workspaces2: Array<ILegacySerializedWorkspace | string>; // legacy, configPath as file path
workspaces: Array<ILegacySerializedWorkspace | string | UriComponents>; // 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 <T>(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(<UriComponents>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

View File

@@ -1,41 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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<IRecentWorkspace | IRecentFolder>;
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');
}

View File

@@ -1,129 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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<ISerializedWorkspace | string>; // workspace or URI.toString() // added in 1.32
workspaceLabels?: Array<string | null>; // added in 1.33
files2: string[]; // files as URI.toString() // added in 1.32
fileLabels?: Array<string | null>; // added in 1.33
}
interface ILegacySerializedRecentlyOpened {
workspaces2: Array<ILegacySerializedWorkspace | string>; // legacy, configPath as file path
workspaces: Array<ILegacySerializedWorkspace | string | UriComponents>; // 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 <T>(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(<UriComponents>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;
}

View File

@@ -12,16 +12,14 @@ import { getBaseLabel, getPathLabel } from 'vs/base/common/labels';
import { IPath } from 'vs/platform/windows/common/windows'; import { IPath } from 'vs/platform/windows/common/windows';
import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
import { isWindows, isMacintosh } from 'vs/base/common/platform'; 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 { 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 { ThrottledDelayer } from 'vs/base/common/async';
import { isEqual as areResourcesEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources'; import { isEqual as areResourcesEqual, dirname, originalFSPath, basename } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { getSimpleWorkspaceLabel } from 'vs/platform/label/common/label'; 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 { exists } from 'vs/base/node/pfs';
import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
@@ -32,7 +30,7 @@ export interface IWorkspacesHistoryMainService {
_serviceBrand: undefined; _serviceBrand: undefined;
onRecentlyOpenedChange: CommonEvent<void>; readonly onRecentlyOpenedChange: CommonEvent<void>;
addRecentlyOpened(recents: IRecent[]): void; addRecentlyOpened(recents: IRecent[]): void;
getRecentlyOpened(currentWorkspace?: IWorkspaceIdentifier, currentFolder?: ISingleFolderWorkspaceIdentifier, currentFiles?: IPath[]): IRecentlyOpened; getRecentlyOpened(currentWorkspace?: IWorkspaceIdentifier, currentFolder?: ISingleFolderWorkspaceIdentifier, currentFiles?: IPath[]): IRecentlyOpened;

View File

@@ -1,58 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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<T>(_: unknown, event: string): Event<T> {
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, arg?: any): Promise<any> {
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}`);
}
}

View File

@@ -20,18 +20,13 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { originalFSPath, isEqualOrParent, joinPath } from 'vs/base/common/resources'; import { originalFSPath, isEqualOrParent, joinPath } from 'vs/base/common/resources';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export interface IStoredWorkspace {
folders: IStoredWorkspaceFolder[];
remoteAuthority?: string;
}
export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService'); export const IWorkspacesMainService = createDecorator<IWorkspacesMainService>('workspacesMainService');
export interface IWorkspacesMainService { export interface IWorkspacesMainService {
_serviceBrand: undefined; _serviceBrand: undefined;
onUntitledWorkspaceDeleted: Event<IWorkspaceIdentifier>; readonly onUntitledWorkspaceDeleted: Event<IWorkspaceIdentifier>;
createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier; createUntitledWorkspaceSync(folders?: IWorkspaceFolderCreationData[]): IWorkspaceIdentifier;
@@ -50,6 +45,11 @@ export interface IWorkspacesMainService {
getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier>; getWorkspaceIdentifier(workspacePath: URI): Promise<IWorkspaceIdentifier>;
} }
export interface IStoredWorkspace {
folders: IStoredWorkspaceFolder[];
remoteAuthority?: string;
}
export class WorkspacesMainService extends Disposable implements IWorkspacesMainService { export class WorkspacesMainService extends Disposable implements IWorkspacesMainService {
_serviceBrand: undefined; _serviceBrand: undefined;

View File

@@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. 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<IWorkspacesService, Promise<any> /* 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<IEnterWorkspaceResult | undefined> {
const window = this.windowsMainService.getWindowById(windowId);
if (window) {
return this.windowsMainService.enterWorkspace(window, path);
}
return undefined;
}
createUntitledWorkspace(windowId: number, folders?: IWorkspaceFolderCreationData[], remoteAuthority?: string): Promise<IWorkspaceIdentifier> {
return this.workspacesMainService.createUntitledWorkspace(folders, remoteAuthority);
}
deleteUntitledWorkspace(windowId: number, workspace: IWorkspaceIdentifier): Promise<void> {
return this.workspacesMainService.deleteUntitledWorkspace(workspace);
}
getWorkspaceIdentifier(windowId: number, workspacePath: URI): Promise<IWorkspaceIdentifier> {
return this.workspacesMainService.getWorkspaceIdentifier(workspacePath);
}
//#endregion
//#region Workspaces History
readonly onRecentlyOpenedChange = this.workspacesHistoryMainService.onRecentlyOpenedChange;
async getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
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<void> {
return this.workspacesHistoryMainService.addRecentlyOpened(recents);
}
async removeFromRecentlyOpened(windowId: number, paths: URI[]): Promise<void> {
return this.workspacesHistoryMainService.removeFromRecentlyOpened(paths);
}
async clearRecentlyOpened(windowId: number): Promise<void> {
return this.workspacesHistoryMainService.clearRecentlyOpened();
}
//#endregion
}

View File

@@ -2,14 +2,12 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as assert from 'assert'; import * as assert from 'assert';
import * as os from 'os'; import * as os from 'os';
import * as path from 'vs/base/common/path'; import * as path from 'vs/base/common/path';
import { IWorkspaceIdentifier, IRecentlyOpened, isRecentFolder, IRecentFolder, IRecentWorkspace, toStoreData, restoreRecentlyOpened } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri'; 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'; import { NullLogService } from 'vs/platform/log/common/log';
function toWorkspace(uri: URI): IWorkspaceIdentifier { function toWorkspace(uri: URI): IWorkspaceIdentifier {

View File

@@ -5,7 +5,7 @@
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { MainContext, MainThreadKeytarShape, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol'; import { MainContext, MainThreadKeytarShape, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { ICredentialsService } from 'vs/workbench/services/credentials/common/credentials'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
@extHostNamedCustomer(MainContext.MainThreadKeytar) @extHostNamedCustomer(MainContext.MainThreadKeytar)
export class MainThreadKeytar implements MainThreadKeytarShape { export class MainThreadKeytar implements MainThreadKeytarShape {

View File

@@ -16,7 +16,7 @@ import { IWorkspaceContextService, WorkbenchState, IWorkspace } from 'vs/platfor
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder'; import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { ExtHostContext, ExtHostWorkspaceShape, IExtHostContext, MainContext, MainThreadWorkspaceShape, IWorkspaceData, ITextSearchComplete } from '../common/extHost.protocol'; import { ExtHostContext, ExtHostWorkspaceShape, IExtHostContext, MainContext, MainThreadWorkspaceShape, IWorkspaceData, ITextSearchComplete } from '../common/extHost.protocol';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { isEqualOrParent } from 'vs/base/common/resources'; import { isEqualOrParent } from 'vs/base/common/resources';

View File

@@ -12,9 +12,7 @@ import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IOpenInWindowOptions, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { IOpenInWindowOptions, IWindowOpenable } from 'vs/platform/windows/common/windows';
import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService'; import { IWorkspacesService, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspacesService, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { IRecent } from 'vs/platform/workspaces/common/workspacesHistory';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@@ -133,8 +131,8 @@ export class OpenAPICommand {
CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute)); CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute));
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, uri: URI) { CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, uri: URI) {
const workspacesHistoryService = accessor.get(IWorkspacesHistoryService); const workspacesService = accessor.get(IWorkspacesService);
return workspacesHistoryService.removeFromRecentlyOpened([uri]); return workspacesService.removeFromRecentlyOpened([uri]);
}); });
export class RemoveFromRecentlyOpenedAPICommand { export class RemoveFromRecentlyOpenedAPICommand {
@@ -164,7 +162,6 @@ interface RecentEntry {
} }
CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async function (accessor: ServicesAccessor, recentEntry: RecentEntry) { CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async function (accessor: ServicesAccessor, recentEntry: RecentEntry) {
const workspacesHistoryService = accessor.get(IWorkspacesHistoryService);
const workspacesService = accessor.get(IWorkspacesService); const workspacesService = accessor.get(IWorkspacesService);
let recent: IRecent | undefined = undefined; let recent: IRecent | undefined = undefined;
const uri = recentEntry.uri; const uri = recentEntry.uri;
@@ -177,12 +174,12 @@ CommandsRegistry.registerCommand('_workbench.addToRecentlyOpened', async functio
} else { } else {
recent = { fileUri: uri, label }; recent = { fileUri: uri, label };
} }
return workspacesHistoryService.addRecentlyOpened([recent]); return workspacesService.addRecentlyOpened([recent]);
}); });
CommandsRegistry.registerCommand('_workbench.getRecentlyOpened', async function (accessor: ServicesAccessor) { CommandsRegistry.registerCommand('_workbench.getRecentlyOpened', async function (accessor: ServicesAccessor) {
const workspacesHistoryService = accessor.get(IWorkspacesHistoryService); const workspacesService = accessor.get(IWorkspacesService);
return workspacesHistoryService.getRecentlyOpened(); return workspacesService.getRecentlyOpened();
}); });
export class SetEditorLayoutAPICommand { export class SetEditorLayoutAPICommand {

View File

@@ -7,9 +7,10 @@ import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net';
import * as http from 'http'; import * as http from 'http';
import * as fs from 'fs'; import * as fs from 'fs';
import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { IWindowOpenable, IOpenInWindowOptions } from 'vs/platform/windows/common/windows'; import { IWindowOpenable } from 'vs/platform/windows/common/windows';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces'; import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
import { INativeOpenInWindowOptions } from 'vs/platform/windows/node/window';
export interface OpenCommandPipeArgs { export interface OpenCommandPipeArgs {
type: 'open'; type: 'open';
@@ -126,7 +127,7 @@ export class CLIServer {
} }
if (urisToOpen.length) { if (urisToOpen.length) {
const waitMarkerFileURI = waitMarkerFilePath ? URI.file(waitMarkerFilePath) : undefined; const waitMarkerFileURI = waitMarkerFilePath ? URI.file(waitMarkerFilePath) : undefined;
const windowOpenArgs: IOpenInWindowOptions = { forceNewWindow, diffMode, addMode, gotoLineMode, forceReuseWindow, waitMarkerFileURI }; const windowOpenArgs: INativeOpenInWindowOptions = { forceNewWindow, diffMode, addMode, gotoLineMode, forceReuseWindow, waitMarkerFileURI };
this._commands.executeCommand('_files.windowOpen', urisToOpen, windowOpenArgs); this._commands.executeCommand('_files.windowOpen', urisToOpen, windowOpenArgs);
} }
res.writeHead(200); res.writeHead(200);

View File

@@ -8,7 +8,6 @@ import 'vs/css!./media/actions';
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions'; import { Action } from 'vs/base/common/actions';
import { IWindowOpenable } from 'vs/platform/windows/common/windows'; 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 { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform'; 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 { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IModelService } from 'vs/editor/common/services/modelService'; import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService'; 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 { URI } from 'vs/base/common/uri';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { FileKind } from 'vs/platform/files/common/files'; import { FileKind } from 'vs/platform/files/common/files';
@@ -45,7 +44,7 @@ abstract class BaseOpenRecentAction extends Action {
constructor( constructor(
id: string, id: string,
label: string, label: string,
private workspacesHistoryService: IWorkspacesHistoryService, private workspacesService: IWorkspacesService,
private quickInputService: IQuickInputService, private quickInputService: IQuickInputService,
private contextService: IWorkspaceContextService, private contextService: IWorkspaceContextService,
private labelService: ILabelService, private labelService: ILabelService,
@@ -60,7 +59,7 @@ abstract class BaseOpenRecentAction extends Action {
protected abstract isQuickNavigate(): boolean; protected abstract isQuickNavigate(): boolean;
async run(): Promise<void> { async run(): Promise<void> {
const { workspaces, files } = await this.workspacesHistoryService.getRecentlyOpened(); const { workspaces, files } = await this.workspacesService.getRecentlyOpened();
this.openRecent(workspaces, files); this.openRecent(workspaces, files);
} }
@@ -130,7 +129,7 @@ abstract class BaseOpenRecentAction extends Action {
onKeyMods: mods => keyMods = mods, onKeyMods: mods => keyMods = mods,
quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined, quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined,
onDidTriggerItemButton: async context => { onDidTriggerItemButton: async context => {
await this.workspacesHistoryService.removeFromRecentlyOpened([context.item.resource]); await this.workspacesService.removeFromRecentlyOpened([context.item.resource]);
context.removeItem(); context.removeItem();
} }
}); });
@@ -149,7 +148,7 @@ export class OpenRecentAction extends BaseOpenRecentAction {
constructor( constructor(
id: string, id: string,
label: string, label: string,
@IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService workspacesService: IWorkspacesService,
@IQuickInputService quickInputService: IQuickInputService, @IQuickInputService quickInputService: IQuickInputService,
@IWorkspaceContextService contextService: IWorkspaceContextService, @IWorkspaceContextService contextService: IWorkspaceContextService,
@IKeybindingService keybindingService: IKeybindingService, @IKeybindingService keybindingService: IKeybindingService,
@@ -158,7 +157,7 @@ export class OpenRecentAction extends BaseOpenRecentAction {
@ILabelService labelService: ILabelService, @ILabelService labelService: ILabelService,
@IHostService hostService: IHostService @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 { protected isQuickNavigate(): boolean {
@@ -174,7 +173,7 @@ class QuickOpenRecentAction extends BaseOpenRecentAction {
constructor( constructor(
id: string, id: string,
label: string, label: string,
@IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService workspacesService: IWorkspacesService,
@IQuickInputService quickInputService: IQuickInputService, @IQuickInputService quickInputService: IQuickInputService,
@IWorkspaceContextService contextService: IWorkspaceContextService, @IWorkspaceContextService contextService: IWorkspaceContextService,
@IKeybindingService keybindingService: IKeybindingService, @IKeybindingService keybindingService: IKeybindingService,
@@ -183,7 +182,7 @@ class QuickOpenRecentAction extends BaseOpenRecentAction {
@ILabelService labelService: ILabelService, @ILabelService labelService: ILabelService,
@IHostService hostService: IHostService @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 { protected isQuickNavigate(): boolean {

View File

@@ -7,7 +7,7 @@ import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands'; import { ADD_ROOT_FOLDER_COMMAND_ID, ADD_ROOT_FOLDER_LABEL, PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
@@ -200,7 +200,7 @@ 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(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(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) }), 'File: Close 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);
// --- Menu Registration // --- Menu Registration

View File

@@ -5,7 +5,7 @@
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import * as resources from 'vs/base/common/resources'; import * as resources from 'vs/base/common/resources';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';

View File

@@ -3,12 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. 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 { normalize } from 'vs/base/common/path';
import { basename } from 'vs/base/common/resources'; import { basename } from 'vs/base/common/resources';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IWindowOpenable } from 'vs/platform/windows/common/windows'; 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 { URI } from 'vs/base/common/uri';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
@@ -29,8 +28,7 @@ import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/co
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { addDisposableListener, EventType } from 'vs/base/browser/dom'; import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IRecentFile } from 'vs/platform/workspaces/common/workspacesHistory'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing';
import { withNullAsUndefined } from 'vs/base/common/types'; import { withNullAsUndefined } from 'vs/base/common/types';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IHostService } from 'vs/workbench/services/host/browser/host';
@@ -162,7 +160,7 @@ export class ResourcesDropHandler {
constructor( constructor(
private options: IResourcesDropHandlerOptions, private options: IResourcesDropHandlerOptions,
@IFileService private readonly fileService: IFileService, @IFileService private readonly fileService: IFileService,
@IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService private readonly workspacesService: IWorkspacesService,
@ITextFileService private readonly textFileService: ITextFileService, @ITextFileService private readonly textFileService: ITextFileService,
@IBackupFileService private readonly backupFileService: IBackupFileService, @IBackupFileService private readonly backupFileService: IBackupFileService,
@IUntitledEditorService private readonly untitledEditorService: IUntitledEditorService, @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 // 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 })); const recentFiles: IRecentFile[] = untitledOrFileResources.filter(d => d.isExternal && d.resource.scheme === Schemas.file).map(d => ({ fileUri: d.resource }));
if (recentFiles.length) { if (recentFiles.length) {
this.workspacesHistoryService.addRecentlyOpened(recentFiles); this.workspacesService.addRecentlyOpened(recentFiles);
} }
const editors: IResourceEditor[] = untitledOrFileResources.map(untitledOrFileResource => ({ const editors: IResourceEditor[] = untitledOrFileResources.map(untitledOrFileResource => ({

View File

@@ -16,12 +16,12 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands'; import { ICommandService } from 'vs/platform/commands/common/commands';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; 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 { 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 { 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 { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { DisposableStore } from 'vs/base/common/lifecycle'; import { DisposableStore } from 'vs/base/common/lifecycle';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
export class ExecuteCommandAction extends Action { export class ExecuteCommandAction extends Action {
@@ -1218,7 +1218,7 @@ export class ClearRecentFilesAction extends Action {
constructor( constructor(
id: string, id: string,
label: string, label: string,
@IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService private readonly workspacesService: IWorkspacesService,
@IHistoryService private readonly historyService: IHistoryService @IHistoryService private readonly historyService: IHistoryService
) { ) {
super(id, label); super(id, label);
@@ -1227,7 +1227,7 @@ export class ClearRecentFilesAction extends Action {
run(): Promise<any> { run(): Promise<any> {
// Clear global recently opened // Clear global recently opened
this.workspacesHistoryService.clearRecentlyOpened(); this.workspacesService.clearRecentlyOpened();
// Clear workspace specific recently opened // Clear workspace specific recently opened
this.historyService.clearRecentlyOpened(); this.historyService.clearRecentlyOpened();

View File

@@ -7,7 +7,6 @@ import * as nls from 'vs/nls';
import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { IMenuService, MenuId, IMenu, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { registerThemingParticipant, ITheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService'; import { registerThemingParticipant, ITheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService';
import { MenuBarVisibility, getTitleBarStyle, IWindowOpenable } from 'vs/platform/windows/common/windows'; 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 { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IAction, Action } from 'vs/base/common/actions'; import { IAction, Action } from 'vs/base/common/actions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; 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 { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle'; 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 { 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 { 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'; import { URI } from 'vs/base/common/uri';
@@ -86,7 +85,7 @@ export abstract class MenubarControl extends Disposable {
constructor( constructor(
protected readonly menuService: IMenuService, protected readonly menuService: IMenuService,
protected readonly workspacesHistoryService: IWorkspacesHistoryService, protected readonly workspacesService: IWorkspacesService,
protected readonly contextKeyService: IContextKeyService, protected readonly contextKeyService: IContextKeyService,
protected readonly keybindingService: IKeybindingService, protected readonly keybindingService: IKeybindingService,
protected readonly configurationService: IConfigurationService, protected readonly configurationService: IConfigurationService,
@@ -129,7 +128,7 @@ export abstract class MenubarControl extends Disposable {
this.updateService.onStateChange(() => this.updateMenubar()); this.updateService.onStateChange(() => this.updateMenubar());
// Listen for changes in recently opened menu // 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 // Listen to keybindings change
this._register(this.keybindingService.onDidUpdateKeybindings(() => this.updateMenubar())); this._register(this.keybindingService.onDidUpdateKeybindings(() => this.updateMenubar()));
@@ -191,7 +190,7 @@ export abstract class MenubarControl extends Disposable {
} }
private onRecentlyOpenedChange(): void { private onRecentlyOpenedChange(): void {
this.workspacesHistoryService.getRecentlyOpened().then(recentlyOpened => { this.workspacesService.getRecentlyOpened().then(recentlyOpened => {
this.recentlyOpened = recentlyOpened; this.recentlyOpened = recentlyOpened;
this.updateMenubar(); this.updateMenubar();
}); });
@@ -271,7 +270,7 @@ export class CustomMenubarControl extends MenubarControl {
constructor( constructor(
@IMenuService menuService: IMenuService, @IMenuService menuService: IMenuService,
@IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService workspacesService: IWorkspacesService,
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService contextKeyService: IContextKeyService,
@IKeybindingService keybindingService: IKeybindingService, @IKeybindingService keybindingService: IKeybindingService,
@IConfigurationService configurationService: IConfigurationService, @IConfigurationService configurationService: IConfigurationService,
@@ -291,7 +290,7 @@ export class CustomMenubarControl extends MenubarControl {
super( super(
menuService, menuService,
workspacesHistoryService, workspacesService,
contextKeyService, contextKeyService,
keybindingService, keybindingService,
configurationService, configurationService,
@@ -308,7 +307,7 @@ export class CustomMenubarControl extends MenubarControl {
this._onVisibilityChange = this._register(new Emitter<boolean>()); this._onVisibilityChange = this._register(new Emitter<boolean>());
this._onFocusStateChange = this._register(new Emitter<boolean>()); this._onFocusStateChange = this._register(new Emitter<boolean>());
this.workspacesHistoryService.getRecentlyOpened().then((recentlyOpened) => { this.workspacesService.getRecentlyOpened().then((recentlyOpened) => {
this.recentlyOpened = recentlyOpened; this.recentlyOpened = recentlyOpened;
}); });

View File

@@ -7,7 +7,9 @@ import 'vs/css!./media/style';
import { registerThemingParticipant, ITheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; import { registerThemingParticipant, ITheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { iconForeground, foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry'; import { iconForeground, foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry';
import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme'; import { WORKBENCH_BACKGROUND, TITLE_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme';
import { isWeb } from 'vs/base/common/platform';
import { createMetaElement } from 'vs/base/browser/dom';
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
@@ -143,4 +145,19 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
`); `);
} }
// Update <meta name="theme-color" content=""> based on selected theme
if (isWeb) {
const titleBackground = theme.getColor(TITLE_BAR_ACTIVE_BACKGROUND);
if (titleBackground) {
const metaElementId = 'monaco-workbench-meta-theme-color';
let metaElement = document.getElementById(metaElementId) as HTMLMetaElement | null;
if (!metaElement) {
metaElement = createMetaElement();
metaElement.name = 'theme-color';
metaElement.id = metaElementId;
}
metaElement.content = titleBackground.toString();
}
}
}); });

View File

@@ -33,7 +33,7 @@ import { ConfigurationCache } from 'vs/workbench/services/configuration/browser/
import { ISignService } from 'vs/platform/sign/common/sign'; import { ISignService } from 'vs/platform/sign/common/sign';
import { SignService } from 'vs/platform/sign/browser/signService'; import { SignService } from 'vs/platform/sign/browser/signService';
import { hash } from 'vs/base/common/hash'; import { hash } from 'vs/base/common/hash';
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api'; import { IWorkbenchConstructionOptions, IWorkspace } from 'vs/workbench/workbench.web.api';
import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider'; import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider';
import { BACKUPS } from 'vs/platform/environment/common/environment'; import { BACKUPS } from 'vs/platform/environment/common/environment';
import { joinPath } from 'vs/base/common/resources'; import { joinPath } from 'vs/base/common/resources';
@@ -47,6 +47,7 @@ import { FileLogService } from 'vs/platform/log/common/fileLogService';
import { toLocalISOString } from 'vs/base/common/date'; import { toLocalISOString } from 'vs/base/common/date';
import { IndexedDBLogProvider } from 'vs/workbench/services/log/browser/indexedDBLogProvider'; import { IndexedDBLogProvider } from 'vs/workbench/services/log/browser/indexedDBLogProvider';
import { InMemoryLogProvider } from 'vs/workbench/services/log/common/inMemoryLogProvider'; import { InMemoryLogProvider } from 'vs/workbench/services/log/common/inMemoryLogProvider';
import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows';
class BrowserMain extends Disposable { class BrowserMain extends Disposable {
@@ -284,15 +285,27 @@ class BrowserMain extends Disposable {
} }
private resolveWorkspaceInitializationPayload(): IWorkspaceInitializationPayload { private resolveWorkspaceInitializationPayload(): IWorkspaceInitializationPayload {
let workspace: IWorkspace | undefined = undefined;
if (this.configuration.workspaceProvider) {
workspace = this.configuration.workspaceProvider.workspace;
} else {
// TODO@ben remove me once IWorkspaceProvider API is adopted
const legacyConfiguration = this.configuration as { workspaceUri?: URI, folderUri?: URI };
if (legacyConfiguration.workspaceUri) {
workspace = { workspaceUri: legacyConfiguration.workspaceUri };
} else if (legacyConfiguration.folderUri) {
workspace = { folderUri: legacyConfiguration.folderUri };
}
}
// Multi-root workspace // Multi-root workspace
if (this.configuration.workspaceUri) { if (workspace && isWorkspaceToOpen(workspace)) {
return { id: hash(this.configuration.workspaceUri.toString()).toString(16), configPath: this.configuration.workspaceUri }; return { id: hash(workspace.workspaceUri.toString()).toString(16), configPath: workspace.workspaceUri };
} }
// Single-folder workspace // Single-folder workspace
if (this.configuration.folderUri) { if (workspace && isFolderToOpen(workspace)) {
return { id: hash(this.configuration.folderUri.toString()).toString(16), folder: this.configuration.folderUri }; return { id: hash(workspace.folderUri.toString()).toString(16), folder: workspace.folderUri };
} }
return { id: 'empty-window' }; return { id: 'empty-window' };

View File

@@ -5,7 +5,7 @@
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform'; import { Registry } from 'vs/platform/registry/common/platform';
import { ToggleAutoSaveAction, GlobalNewUntitledFileAction, ShowOpenedFileInNewWindow, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CollapseExplorerView, RefreshExplorerView, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, GlobalNewUntitledPlainFileAction, openFilePreserveFocusHandler } from 'vs/workbench/contrib/files/browser/fileActions'; import { ToggleAutoSaveAction, GlobalNewUntitledFileAction, FocusFilesExplorer, GlobalCompareResourcesAction, SaveAllAction, ShowActiveFileInExplorer, CollapseExplorerView, RefreshExplorerView, CompareWithClipboardAction, NEW_FILE_COMMAND_ID, NEW_FILE_LABEL, NEW_FOLDER_COMMAND_ID, NEW_FOLDER_LABEL, TRIGGER_RENAME_LABEL, MOVE_FILE_TO_TRASH_LABEL, COPY_FILE_LABEL, PASTE_FILE_LABEL, FileCopiedContext, renameHandler, moveFileToTrashHandler, copyFileHandler, pasteFileHandler, deleteFileHandler, cutFileHandler, DOWNLOAD_COMMAND_ID, openFilePreserveFocusHandler, GlobalNewUntitledPlainFileAction } from 'vs/workbench/contrib/files/browser/fileActions'; // {{SQL CARBON EDIT}} -- Add 'New File' command for plain untitled files
import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTION_CONTEXT } from 'vs/workbench/contrib/files/browser/saveErrorHandler'; import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTION_CONTEXT } from 'vs/workbench/contrib/files/browser/saveErrorHandler';
import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions'; import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
@@ -41,12 +41,9 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ShowActiveFileInExplor
registry.registerWorkbenchAction(new SyncActionDescriptor(CollapseExplorerView, CollapseExplorerView.ID, CollapseExplorerView.LABEL), 'File: Collapse Folders in Explorer', category.value); registry.registerWorkbenchAction(new SyncActionDescriptor(CollapseExplorerView, CollapseExplorerView.ID, CollapseExplorerView.LABEL), 'File: Collapse Folders in Explorer', category.value);
registry.registerWorkbenchAction(new SyncActionDescriptor(RefreshExplorerView, RefreshExplorerView.ID, RefreshExplorerView.LABEL), 'File: Refresh Explorer', category.value); registry.registerWorkbenchAction(new SyncActionDescriptor(RefreshExplorerView, RefreshExplorerView.ID, RefreshExplorerView.LABEL), 'File: Refresh Explorer', category.value);
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalNewUntitledFileAction, GlobalNewUntitledFileAction.ID, GlobalNewUntitledFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_N }), 'File: New Untitled File', category.value); registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalNewUntitledFileAction, GlobalNewUntitledFileAction.ID, GlobalNewUntitledFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_N }), 'File: New Untitled File', category.value);
// {{SQL CARBON EDIT}} -- Add 'New File' command for plain untitled files
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalNewUntitledPlainFileAction, GlobalNewUntitledPlainFileAction.ID, GlobalNewUntitledPlainFileAction.LABEL), 'File: New Plain Text File', category.value);
registry.registerWorkbenchAction(new SyncActionDescriptor(ShowOpenedFileInNewWindow, ShowOpenedFileInNewWindow.ID, ShowOpenedFileInNewWindow.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_O) }), 'File: Open Active File in New Window', category.value);
registry.registerWorkbenchAction(new SyncActionDescriptor(CompareWithClipboardAction, CompareWithClipboardAction.ID, CompareWithClipboardAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_C) }), 'File: Compare Active File with Clipboard', category.value); registry.registerWorkbenchAction(new SyncActionDescriptor(CompareWithClipboardAction, CompareWithClipboardAction.ID, CompareWithClipboardAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_C) }), 'File: Compare Active File with Clipboard', category.value);
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleAutoSaveAction, ToggleAutoSaveAction.ID, ToggleAutoSaveAction.LABEL), 'File: Toggle Auto Save', category.value); registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleAutoSaveAction, ToggleAutoSaveAction.ID, ToggleAutoSaveAction.LABEL), 'File: Toggle Auto Save', category.value);
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalNewUntitledPlainFileAction, GlobalNewUntitledPlainFileAction.ID, GlobalNewUntitledPlainFileAction.LABEL), 'File: New Plain Text File', category.value); // {{SQL CARBON EDIT}} -- Add 'New File' command for plain untitled files
const workspacesCategory = nls.localize('workspaces', "Workspaces"); const workspacesCategory = nls.localize('workspaces', "Workspaces");
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory); registry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceAction, OpenWorkspaceAction.ID, OpenWorkspaceAction.LABEL), 'Workspaces: Open Workspace...', workspacesCategory);

View File

@@ -29,7 +29,7 @@ import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
import { isWindows } from 'vs/base/common/platform'; import { isWindows } from 'vs/base/common/platform';
import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { getResourceForCommand, getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; import { getResourceForCommand, getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { INotificationService } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';

View File

@@ -39,7 +39,7 @@ import { isMacintosh } from 'vs/base/common/platform';
import { IDialogService, IConfirmationResult, IConfirmation, getConfirmMessage } from 'vs/platform/dialogs/common/dialogs'; import { IDialogService, IConfirmationResult, IConfirmation, getConfirmMessage } from 'vs/platform/dialogs/common/dialogs';
import { ITextFileService, ITextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, ITextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles';
import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { ITask, sequence } from 'vs/base/common/async'; import { ITask, sequence } from 'vs/base/common/async';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';

View File

@@ -244,8 +244,9 @@ export class OpenEditorsView extends ViewletPanel {
this.dirtyEditorFocusedContext.reset(); this.dirtyEditorFocusedContext.reset();
const element = e.elements.length ? e.elements[0] : undefined; const element = e.elements.length ? e.elements[0] : undefined;
if (element instanceof OpenEditor) { if (element instanceof OpenEditor) {
this.dirtyEditorFocusedContext.set(this.textFileService.isDirty(withNullAsUndefined(element.getResource()))); const resource = element.getResource();
this.resourceContext.set(withUndefinedAsNull(element.getResource())); this.dirtyEditorFocusedContext.set(this.textFileService.isDirty(resource));
this.resourceContext.set(withUndefinedAsNull(resource));
} else if (!!element) { } else if (!!element) {
this.groupFocusedContext.set(true); this.groupFocusedContext.set(true);
} }

View File

@@ -18,9 +18,12 @@ import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/fi
import { IListService } from 'vs/platform/list/browser/listService'; import { IListService } from 'vs/platform/list/browser/listService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-browser/fileCommands'; import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-browser/fileCommands';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { MenuRegistry, MenuId, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ResourceContextKey } from 'vs/workbench/common/resources';
import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution'; import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { ShowOpenedFileInNewWindow } from 'vs/workbench/contrib/files/browser/fileActions';
const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS'; const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS';
const REVEAL_IN_OS_LABEL = isWindows ? nls.localize('revealInWindows', "Reveal in Explorer") : isMacintosh ? nls.localize('revealInMac', "Reveal in Finder") : nls.localize('openContainer', "Open Containing Folder"); const REVEAL_IN_OS_LABEL = isWindows ? nls.localize('revealInWindows', "Reveal in Explorer") : isMacintosh ? nls.localize('revealInMac', "Reveal in Finder") : nls.localize('openContainer', "Open Containing Folder");
@@ -81,3 +84,6 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
const category = { value: nls.localize('filesCategory', "File"), original: 'File' }; const category = { value: nls.localize('filesCategory', "File"), original: 'File' };
appendToCommandPalette(REVEAL_IN_OS_COMMAND_ID, { value: REVEAL_IN_OS_LABEL, original: isWindows ? 'Reveal in Explorer' : isMacintosh ? 'Reveal in Finder' : 'Open Containing Folder' }, category); appendToCommandPalette(REVEAL_IN_OS_COMMAND_ID, { value: REVEAL_IN_OS_LABEL, original: isWindows ? 'Reveal in Explorer' : isMacintosh ? 'Reveal in Finder' : 'Open Containing Folder' }, category);
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(ShowOpenedFileInNewWindow, ShowOpenedFileInNewWindow.ID, ShowOpenedFileInNewWindow.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_O) }), 'File: Open Active File in New Window', category.value);

View File

@@ -58,7 +58,7 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution {
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions); const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions);
const devCategory = nls.localize('developer', "Developer"); const devCategory = nls.localize('developer', "Developer");
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenWindowSessionLogFileAction, OpenWindowSessionLogFileAction.ID, OpenWindowSessionLogFileAction.LABEL), 'Developer: Open Browser Log File (Session)...', devCategory); workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenWindowSessionLogFileAction, OpenWindowSessionLogFileAction.ID, OpenWindowSessionLogFileAction.LABEL), 'Developer: Open Window Log File (Session)...', devCategory);
} }
private registerNativeContributions(): void { private registerNativeContributions(): void {

View File

@@ -317,7 +317,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
const fullTextSearchPlaceholder = localize('SearchKeybindings.FullTextSearchPlaceholder', "Type to search in keybindings"); const fullTextSearchPlaceholder = localize('SearchKeybindings.FullTextSearchPlaceholder', "Type to search in keybindings");
const keybindingsSearchPlaceholder = localize('SearchKeybindings.KeybindingsSearchPlaceholder', "Recording Keys. Press Escape to exit"); const keybindingsSearchPlaceholder = localize('SearchKeybindings.KeybindingsSearchPlaceholder', "Recording Keys. Press Escape to exit");
const clearInputAction = new Action(KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Keybindings Search Input"), 'clear-input', false, () => { this.search(''); return Promise.resolve(null); }); const clearInputAction = new Action(KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, localize('clearInput', "Clear Keybindings Search Input"), 'codicon-clear-all', false, () => { this.search(''); return Promise.resolve(null); });
const searchContainer = DOM.append(this.headerContainer, $('.search-container')); const searchContainer = DOM.append(this.headerContainer, $('.search-container'));
this.searchWidget = this._register(this.instantiationService.createInstance(KeybindingsSearchWidget, searchContainer, <KeybindingsSearchOptions>{ this.searchWidget = this._register(this.instantiationService.createInstance(KeybindingsSearchWidget, searchContainer, <KeybindingsSearchOptions>{
@@ -340,7 +340,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
const sortByPrecedenceActionKeybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE); const sortByPrecedenceActionKeybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE);
const sortByPrecedenceActionLabel = localize('sortByPrecedeneLabel', "Sort by Precedence"); const sortByPrecedenceActionLabel = localize('sortByPrecedeneLabel', "Sort by Precedence");
this.sortByPrecedenceAction = new Action('keybindings.editor.sortByPrecedence', sortByPrecedenceActionKeybinding ? localize('sortByPrecedeneLabelWithKeybinding', "{0} ({1})", sortByPrecedenceActionLabel, sortByPrecedenceActionKeybinding.getLabel()) : sortByPrecedenceActionLabel, 'sort-by-precedence'); this.sortByPrecedenceAction = new Action('keybindings.editor.sortByPrecedence', sortByPrecedenceActionKeybinding ? localize('sortByPrecedeneLabelWithKeybinding', "{0} ({1})", sortByPrecedenceActionLabel, sortByPrecedenceActionKeybinding.getLabel()) : sortByPrecedenceActionLabel, 'codicon-sort-precedence');
this.sortByPrecedenceAction.checked = false; this.sortByPrecedenceAction.checked = false;
this._register(this.sortByPrecedenceAction.onDidChange(e => { this._register(this.sortByPrecedenceAction.onDidChange(e => {
if (e.checked !== undefined) { if (e.checked !== undefined) {
@@ -351,7 +351,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor
const recordKeysActionKeybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS); const recordKeysActionKeybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS);
const recordKeysActionLabel = localize('recordKeysLabel', "Record Keys"); const recordKeysActionLabel = localize('recordKeysLabel', "Record Keys");
this.recordKeysAction = new Action(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, recordKeysActionKeybinding ? localize('recordKeysLabelWithKeybinding', "{0} ({1})", recordKeysActionLabel, recordKeysActionKeybinding.getLabel()) : recordKeysActionLabel, 'record-keys'); this.recordKeysAction = new Action(KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, recordKeysActionKeybinding ? localize('recordKeysLabelWithKeybinding', "{0} ({1})", recordKeysActionLabel, recordKeysActionKeybinding.getLabel()) : recordKeysActionLabel, 'codicon-record-keys');
this.recordKeysAction.checked = false; this.recordKeysAction.checked = false;
this._register(this.recordKeysAction.onDidChange(e => { this._register(this.recordKeysAction.onDidChange(e => {
if (e.checked !== undefined) { if (e.checked !== undefined) {
@@ -899,7 +899,7 @@ class ActionsColumn extends Column {
private createAddAction(keybindingItemEntry: IKeybindingItemEntry): IAction { private createAddAction(keybindingItemEntry: IKeybindingItemEntry): IAction {
const keybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_DEFINE); const keybinding = this.keybindingsService.lookupKeybinding(KEYBINDINGS_EDITOR_COMMAND_DEFINE);
return <IAction>{ return <IAction>{
class: 'add', class: 'codicon-add',
enabled: true, enabled: true,
id: 'addKeybinding', id: 'addKeybinding',
tooltip: keybinding ? localize('addKeybindingLabelWithKey', "Add Keybinding {0}", `(${keybinding.getLabel()})`) : localize('addKeybindingLabel', "Add Keybinding"), tooltip: keybinding ? localize('addKeybindingLabelWithKey', "Add Keybinding {0}", `(${keybinding.getLabel()})`) : localize('addKeybindingLabel', "Add Keybinding"),

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 7V8H8V14H7V8H1V7H7V1H8V7H14Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 163 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 7V8H8V14H7V8H1V7H7V1H8V7H14Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 163 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4315 3.3232L5.96154 13.3232L5.17083 13.2874L1.82083 8.5174L2.63918 7.94268L5.617 12.1827L13.6685 2.67688L14.4315 3.3232Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 295 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4315 3.3232L5.96154 13.3232L5.17083 13.2874L1.82083 8.5174L2.63918 7.94268L5.617 12.1827L13.6685 2.67688L14.4315 3.3232Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 295 B

View File

@@ -1,7 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#C5C5C5"/>
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#C5C5C5"/>
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#C5C5C5"/>
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#C5C5C5"/>
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 484 B

View File

@@ -1,7 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#424242"/>
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#424242"/>
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#424242"/>
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#424242"/>
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 484 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.40706 15L1 13.5929L3.35721 9.46781L3.52339 9.25025L11.7736 1L13.2321 1L15 2.76791V4.22636L6.74975 12.4766L6.53219 12.6428L2.40706 15ZM2.40706 13.5929L6.02053 11.7474L14.2708 3.49714L12.5029 1.72923L4.25262 9.97947L2.40706 13.5929Z" fill="#C5C5C5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.64645 12.3536L3.64645 10.3536L4.35355 9.64648L6.35355 11.6465L5.64645 12.3536Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 553 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.40706 15L1 13.5929L3.35721 9.46781L3.52339 9.25025L11.7736 1L13.2321 1L15 2.76791V4.22636L6.74975 12.4766L6.53219 12.6428L2.40706 15ZM2.40706 13.5929L6.02053 11.7474L14.2708 3.49714L12.5029 1.72923L4.25262 9.97947L2.40706 13.5929Z" fill="#424242"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.64645 12.3536L3.64645 10.3536L4.35355 9.64648L6.35355 11.6465L5.64645 12.3536Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 553 B

View File

@@ -45,31 +45,11 @@
margin-right: 4px; margin-right: 4px;
} }
.keybindings-editor .monaco-action-bar .action-item > .sort-by-precedence { .keybindings-editor .monaco-action-bar .action-item > .codicon {
background: url('sort-precedence-light.svg') center center no-repeat; display: flex;
} align-items: center;
justify-content: center;
.hc-black .keybindings-editor .monaco-action-bar .action-item > .sort-by-precedence, color: inherit;
.vs-dark .keybindings-editor .monaco-action-bar .action-item > .sort-by-precedence {
background: url('sort-precedence-dark.svg') center center no-repeat;
}
.keybindings-editor .monaco-action-bar .action-item > .record-keys {
background: url('record-keys-light.svg') center center no-repeat;
}
.hc-black .keybindings-editor .monaco-action-bar .action-item > .record-keys,
.vs-dark .keybindings-editor .monaco-action-bar .action-item > .record-keys {
background: url('record-keys-dark.svg') center center no-repeat;
}
.keybindings-editor .monaco-action-bar .action-item > .clear-input {
background: url('clear-light.svg') center center no-repeat;
}
.hc-black .keybindings-editor .monaco-action-bar .action-item > .clear-input,
.vs-dark .keybindings-editor .monaco-action-bar .action-item > .clear-input {
background: url('clear-dark.svg') center center no-repeat;
} }
.keybindings-editor > .keybindings-header .open-keybindings-container { .keybindings-editor > .keybindings-header .open-keybindings-container {
@@ -206,22 +186,3 @@
cursor: pointer; cursor: pointer;
margin-top: 3px; margin-top: 3px;
} }
.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row > .column .monaco-action-bar .action-item > .icon.edit {
background: url('edit-light.svg') center center no-repeat;
transform: rotate(-90deg);
}
.hc-black .keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row > .column .monaco-action-bar .action-item > .icon.edit,
.vs-dark .keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row > .column .monaco-action-bar .action-item > .icon.edit {
background: url('edit-dark.svg') center center no-repeat;
}
.keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row > .column .monaco-action-bar .action-item > .icon.add {
background: url('add-light.svg') center center no-repeat;
}
.hc-black .keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row > .column .monaco-action-bar .action-item > .icon.add,
.vs-dark .keybindings-editor > .keybindings-body > .keybindings-list-container .monaco-list-row > .column .monaco-action-bar .action-item > .icon.add {
background: url('add-dark.svg') center center no-repeat;
}

View File

@@ -216,24 +216,18 @@
transform: rotate(-90deg); transform: rotate(-90deg);
} }
.monaco-editor .edit-preferences-widget { .monaco-editor .codicon-edit {
background: url('edit-light.svg') center center no-repeat;
transform: rotate(-90deg); transform: rotate(-90deg);
width:16px; width:16px;
height: 16px; height: 16px;
cursor: pointer; cursor: pointer;
} }
.monaco-editor .edit-preferences-widget.hidden { .monaco-editor .codicon-edit.hidden {
display: none; display: none;
visibility: hidden; visibility: hidden;
} }
.monaco-editor.hc-black .edit-preferences-widget,
.monaco-editor.vs-dark .edit-preferences-widget {
background: url('edit-dark.svg') center center no-repeat;
}
.monaco-editor .dim-configuration { .monaco-editor .dim-configuration {
color: #b1b1b1; color: #b1b1b1;
} }

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 4H3L3 11H14V4ZM3 3C2.44772 3 2 3.44772 2 4V11C2 11.5523 2.44772 12 3 12H14C14.5523 12 15 11.5523 15 11V4C15 3.44772 14.5523 3 14 3H3ZM4 5H5V6H4V5ZM7 5H6V6H7V5ZM8 5H9V6H8V5ZM11 5H10V6H11V5ZM12 5H13V6H12V5ZM6 8V7H4V8H6ZM7 7H8V8H7V7ZM10 7H9V8H10V7ZM13 7V8H11V7H13ZM5 9H4V10H5V9ZM6 9H11V10H6V9ZM13 9H12V10H13V9Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 482 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 4H3L3 11H14V4ZM3 3C2.44772 3 2 3.44772 2 4V11C2 11.5523 2.44772 12 3 12H14C14.5523 12 15 11.5523 15 11V4C15 3.44772 14.5523 3 14 3H3ZM4 5H5V6H4V5ZM7 5H6V6H7V5ZM8 5H9V6H8V5ZM11 5H10V6H11V5ZM12 5H13V6H12V5ZM6 8V7H4V8H6ZM7 7H8V8H7V7ZM10 7H9V8H10V7ZM13 7V8H11V7H13ZM5 9H4V10H5V9ZM6 9H11V10H6V9ZM13 9H12V10H13V9Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 482 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 8.70714L11.6464 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6464 3.64648L8 7.29293L4.35355 3.64648L3.64645 4.35359L7.29289 8.00004L3.64645 11.6465L4.35355 12.3536L8 8.70714Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 362 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 8.70714L11.6464 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6464 3.64648L8 7.29293L4.35355 3.64648L3.64645 4.35359L7.29289 8.00004L3.64645 11.6465L4.35355 12.3536L8 8.70714Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 362 B

View File

@@ -12,6 +12,10 @@
overflow: hidden; overflow: hidden;
} }
.settings-editor .codicon {
color: inherit !important;
}
/* header styling */ /* header styling */
.settings-editor > .settings-header { .settings-editor > .settings-header {
box-sizing: border-box; box-sizing: border-box;
@@ -88,7 +92,6 @@
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label { .settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label {
text-transform: none; text-transform: none;
font-size: 13px; font-size: 13px;
padding-bottom: 7px; padding-bottom: 7px;
padding-top: 7px; padding-top: 7px;
padding-left: 8px; padding-left: 8px;
@@ -166,21 +169,9 @@
transition: opacity .3s; transition: opacity .3s;
width: 22px; width: 22px;
height: 22px; height: 22px;
background-position: center; display: flex;
background-repeat: no-repeat; align-items: center;
background-size: 16px; justify-content: center;
}
.settings-editor > .settings-body .settings-tree-container .setting-toolbar-container > .monaco-toolbar .codicon-more::before {
content: ' ';
}
.vs .settings-editor > .settings-body .settings-tree-container .monaco-toolbar .codicon-more {
background-image: url('configure-light.svg');
}
.vs-dark .settings-editor > .settings-body .settings-tree-container .monaco-toolbar .codicon-more {
background-image: url('configure-dark.svg');
} }
.settings-editor > .settings-body .settings-toc-container { .settings-editor > .settings-body .settings-toc-container {
@@ -436,16 +427,10 @@
margin-right: 9px; margin-right: 9px;
margin-left: 0px; margin-left: 0px;
padding: 0px; padding: 0px;
background-size: 16px !important;
} }
.vs .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.checked { .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.codicon:not(.checked)::before {
background: url('check-light.svg') center center no-repeat; opacity: 0;
}
.vs-dark .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.checked,
.hc-black .settings-editor > .settings-body > .settings-tree-container .setting-item-bool .setting-value-checkbox.checked {
background: url('check-dark.svg') center center no-repeat;
} }
.settings-editor > .settings-body > .settings-tree-container .setting-item-contents .setting-item-value { .settings-editor > .settings-body > .settings-tree-container .setting-item-contents .setting-item-value {

View File

@@ -70,28 +70,15 @@
height: 20px; height: 20px;
padding: 2px; padding: 2px;
margin-right: 2px; margin-right: 2px;
display: flex;
align-items: center;
justify-content: center;
} }
.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row .monaco-action-bar .setting-listAction-edit { .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row .monaco-action-bar .setting-listAction-edit {
margin-right: 4px; margin-right: 4px;
} }
.vs .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row .monaco-action-bar .setting-listAction-edit {
background: url("edit-light.svg") center center no-repeat;
}
.vs-dark .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row .monaco-action-bar .setting-listAction-edit {
background: url("edit-dark.svg") center center no-repeat;
}
.vs .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row .monaco-action-bar .setting-listAction-remove {
background: url("remove-light.svg") center center no-repeat;
}
.vs-dark .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row .monaco-action-bar .setting-listAction-remove {
background: url("remove-dark.svg") center center no-repeat;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .monaco-text-button { .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .monaco-text-button {
width: initial; width: initial;
padding: 2px 14px; padding: 2px 14px;

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 2L6 3V6H7V3H14V5.45306L14.2071 5.29286L15 6.08576V3L14 2H7ZM8 4H10V6H8V4ZM5 9H3V11H5V9ZM2 7L1 8V13L2 14H9L10 13V8L9 7H2ZM2 13V8H9V13H2ZM8 10H6V12H8V10ZM13 4H12V7.86388L10.818 6.68192L10.1109 7.38903L12.1465 9.42454L12.8536 9.42454L14.889 7.38908L14.1819 6.68197L13 7.86388V4Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 449 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 2L6 3V6H7V3H14V5.45306L14.2071 5.29286L15 6.08576V3L14 2H7ZM8 4H10V6H8V4ZM5 9H3V11H5V9ZM2 7L1 8V13L2 14H9L10 13V8L9 7H2ZM2 13V8H9V13H2ZM8 10H6V12H8V10ZM13 4H12V7.86388L10.818 6.68192L10.1109 7.38903L12.1465 9.42454L12.8536 9.42454L14.889 7.38908L14.1819 6.68197L13 7.86388V4Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 449 B

View File

@@ -37,7 +37,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IOpenerService } from 'vs/platform/opener/common/opener';
import { editorBackground, errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry'; import { errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry';
import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler } from 'vs/platform/theme/common/styler'; import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler } from 'vs/platform/theme/common/styler';
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ITOCEntry } from 'vs/workbench/contrib/preferences/browser/settingsLayout'; import { ITOCEntry } from 'vs/workbench/contrib/preferences/browser/settingsLayout';
@@ -393,6 +393,13 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre
toggleMenuTitle toggleMenuTitle
}); });
toolbar.setActions([], this.settingActions)(); toolbar.setActions([], this.settingActions)();
// change icon from ellipsis to gear
let icon = container.querySelector('.codicon-more');
if (icon) {
(<HTMLElement>icon).classList.add('codicon-gear');
}
const button = container.querySelector('.toolbar-toggle-more'); const button = container.querySelector('.toolbar-toggle-more');
if (button) { if (button) {
(<HTMLElement>button).tabIndex = -1; (<HTMLElement>button).tabIndex = -1;
@@ -1071,7 +1078,7 @@ export class SettingBoolRenderer extends AbstractSettingRenderer implements ITre
const deprecationWarningElement = DOM.append(container, $('.setting-item-deprecation-message')); const deprecationWarningElement = DOM.append(container, $('.setting-item-deprecation-message'));
const toDispose = new DisposableStore(); const toDispose = new DisposableStore();
const checkbox = new Checkbox({ actionClassName: 'setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: undefined }); const checkbox = new Checkbox({ actionClassName: 'codicon-check setting-value-checkbox', isChecked: true, title: '', inputActiveOptionBorder: undefined });
controlElement.appendChild(checkbox.domNode); controlElement.appendChild(checkbox.domNode);
toDispose.add(checkbox); toDispose.add(checkbox);
toDispose.add(checkbox.onChange(() => { toDispose.add(checkbox.onChange(() => {
@@ -1537,20 +1544,20 @@ export class SettingsTree extends ObjectTree<SettingsTreeElement> {
this.getHTMLElement().classList.add(treeClass); this.getHTMLElement().classList.add(treeClass);
this.disposables.push(attachStyler(themeService, { this.disposables.push(attachStyler(themeService, {
listActiveSelectionBackground: editorBackground, listActiveSelectionBackground: 'transparent',
listActiveSelectionForeground: foreground, listActiveSelectionForeground: foreground,
listFocusAndSelectionBackground: editorBackground, listFocusAndSelectionBackground: 'transparent',
listFocusAndSelectionForeground: foreground, listFocusAndSelectionForeground: foreground,
listFocusBackground: editorBackground, listFocusBackground: 'transparent',
listFocusForeground: foreground, listFocusForeground: foreground,
listHoverForeground: foreground, listHoverForeground: foreground,
listHoverBackground: editorBackground, listHoverBackground: 'transparent',
listHoverOutline: editorBackground, listHoverOutline: 'transparent',
listFocusOutline: editorBackground, listFocusOutline: 'transparent',
listInactiveSelectionBackground: editorBackground, listInactiveSelectionBackground: 'transparent',
listInactiveSelectionForeground: foreground, listInactiveSelectionForeground: foreground,
listInactiveFocusBackground: editorBackground, listInactiveFocusBackground: 'transparent',
listInactiveFocusOutline: editorBackground listInactiveFocusOutline: 'transparent'
}, colors => { }, colors => {
this.style(colors); this.style(colors);
})); }));

View File

@@ -352,7 +352,7 @@ export class ListSettingWidget extends Disposable {
private createDeleteAction(key: string, idx: number): IAction { private createDeleteAction(key: string, idx: number): IAction {
return <IAction>{ return <IAction>{
class: 'setting-listAction-remove', class: 'codicon-close',
enabled: true, enabled: true,
id: 'workbench.action.removeListItem', id: 'workbench.action.removeListItem',
tooltip: this.getLocalizedStrings().deleteActionTooltip, tooltip: this.getLocalizedStrings().deleteActionTooltip,
@@ -362,7 +362,7 @@ export class ListSettingWidget extends Disposable {
private createEditAction(idx: number): IAction { private createEditAction(idx: number): IAction {
return <IAction>{ return <IAction>{
class: 'setting-listAction-edit', class: 'codicon-edit',
enabled: true, enabled: true,
id: 'workbench.action.editListItem', id: 'workbench.action.editListItem',
tooltip: this.getLocalizedStrings().editActionTooltip, tooltip: this.getLocalizedStrings().editActionTooltip,

View File

@@ -6,6 +6,7 @@
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import * as Objects from 'vs/base/common/objects'; import * as Objects from 'vs/base/common/objects';
import * as resources from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { IStringDictionary } from 'vs/base/common/collections'; import { IStringDictionary } from 'vs/base/common/collections';
import { Action } from 'vs/base/common/actions'; import { Action } from 'vs/base/common/actions';
@@ -77,6 +78,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { applyEdits } from 'vs/base/common/jsonEdit'; import { applyEdits } from 'vs/base/common/jsonEdit';
import { ITextEditor } from 'vs/workbench/common/editor'; import { ITextEditor } from 'vs/workbench/common/editor';
import { ITextEditorSelection } from 'vs/platform/editor/common/editor'; import { ITextEditorSelection } from 'vs/platform/editor/common/editor';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
export namespace ConfigureTaskAction { export namespace ConfigureTaskAction {
export const ID = 'workbench.action.tasks.configureTaskRunner'; export const ID = 'workbench.action.tasks.configureTaskRunner';
@@ -224,7 +226,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@ITerminalInstanceService private readonly terminalInstanceService: ITerminalInstanceService, @ITerminalInstanceService private readonly terminalInstanceService: ITerminalInstanceService,
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
@ITextModelService private readonly textModelResolverService: ITextModelService @ITextModelService private readonly textModelResolverService: ITextModelService,
@IPreferencesService private readonly preferencesService: IPreferencesService
) { ) {
super(); super();
@@ -389,6 +392,13 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
this.panelService.openPanel(Constants.MARKERS_PANEL_ID, true); this.panelService.openPanel(Constants.MARKERS_PANEL_ID, true);
} }
}); });
CommandsRegistry.registerCommand('workbench.action.tasks.configureUserTask', async () => {
const resource = this.getResourceForKind(TaskSourceKind.User);
if (resource) {
this.openTaskFile(resource);
}
});
} }
private get workspaceFolders(): IWorkspaceFolder[] { private get workspaceFolders(): IWorkspaceFolder[] {
@@ -963,10 +973,34 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
} }
} }
private getResourceForKind(kind: string): URI | undefined {
switch (kind) {
case TaskSourceKind.User: {
return resources.joinPath(resources.dirname(this.preferencesService.userSettingsResource), 'tasks.json');
}
case TaskSourceKind.WorkspaceFile: {
if (this._workspace && this._workspace.configuration) {
return this._workspace.configuration;
}
}
default: {
return undefined;
}
}
}
private getResourceForTask(task: CustomTask): URI {
let uri = this.getResourceForKind(task._source.kind);
if (!uri) {
uri = task.getWorkspaceFolder().toResource(task._source.config.file);
}
return uri;
}
public openConfig(task: CustomTask | undefined): Promise<void> { public openConfig(task: CustomTask | undefined): Promise<void> {
let resource: URI | undefined; let resource: URI | undefined;
if (task) { if (task) {
resource = task.getWorkspaceFolder().toResource(task._source.config.file); resource = this.getResourceForTask(task);
} else { } else {
resource = (this._workspaceFolders && (this._workspaceFolders.length > 0)) ? this._workspaceFolders[0].toResource('.vscode/tasks.json') : undefined; resource = (this._workspaceFolders && (this._workspaceFolders.length > 0)) ? this._workspaceFolders[0].toResource('.vscode/tasks.json') : undefined;
} }
@@ -2206,6 +2240,52 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
return result; return result;
} }
private openTaskFile(resource: URI) {
let configFileCreated = false;
this.fileService.resolve(resource).then((stat) => stat, () => undefined).then((stat) => {
if (stat) {
return stat.resource;
}
return this.quickInputService.pick(getTaskTemplates(), { placeHolder: nls.localize('TaskService.template', 'Select a Task Template') }).then((selection) => {
if (!selection) {
return Promise.resolve(undefined);
}
let content = selection.content;
let editorConfig = this.configurationService.getValue<any>();
if (editorConfig.editor.insertSpaces) {
content = content.replace(/(\n)(\t+)/g, (_, s1, s2) => s1 + strings.repeat(' ', s2.length * editorConfig.editor.tabSize));
}
configFileCreated = true;
type TaskServiceTemplateClassification = {
templateId?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
autoDetect: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
};
type TaskServiceEvent = {
templateId?: string;
autoDetect: boolean;
};
return this.textFileService.create(resource, content).then((result): URI => {
this.telemetryService.publicLog2<TaskServiceEvent, TaskServiceTemplateClassification>('taskService.template', {
templateId: selection.id,
autoDetect: selection.autoDetect
});
return result.resource;
});
});
}).then((resource) => {
if (!resource) {
return;
}
this.editorService.openEditor({
resource,
options: {
pinned: configFileCreated // pin only if config file is created #8727
}
});
});
}
private runConfigureTasks(): void { private runConfigureTasks(): void {
if (!this.canRunCommand()) { if (!this.canRunCommand()) {
return undefined; return undefined;
@@ -2217,52 +2297,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
taskPromise = Promise.resolve(new TaskMap()); taskPromise = Promise.resolve(new TaskMap());
} }
let openTaskFile = (workspaceFolder: IWorkspaceFolder): void => {
let resource = workspaceFolder.toResource('.vscode/tasks.json');
let configFileCreated = false;
this.fileService.resolve(resource).then((stat) => stat, () => undefined).then((stat) => {
if (stat) {
return stat.resource;
}
return this.quickInputService.pick(getTaskTemplates(), { placeHolder: nls.localize('TaskService.template', 'Select a Task Template') }).then((selection) => {
if (!selection) {
return Promise.resolve(undefined);
}
let content = selection.content;
let editorConfig = this.configurationService.getValue<any>();
if (editorConfig.editor.insertSpaces) {
content = content.replace(/(\n)(\t+)/g, (_, s1, s2) => s1 + strings.repeat(' ', s2.length * editorConfig.editor.tabSize));
}
configFileCreated = true;
type TaskServiceTemplateClassification = {
templateId?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
autoDetect: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
};
type TaskServiceEvent = {
templateId?: string;
autoDetect: boolean;
};
return this.textFileService.create(resource, content).then((result): URI => {
this.telemetryService.publicLog2<TaskServiceEvent, TaskServiceTemplateClassification>('taskService.template', {
templateId: selection.id,
autoDetect: selection.autoDetect
});
return result.resource;
});
});
}).then((resource) => {
if (!resource) {
return;
}
this.editorService.openEditor({
resource,
options: {
pinned: configFileCreated // pin only if config file is created #8727
}
});
});
};
let configureTask = (task: Task): void => { let configureTask = (task: Task): void => {
if (ContributedTask.is(task)) { if (ContributedTask.is(task)) {
this.customize(task, undefined, true); this.customize(task, undefined, true);
@@ -2343,7 +2377,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
if (isTaskEntry(selection)) { if (isTaskEntry(selection)) {
configureTask(selection.task); configureTask(selection.task);
} else { } else {
openTaskFile(selection.folder); this.openTaskFile(selection.folder.toResource('.vscode/tasks.json'));
} }
}); });
} }

View File

@@ -4,32 +4,15 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IUserDataSyncService, SyncStatus, SyncSource, CONTEXT_SYNC_STATE, registerConfiguration } from 'vs/platform/userDataSync/common/userDataSync'; import { registerConfiguration } from 'vs/platform/userDataSync/common/userDataSync';
import { localize } from 'vs/nls'; import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { Registry } from 'vs/platform/registry/common/platform'; import { Registry } from 'vs/platform/registry/common/platform';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { MenuRegistry, MenuId, IMenuItem } from 'vs/platform/actions/common/actions';
import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IActivityService, IBadge, NumberBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity';
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { URI } from 'vs/base/common/uri';
import { registerAndGetAmdImageURL } from 'vs/base/common/amd';
import { ResourceContextKey } from 'vs/workbench/common/resources';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { Event } from 'vs/base/common/event';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { isEqual } from 'vs/base/common/resources';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { isWeb } from 'vs/base/common/platform'; import { isWeb } from 'vs/base/common/platform';
import { UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService';
import { IProductService } from 'vs/platform/product/common/productService'; import { IProductService } from 'vs/platform/product/common/productService';
import { IEditorInput } from 'vs/workbench/common/editor'; import { UserDataSyncWorkbenchContribution } from 'vs/workbench/contrib/userDataSync/browser/userDataSync';
class UserDataSyncConfigurationContribution implements IWorkbenchContribution { class UserDataSyncConfigurationContribution implements IWorkbenchContribution {
@@ -54,185 +37,8 @@ class UserDataAutoSyncContribution extends Disposable implements IWorkbenchContr
} }
} }
const SYNC_PUSH_LIGHT_ICON_URI = URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/userDataSync/browser/media/check-light.svg`));
const SYNC_PUSH_DARK_ICON_URI = URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/userDataSync/browser/media/check-dark.svg`));
class SyncActionsContribution extends Disposable implements IWorkbenchContribution {
private readonly syncEnablementContext: IContextKey<string>;
private readonly badgeDisposable = this._register(new MutableDisposable());
private readonly conflictsWarningDisposable = this._register(new MutableDisposable());
constructor(
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
@IContextKeyService contextKeyService: IContextKeyService,
@IActivityService private readonly activityService: IActivityService,
@INotificationService private readonly notificationService: INotificationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEditorService private readonly editorService: IEditorService,
@ITextFileService private readonly textFileService: ITextFileService,
@IHistoryService private readonly historyService: IHistoryService,
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
) {
super();
this.syncEnablementContext = CONTEXT_SYNC_STATE.bindTo(contextKeyService);
this.onDidChangeStatus(userDataSyncService.status);
this._register(Event.debounce(userDataSyncService.onDidChangeStatus, () => undefined, 500)(status => this.onDidChangeStatus(userDataSyncService.status)));
this.registerActions();
}
private onDidChangeStatus(status: SyncStatus) {
this.syncEnablementContext.set(status);
let badge: IBadge | undefined = undefined;
let clazz: string | undefined;
if (status === SyncStatus.HasConflicts) {
badge = new NumberBadge(1, () => localize('resolve conflicts', "Resolve Conflicts"));
} else if (status === SyncStatus.Syncing) {
badge = new ProgressBadge(() => localize('syncing', "Synchronising User Configuration..."));
clazz = 'progress-badge';
}
this.badgeDisposable.clear();
if (badge) {
this.badgeDisposable.value = this.activityService.showActivity(GLOBAL_ACTIVITY_ID, badge, clazz);
}
if (status === SyncStatus.HasConflicts) {
if (!this.conflictsWarningDisposable.value) {
const handle = this.notificationService.prompt(Severity.Warning, localize('conflicts detected', "Unable to sync due to conflicts. Please resolve them to continue."),
[
{
label: localize('resolve', "Resolve Conflicts"),
run: () => this.handleConflicts()
}
]);
this.conflictsWarningDisposable.value = toDisposable(() => handle.close());
handle.onDidClose(() => this.conflictsWarningDisposable.clear());
}
} else {
const previewEditorInput = this.getPreviewEditorInput();
if (previewEditorInput) {
previewEditorInput.dispose();
}
this.conflictsWarningDisposable.clear();
}
}
private async continueSync(): Promise<void> {
// Get the preview editor
const previewEditorInput = this.getPreviewEditorInput();
// Save the preview
if (previewEditorInput && previewEditorInput.isDirty()) {
await this.textFileService.save(previewEditorInput.getResource()!);
}
try {
// Continue Sync
await this.userDataSyncService.sync(true);
} catch (error) {
this.notificationService.error(error);
return;
}
// Close the preview editor
if (previewEditorInput) {
previewEditorInput.dispose();
}
}
private getPreviewEditorInput(): IEditorInput | undefined {
return this.editorService.editors.filter(input => isEqual(input.getResource(), this.workbenchEnvironmentService.settingsSyncPreviewResource))[0];
}
private async handleConflicts(): Promise<void> {
if (this.userDataSyncService.conflictsSource === SyncSource.Settings) {
const resourceInput = {
resource: this.workbenchEnvironmentService.settingsSyncPreviewResource,
options: {
preserveFocus: false,
pinned: false,
revealIfVisible: true,
},
mode: 'jsonc'
};
this.editorService.openEditor(resourceInput)
.then(editor => {
this.historyService.remove(resourceInput);
if (editor && editor.input) {
// Trigger sync after closing the conflicts editor.
const disposable = editor.input.onDispose(() => {
disposable.dispose();
this.userDataSyncService.sync(true);
});
}
});
}
}
private registerActions(): void {
const startSyncMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'workbench.userData.actions.syncStart',
title: localize('start sync', "Configuration Sync: Turn On")
},
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), ContextKeyExpr.not('config.configurationSync.enable')),
};
CommandsRegistry.registerCommand(startSyncMenuItem.command.id, () => this.configurationService.updateValue('configurationSync.enable', true));
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, startSyncMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, startSyncMenuItem);
const stopSyncMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'workbench.userData.actions.stopSync',
title: localize('stop sync', "Configuration Sync: Turn Off")
},
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), ContextKeyExpr.has('config.configurationSync.enable')),
};
CommandsRegistry.registerCommand(stopSyncMenuItem.command.id, () => this.configurationService.updateValue('configurationSync.enable', false));
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, stopSyncMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, stopSyncMenuItem);
const resolveConflictsMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'sync.resolveConflicts',
title: localize('resolveConflicts', "Configuration Sync: Resolve Conflicts"),
},
when: CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts),
};
CommandsRegistry.registerCommand(resolveConflictsMenuItem.command.id, () => this.handleConflicts());
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, resolveConflictsMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, resolveConflictsMenuItem);
const continueSyncCommandId = 'workbench.userData.actions.continueSync';
CommandsRegistry.registerCommand(continueSyncCommandId, () => this.continueSync());
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: continueSyncCommandId,
title: localize('continue sync', "Configuration Sync: Continue")
},
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts)),
});
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: continueSyncCommandId,
title: localize('continue sync', "Configuration Sync: Continue"),
iconLocation: {
light: SYNC_PUSH_LIGHT_ICON_URI,
dark: SYNC_PUSH_DARK_ICON_URI
}
},
group: 'navigation',
order: 1,
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts), ResourceContextKey.Resource.isEqualTo(this.workbenchEnvironmentService.settingsSyncPreviewResource.toString())),
});
}
}
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench); const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(UserDataSyncConfigurationContribution, LifecyclePhase.Starting); workbenchRegistry.registerWorkbenchContribution(UserDataSyncConfigurationContribution, LifecyclePhase.Starting);
workbenchRegistry.registerWorkbenchContribution(SyncActionsContribution, LifecyclePhase.Restored); workbenchRegistry.registerWorkbenchContribution(UserDataSyncWorkbenchContribution, LifecyclePhase.Restored);
workbenchRegistry.registerWorkbenchContribution(UserDataAutoSyncContribution, LifecyclePhase.Restored); workbenchRegistry.registerWorkbenchContribution(UserDataAutoSyncContribution, LifecyclePhase.Restored);

View File

@@ -0,0 +1,283 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IUserDataSyncService, SyncStatus, SyncSource, CONTEXT_SYNC_STATE } from 'vs/platform/userDataSync/common/userDataSync';
import { localize } from 'vs/nls';
import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { MenuRegistry, MenuId, IMenuItem } from 'vs/platform/actions/common/actions';
import { IContextKeyService, IContextKey, ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IActivityService, IBadge, NumberBadge, ProgressBadge } from 'vs/workbench/services/activity/common/activity';
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { URI } from 'vs/base/common/uri';
import { registerAndGetAmdImageURL } from 'vs/base/common/amd';
import { ResourceContextKey } from 'vs/workbench/common/resources';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { Event } from 'vs/base/common/event';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { isEqual } from 'vs/base/common/resources';
import { IEditorInput } from 'vs/workbench/common/editor';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { timeout } from 'vs/base/common/async';
const CONTEXT_AUTH_TOKEN_STATE = new RawContextKey<string>('authTokenStatus', AuthTokenStatus.Inactive);
const SYNC_PUSH_LIGHT_ICON_URI = URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/userDataSync/browser/media/check-light.svg`));
const SYNC_PUSH_DARK_ICON_URI = URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/userDataSync/browser/media/check-dark.svg`));
export class UserDataSyncWorkbenchContribution extends Disposable implements IWorkbenchContribution {
private readonly syncStatusContext: IContextKey<string>;
private readonly authTokenContext: IContextKey<string>;
private readonly badgeDisposable = this._register(new MutableDisposable());
private readonly conflictsWarningDisposable = this._register(new MutableDisposable());
private readonly signInNotificationDisposable = this._register(new MutableDisposable());
constructor(
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
@IAuthTokenService private readonly authTokenService: IAuthTokenService,
@IContextKeyService contextKeyService: IContextKeyService,
@IActivityService private readonly activityService: IActivityService,
@INotificationService private readonly notificationService: INotificationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEditorService private readonly editorService: IEditorService,
@ITextFileService private readonly textFileService: ITextFileService,
@IHistoryService private readonly historyService: IHistoryService,
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
) {
super();
this.syncStatusContext = CONTEXT_SYNC_STATE.bindTo(contextKeyService);
this.authTokenContext = CONTEXT_AUTH_TOKEN_STATE.bindTo(contextKeyService);
this.onDidChangeAuthTokenStatus(this.authTokenService.status);
this.onDidChangeSyncStatus(this.userDataSyncService.status);
this._register(Event.debounce(authTokenService.onDidChangeStatus, () => undefined, 500)(() => this.onDidChangeAuthTokenStatus(this.authTokenService.status)));
this._register(Event.debounce(userDataSyncService.onDidChangeStatus, () => undefined, 500)(() => this.onDidChangeSyncStatus(this.userDataSyncService.status)));
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => this.updateBadge()));
this.registerActions();
timeout(2000).then(() => {
if (this.authTokenService.status === AuthTokenStatus.Inactive && configurationService.getValue<boolean>('configurationSync.enable')) {
this.showSignInNotification();
}
});
}
private onDidChangeAuthTokenStatus(status: AuthTokenStatus) {
this.authTokenContext.set(status);
if (status === AuthTokenStatus.Active) {
this.signInNotificationDisposable.clear();
}
this.updateBadge();
}
private onDidChangeSyncStatus(status: SyncStatus) {
this.syncStatusContext.set(status);
this.updateBadge();
if (this.userDataSyncService.status === SyncStatus.HasConflicts) {
if (!this.conflictsWarningDisposable.value) {
const handle = this.notificationService.prompt(Severity.Warning, localize('conflicts detected', "Unable to sync due to conflicts. Please resolve them to continue."),
[
{
label: localize('resolve', "Resolve Conflicts"),
run: () => this.handleConflicts()
}
]);
this.conflictsWarningDisposable.value = toDisposable(() => handle.close());
handle.onDidClose(() => this.conflictsWarningDisposable.clear());
}
} else {
const previewEditorInput = this.getPreviewEditorInput();
if (previewEditorInput) {
previewEditorInput.dispose();
}
this.conflictsWarningDisposable.clear();
}
}
private updateBadge(): void {
this.badgeDisposable.clear();
let badge: IBadge | undefined = undefined;
let clazz: string | undefined;
if (this.authTokenService.status === AuthTokenStatus.Inactive && this.configurationService.getValue<boolean>('configurationSync.enable')) {
badge = new NumberBadge(1, () => localize('sign in', "Sign in..."));
} else if (this.userDataSyncService.status === SyncStatus.HasConflicts) {
badge = new NumberBadge(1, () => localize('resolve conflicts', "Resolve Conflicts"));
} else if (this.userDataSyncService.status === SyncStatus.Syncing) {
badge = new ProgressBadge(() => localize('syncing', "Synchronising User Configuration..."));
clazz = 'progress-badge';
}
if (badge) {
this.badgeDisposable.value = this.activityService.showActivity(GLOBAL_ACTIVITY_ID, badge, clazz);
}
}
private showSignInNotification(): void {
const handle = this.notificationService.prompt(Severity.Info, localize('show sign in', "Please sign in to Settings Sync service to start syncing configuration."),
[
{
label: localize('sign in', "Sign in..."),
run: () => this.signIn()
}
]);
this.signInNotificationDisposable.value = toDisposable(() => handle.close());
handle.onDidClose(() => this.signInNotificationDisposable.clear());
}
private async signIn(): Promise<void> {
const token = await this.quickInputService.input({ placeHolder: localize('enter token', "Please provide the auth bearer token"), ignoreFocusLost: true, });
if (token) {
await this.authTokenService.updateToken(token);
}
}
private async signOut(): Promise<void> {
await this.authTokenService.deleteToken();
}
private async continueSync(): Promise<void> {
// Get the preview editor
const previewEditorInput = this.getPreviewEditorInput();
// Save the preview
if (previewEditorInput && previewEditorInput.isDirty()) {
await this.textFileService.save(previewEditorInput.getResource()!);
}
try {
// Continue Sync
await this.userDataSyncService.sync(true);
} catch (error) {
this.notificationService.error(error);
return;
}
// Close the preview editor
if (previewEditorInput) {
previewEditorInput.dispose();
}
}
private getPreviewEditorInput(): IEditorInput | undefined {
return this.editorService.editors.filter(input => isEqual(input.getResource(), this.workbenchEnvironmentService.settingsSyncPreviewResource))[0];
}
private async handleConflicts(): Promise<void> {
if (this.userDataSyncService.conflictsSource === SyncSource.Settings) {
const resourceInput = {
resource: this.workbenchEnvironmentService.settingsSyncPreviewResource,
options: {
preserveFocus: false,
pinned: false,
revealIfVisible: true,
},
mode: 'jsonc'
};
this.editorService.openEditor(resourceInput)
.then(editor => {
this.historyService.remove(resourceInput);
if (editor && editor.input) {
// Trigger sync after closing the conflicts editor.
const disposable = editor.input.onDispose(() => {
disposable.dispose();
this.userDataSyncService.sync(true);
});
}
});
}
}
private registerActions(): void {
const signInMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'workbench.userData.actions.login',
title: localize('sign in', "Sign in...")
},
when: ContextKeyExpr.and(CONTEXT_AUTH_TOKEN_STATE.isEqualTo(AuthTokenStatus.Inactive), ContextKeyExpr.has('config.configurationSync.enable')),
};
CommandsRegistry.registerCommand(signInMenuItem.command.id, () => this.signIn());
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, signInMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, signInMenuItem);
const signOutMenuItem: IMenuItem = {
command: {
id: 'workbench.userData.actions.logout',
title: localize('sign out', "Sign Out")
},
when: ContextKeyExpr.and(CONTEXT_AUTH_TOKEN_STATE.isEqualTo(AuthTokenStatus.Active)),
};
CommandsRegistry.registerCommand(signOutMenuItem.command.id, () => this.signOut());
MenuRegistry.appendMenuItem(MenuId.CommandPalette, signOutMenuItem);
const startSyncMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'workbench.userData.actions.syncStart',
title: localize('start sync', "Configuration Sync: Turn On")
},
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), ContextKeyExpr.not('config.configurationSync.enable')),
};
CommandsRegistry.registerCommand(startSyncMenuItem.command.id, () => this.configurationService.updateValue('configurationSync.enable', true));
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, startSyncMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, startSyncMenuItem);
const stopSyncMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'workbench.userData.actions.stopSync',
title: localize('stop sync', "Configuration Sync: Turn Off")
},
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), ContextKeyExpr.has('config.configurationSync.enable')),
};
CommandsRegistry.registerCommand(stopSyncMenuItem.command.id, () => this.configurationService.updateValue('configurationSync.enable', false));
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, stopSyncMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, stopSyncMenuItem);
const resolveConflictsMenuItem: IMenuItem = {
group: '5_sync',
command: {
id: 'sync.resolveConflicts',
title: localize('resolveConflicts', "Configuration Sync: Resolve Conflicts"),
},
when: CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts),
};
CommandsRegistry.registerCommand(resolveConflictsMenuItem.command.id, () => this.handleConflicts());
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, resolveConflictsMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, resolveConflictsMenuItem);
const continueSyncCommandId = 'workbench.userData.actions.continueSync';
CommandsRegistry.registerCommand(continueSyncCommandId, () => this.continueSync());
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: continueSyncCommandId,
title: localize('continue sync', "Configuration Sync: Continue")
},
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts)),
});
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: continueSyncCommandId,
title: localize('continue sync', "Configuration Sync: Continue"),
iconLocation: {
light: SYNC_PUSH_LIGHT_ICON_URI,
dark: SYNC_PUSH_DARK_ICON_URI
}
},
group: 'navigation',
order: 1,
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts), ResourceContextKey.Resource.isEqualTo(this.workbenchEnvironmentService.settingsSyncPreviewResource.toString())),
});
}
}

View File

@@ -15,7 +15,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors'; import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors';
import { IWindowOpenable } from 'vs/platform/windows/common/windows'; 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 { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { localize } from 'vs/nls'; 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 { IFileService } from 'vs/platform/files/common/files';
import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { joinPath } from 'vs/base/common/resources'; 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 { CancellationToken } from 'vs/base/common/cancellation';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; // {{SQL CARBON EDIT}} import { IEnvironmentService } from 'vs/platform/environment/common/environment'; // {{SQL CARBON EDIT}}
import { setProductQuality } from 'sql/workbench/contrib/welcome/page/browser/az_data_welcome_page'; // {{SQL CARBON EDIT}} import { setProductQuality } from 'sql/workbench/contrib/welcome/page/browser/az_data_welcome_page'; // {{SQL CARBON EDIT}}
@@ -255,7 +254,7 @@ class WelcomePage extends Disposable {
constructor( constructor(
@IEditorService private readonly editorService: IEditorService, @IEditorService private readonly editorService: IEditorService,
@IInstantiationService private readonly instantiationService: IInstantiationService, @IInstantiationService private readonly instantiationService: IInstantiationService,
@IWorkspacesHistoryService private readonly workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService private readonly workspacesService: IWorkspacesService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService, @IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService, @ILabelService private readonly labelService: ILabelService,
@@ -273,7 +272,7 @@ class WelcomePage extends Disposable {
super(); super();
this._register(lifecycleService.onShutdown(() => this.dispose())); this._register(lifecycleService.onShutdown(() => this.dispose()));
const recentlyOpened = this.workspacesHistoryService.getRecentlyOpened(); const recentlyOpened = this.workspacesService.getRecentlyOpened();
const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions); const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions);
// {{SQL CARBON EDIT}} - Redirect to ADS welcome page // {{SQL CARBON EDIT}} - Redirect to ADS welcome page
setProductQuality(this.environmentService.appQuality); setProductQuality(this.environmentService.appQuality);

View File

@@ -7,7 +7,7 @@ import { Action } from 'vs/base/common/actions';
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';

View File

@@ -23,14 +23,14 @@ import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/c
import { IResourceInput } from 'vs/platform/editor/common/editor'; import { IResourceInput } from 'vs/platform/editor/common/editor';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService'; import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService';
import { ipcRenderer as ipc, webFrame, crashReporter, Event } from 'electron'; import { ipcRenderer as ipc, webFrame, crashReporter, Event } from 'electron';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common/workspaceEditing'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction, SubmenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction, SubmenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { RunOnceScheduler } from 'vs/base/common/async'; import { RunOnceScheduler } from 'vs/base/common/async';
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { LifecyclePhase, ILifecycleService } from 'vs/platform/lifecycle/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 { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity';
import { isRootUser, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform'; import { isRootUser, isWindows, isMacintosh, isLinux } from 'vs/base/common/platform';
import product from 'vs/platform/product/common/product'; 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 { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService'; import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService';
import { IWorkspacesHistoryService } from 'vs/workbench/services/workspace/common/workspacesHistoryService';
const TextInputActions: IAction[] = [ const TextInputActions: IAction[] = [
new Action('undo', nls.localize('undo', "Undo"), undefined, true, () => Promise.resolve(document.execCommand('undo'))), 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 { class NativeMenubarControl extends MenubarControl {
constructor( constructor(
@IMenuService menuService: IMenuService, @IMenuService menuService: IMenuService,
@IWorkspacesHistoryService workspacesHistoryService: IWorkspacesHistoryService, @IWorkspacesService workspacesService: IWorkspacesService,
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService contextKeyService: IContextKeyService,
@IKeybindingService keybindingService: IKeybindingService, @IKeybindingService keybindingService: IKeybindingService,
@IConfigurationService configurationService: IConfigurationService, @IConfigurationService configurationService: IConfigurationService,
@@ -698,7 +697,7 @@ class NativeMenubarControl extends MenubarControl {
) { ) {
super( super(
menuService, menuService,
workspacesHistoryService, workspacesService,
contextKeyService, contextKeyService,
keybindingService, keybindingService,
configurationService, configurationService,
@@ -725,7 +724,7 @@ class NativeMenubarControl extends MenubarControl {
} }
(async () => { (async () => {
this.recentlyOpened = await this.workspacesHistoryService.getRecentlyOpened(); this.recentlyOpened = await this.workspacesService.getRecentlyOpened();
this.doUpdateMenubar(true); this.doUpdateMenubar(true);
})(); })();

View File

@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
export class AuthTokenService extends Disposable implements IAuthTokenService {
_serviceBrand: undefined;
private readonly channel: IChannel;
private _status: AuthTokenStatus = AuthTokenStatus.Disabled;
get status(): AuthTokenStatus { return this._status; }
private _onDidChangeStatus: Emitter<AuthTokenStatus> = this._register(new Emitter<AuthTokenStatus>());
readonly onDidChangeStatus: Event<AuthTokenStatus> = this._onDidChangeStatus.event;
constructor(
@ISharedProcessService sharedProcessService: ISharedProcessService
) {
super();
this.channel = sharedProcessService.getChannel('authToken');
this.channel.call<AuthTokenStatus>('_getInitialStatus').then(status => {
this.updateStatus(status);
this._register(this.channel.listen<AuthTokenStatus>('onDidChangeStatus')(status => this.updateStatus(status)));
});
}
getToken(): Promise<string> {
return this.channel.call('getToken');
}
updateToken(token: string): Promise<void> {
return this.channel.call('updateToken', [token]);
}
refreshToken(): Promise<void> {
return this.channel.call('getToken');
}
deleteToken(): Promise<void> {
return this.channel.call('deleteToken');
}
private async updateStatus(status: AuthTokenStatus): Promise<void> {
this._status = status;
this._onDidChangeStatus.fire(status);
}
}
registerSingleton(IAuthTokenService, AuthTokenService);

View File

@@ -7,8 +7,9 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
import { clipboard } from 'electron'; import { clipboard } from 'electron';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { isMacintosh } from 'vs/base/common/platform'; import { isMacintosh } from 'vs/base/common/platform';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
export class ClipboardService implements IClipboardService { export class NativeClipboardService implements IClipboardService {
private static FILE_FORMAT = 'code/file-list'; // Clipboard format for files private static FILE_FORMAT = 'code/file-list'; // Clipboard format for files
@@ -42,16 +43,16 @@ export class ClipboardService implements IClipboardService {
writeResources(resources: URI[]): void { writeResources(resources: URI[]): void {
if (resources.length) { if (resources.length) {
clipboard.writeBuffer(ClipboardService.FILE_FORMAT, this.resourcesToBuffer(resources)); clipboard.writeBuffer(NativeClipboardService.FILE_FORMAT, this.resourcesToBuffer(resources));
} }
} }
readResources(): URI[] { readResources(): URI[] {
return this.bufferToResources(clipboard.readBuffer(ClipboardService.FILE_FORMAT)); return this.bufferToResources(clipboard.readBuffer(NativeClipboardService.FILE_FORMAT));
} }
hasResources(): boolean { hasResources(): boolean {
return clipboard.has(ClipboardService.FILE_FORMAT); return clipboard.has(NativeClipboardService.FILE_FORMAT);
} }
private resourcesToBuffer(resources: URI[]): Buffer { private resourcesToBuffer(resources: URI[]): Buffer {
@@ -75,3 +76,5 @@ export class ClipboardService implements IClipboardService {
} }
} }
} }
registerSingleton(IClipboardService, NativeClipboardService, true);

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ICredentialsService } from 'vs/workbench/services/credentials/common/credentials'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ICredentialsService } from 'vs/workbench/services/credentials/common/credentials'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { IdleValue } from 'vs/base/common/async'; import { IdleValue } from 'vs/base/common/async';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions';

Some files were not shown because too many files have changed in this diff Show More