mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-10 02:02:35 -05:00
Merge from vscode ad407028575a77ea387eb7cc219b323dc017b686
This commit is contained in:
committed by
Anthony Dresser
parent
404260b8a0
commit
4ad73d381c
@@ -16,9 +16,29 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
|
||||
export function getAuthenticationProviderActivationEvent(id: string): string { return `onAuthenticationRequest:${id}`; }
|
||||
|
||||
export type AuthenticationSessionInfo = { readonly id: string, readonly accessToken: string, readonly providerId: string };
|
||||
export async function getCurrentAuthenticationSessionInfo(environmentService: IWorkbenchEnvironmentService, productService: IProductService): Promise<AuthenticationSessionInfo | undefined> {
|
||||
if (environmentService.options?.credentialsProvider) {
|
||||
const authenticationSessionValue = await environmentService.options.credentialsProvider.getPassword(`${productService.urlProtocol}.login`, 'account');
|
||||
if (authenticationSessionValue) {
|
||||
const authenticationSessionInfo: AuthenticationSessionInfo = JSON.parse(authenticationSessionValue);
|
||||
if (authenticationSessionInfo
|
||||
&& isString(authenticationSessionInfo.id)
|
||||
&& isString(authenticationSessionInfo.accessToken)
|
||||
&& isString(authenticationSessionInfo.providerId)
|
||||
) {
|
||||
return authenticationSessionInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export const IAuthenticationService = createDecorator<IAuthenticationService>('IAuthenticationService');
|
||||
|
||||
export interface IAuthenticationService {
|
||||
@@ -227,8 +247,22 @@ export class AuthenticationService extends Disposable implements IAuthentication
|
||||
}
|
||||
}
|
||||
|
||||
requestNewSession(providerId: string, scopes: string[], extensionId: string, extensionName: string): void {
|
||||
const provider = this._authenticationProviders.get(providerId);
|
||||
async requestNewSession(providerId: string, scopes: string[], extensionId: string, extensionName: string): Promise<void> {
|
||||
let provider = this._authenticationProviders.get(providerId);
|
||||
if (!provider) {
|
||||
// Activate has already been called for the authentication provider, but it cannot block on registering itself
|
||||
// since this is sync and returns a disposable. So, wait for registration event to fire that indicates the
|
||||
// provider is now in the map.
|
||||
await new Promise((resolve, _) => {
|
||||
this.onDidRegisterAuthenticationProvider(e => {
|
||||
if (e.id === providerId) {
|
||||
provider = this._authenticationProviders.get(providerId);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (provider) {
|
||||
const providerRequests = this._signInRequestItems.get(providerId);
|
||||
const scopesList = scopes.sort().join('');
|
||||
|
||||
@@ -353,8 +353,9 @@ export class ConfigurationEditingService {
|
||||
}
|
||||
}
|
||||
return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open the '{0}' folder settings to correct errors/warnings in it and try again.", workspaceFolderName);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
case ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY: {
|
||||
if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY) {
|
||||
@@ -379,8 +380,9 @@ export class ConfigurationEditingService {
|
||||
}
|
||||
}
|
||||
return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the '{0}' folder settings file first and then try again.", workspaceFolderName);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
case ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_MODIFIED_SINCE:
|
||||
if (operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY) {
|
||||
@@ -412,8 +414,9 @@ export class ConfigurationEditingService {
|
||||
return nls.localize('workspaceTarget', "Workspace Settings");
|
||||
case EditableConfigurationTarget.WORKSPACE_FOLDER:
|
||||
return nls.localize('folderTarget', "Folder Settings");
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private getEdits(model: ITextModel, edit: IConfigurationEditOperation): Edit[] {
|
||||
|
||||
@@ -264,7 +264,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
||||
if (!Types.isString(info.description)) {
|
||||
missingAttribute('description');
|
||||
}
|
||||
const inputOptions: IInputOptions = { prompt: info.description };
|
||||
const inputOptions: IInputOptions = { prompt: info.description, ignoreFocusLost: true };
|
||||
if (info.default) {
|
||||
inputOptions.value = info.default;
|
||||
}
|
||||
@@ -310,7 +310,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
|
||||
picks.push(item);
|
||||
}
|
||||
});
|
||||
const pickOptions: IPickOptions<PickStringItem> = { placeHolder: info.description, matchOnDetail: true };
|
||||
const pickOptions: IPickOptions<PickStringItem> = { placeHolder: info.description, matchOnDetail: true, ignoreFocusLost: true };
|
||||
return this.quickInputService.pick(picks, pickOptions, undefined).then(resolvedInput => {
|
||||
if (resolvedInput) {
|
||||
return resolvedInput.value;
|
||||
|
||||
@@ -142,10 +142,9 @@ class NativeContextMenuService extends Disposable implements IContextMenuService
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const actions = Array.isArray(entry.actions) ? entry.actions : entry.actions();
|
||||
return {
|
||||
label: unmnemonicLabel(stripCodicons(entry.label)).trim(),
|
||||
submenu: this.createMenu(delegate, actions, onHide, new Set([...submenuIds, entry.id]))
|
||||
submenu: this.createMenu(delegate, entry.actions, onHide, new Set([...submenuIds, entry.id]))
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,21 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
|
||||
import { ICredentialsProvider, ICredentialsService } from 'vs/platform/credentials/common/credentials';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
|
||||
export interface ICredentialsProvider {
|
||||
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; }>>;
|
||||
}
|
||||
|
||||
export class BrowserCredentialsService implements ICredentialsService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
@@ -24,7 +24,7 @@ export class DialogService implements IDialogService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private allowableCommands = ['copy', 'cut'];
|
||||
private allowableCommands = ['copy', 'cut', 'editor.action.clipboardCopyAction', 'editor.action.clipboardCutAction'];
|
||||
|
||||
constructor(
|
||||
@ILogService private readonly logService: ILogService,
|
||||
|
||||
@@ -747,9 +747,9 @@ export class EditorService extends Disposable implements EditorServiceImpl {
|
||||
|
||||
//#region replaceEditors()
|
||||
|
||||
replaceEditors(editors: IResourceEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
|
||||
replaceEditors(editors: IEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
|
||||
replaceEditors(editors: Array<IEditorReplacement | IResourceEditorReplacement>, group: IEditorGroup | GroupIdentifier): Promise<void> {
|
||||
async replaceEditors(editors: IResourceEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
|
||||
async replaceEditors(editors: IEditorReplacement[], group: IEditorGroup | GroupIdentifier): Promise<void>;
|
||||
async replaceEditors(editors: Array<IEditorReplacement | IResourceEditorReplacement>, group: IEditorGroup | GroupIdentifier): Promise<void> {
|
||||
const typedEditors: IEditorReplacement[] = [];
|
||||
|
||||
editors.forEach(replaceEditorArg => {
|
||||
@@ -776,8 +776,6 @@ export class EditorService extends Disposable implements EditorServiceImpl {
|
||||
if (targetGroup) {
|
||||
return targetGroup.replaceEditors(typedEditors);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -17,8 +17,8 @@ export interface INativeWorkbenchEnvironmentService extends IWorkbenchEnvironmen
|
||||
|
||||
readonly configuration: INativeEnvironmentConfiguration;
|
||||
|
||||
readonly disableCrashReporter: boolean;
|
||||
readonly crashReporterDirectory?: string;
|
||||
readonly crashReporterId?: string;
|
||||
|
||||
readonly cliPath: string;
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
||||
import { ITelemetryData } from 'vs/base/common/actions';
|
||||
import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
const storageKey = 'VSCode.ABExp.FeatureData';
|
||||
const refetchInterval = 1000 * 60 * 30; // By default it's set up to 30 minutes.
|
||||
const refetchInterval = 0; // no polling
|
||||
|
||||
class MementoKeyValueStorage implements IKeyValueStorage {
|
||||
constructor(private mementoObj: MementoObject) { }
|
||||
@@ -160,13 +161,18 @@ export class ExperimentService implements ITASExperimentService {
|
||||
private tasClient: Promise<TASClient> | undefined;
|
||||
private static MEMENTO_ID = 'experiment.service.memento';
|
||||
|
||||
private get experimentsEnabled(): boolean {
|
||||
return this.configurationService.getValue('workbench.enableExperiments') === true;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@IProductService private productService: IProductService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IStorageService private storageService: IStorageService
|
||||
@IStorageService private storageService: IStorageService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
) {
|
||||
|
||||
if (this.productService.tasConfig) {
|
||||
if (this.productService.tasConfig && this.experimentsEnabled && this.telemetryService.isOptedIn) {
|
||||
this.tasClient = this.setupTASClient();
|
||||
}
|
||||
}
|
||||
@@ -176,6 +182,10 @@ export class ExperimentService implements ITASExperimentService {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this.experimentsEnabled) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return (await this.tasClient).getTreatmentVariable<T>('vscode', name);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,38 +29,54 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
|
||||
@IUriIdentityService uriIdentityService: IUriIdentityService,
|
||||
) {
|
||||
if (isWeb) {
|
||||
const builtinExtensionsServiceUrl = this._getBuiltinExtensionsUrl(environmentService);
|
||||
if (builtinExtensionsServiceUrl) {
|
||||
let scannedBuiltinExtensions: IScannedBuiltinExtension[] = [];
|
||||
|
||||
const builtinExtensionsServiceUrl = environmentService.options?.builtinExtensionsServiceUrl ? URI.parse(environmentService.options?.builtinExtensionsServiceUrl) : undefined;
|
||||
if (isWeb && builtinExtensionsServiceUrl) {
|
||||
|
||||
let scannedBuiltinExtensions: IScannedBuiltinExtension[] = [];
|
||||
|
||||
if (environmentService.isBuilt) {
|
||||
// Built time configuration (do NOT modify)
|
||||
scannedBuiltinExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/];
|
||||
} else {
|
||||
// Find builtin extensions by checking for DOM
|
||||
const builtinExtensionsElement = document.getElementById('vscode-workbench-builtin-extensions');
|
||||
const builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined;
|
||||
if (builtinExtensionsElementAttribute) {
|
||||
try {
|
||||
scannedBuiltinExtensions = JSON.parse(builtinExtensionsElementAttribute);
|
||||
} catch (error) { /* ignore error*/ }
|
||||
if (environmentService.isBuilt) {
|
||||
// Built time configuration (do NOT modify)
|
||||
scannedBuiltinExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/];
|
||||
} else {
|
||||
// Find builtin extensions by checking for DOM
|
||||
const builtinExtensionsElement = document.getElementById('vscode-workbench-builtin-extensions');
|
||||
const builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined;
|
||||
if (builtinExtensionsElementAttribute) {
|
||||
try {
|
||||
scannedBuiltinExtensions = JSON.parse(builtinExtensionsElementAttribute);
|
||||
} catch (error) { /* ignore error*/ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.builtinExtensions = scannedBuiltinExtensions.map(e => ({
|
||||
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
|
||||
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
|
||||
type: ExtensionType.System,
|
||||
packageJSON: e.packageJSON,
|
||||
packageNLS: e.packageNLS,
|
||||
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
|
||||
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
|
||||
}));
|
||||
this.builtinExtensions = scannedBuiltinExtensions.map(e => ({
|
||||
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
|
||||
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
|
||||
type: ExtensionType.System,
|
||||
packageJSON: e.packageJSON,
|
||||
packageNLS: e.packageNLS,
|
||||
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
|
||||
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _getBuiltinExtensionsUrl(environmentService: IWorkbenchEnvironmentService): URI | undefined {
|
||||
if (environmentService.options?.builtinExtensionsServiceUrl) {
|
||||
return URI.parse(environmentService.options?.builtinExtensionsServiceUrl);
|
||||
}
|
||||
let enableBuiltinExtensions: boolean;
|
||||
if (environmentService.options && typeof environmentService.options._enableBuiltinExtensions !== 'undefined') {
|
||||
enableBuiltinExtensions = environmentService.options._enableBuiltinExtensions;
|
||||
} else {
|
||||
enableBuiltinExtensions = environmentService.configuration.remoteAuthority ? false : true;
|
||||
}
|
||||
if (enableBuiltinExtensions) {
|
||||
return URI.parse(require.toUrl('../../../../../../extensions'));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async scanBuiltinExtensions(): Promise<IScannedExtension[]> {
|
||||
if (isWeb) {
|
||||
return this.builtinExtensions;
|
||||
|
||||
@@ -93,7 +93,7 @@ export class WebExtensionsScannerService extends Disposable implements IWebExten
|
||||
.map(e => ({
|
||||
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
|
||||
location: e.extensionLocation,
|
||||
type: ExtensionType.System,
|
||||
type: e.isBuiltin ? ExtensionType.System : ExtensionType.User,
|
||||
packageJSON: e.packageJSON,
|
||||
}))
|
||||
);
|
||||
|
||||
@@ -24,6 +24,8 @@ import { FetchFileSystemProvider } from 'vs/workbench/services/extensions/browse
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IUserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit';
|
||||
|
||||
export class ExtensionService extends AbstractExtensionService implements IExtensionService {
|
||||
|
||||
@@ -43,6 +45,8 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
|
||||
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||
@IWebExtensionsScannerService private readonly _webExtensionsScannerService: IWebExtensionsScannerService,
|
||||
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
|
||||
@IUserDataInitializationService private readonly _userDataInitializationService: IUserDataInitializationService,
|
||||
) {
|
||||
super(
|
||||
instantiationService,
|
||||
@@ -56,7 +60,12 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
|
||||
this._runningLocation = new Map<string, ExtensionRunningLocation>();
|
||||
|
||||
this._initialize();
|
||||
// Initialize extensions first and do it only after workbench is ready
|
||||
this._lifecycleService.when(LifecyclePhase.Ready).then(async () => {
|
||||
await this._userDataInitializationService.initializeExtensions(this._instantiationService);
|
||||
this._initialize();
|
||||
});
|
||||
|
||||
this._initFetchFileSystem();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { canceled, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { WEB_WORKER_IFRAME } from 'vs/workbench/services/extensions/common/webWorkerIframe';
|
||||
|
||||
const WRAP_IN_IFRAME = true;
|
||||
|
||||
export interface IWebWorkerExtensionHostInitData {
|
||||
readonly autoStart: boolean;
|
||||
readonly extensions: IExtensionDescription[];
|
||||
@@ -74,7 +72,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
|
||||
public async start(): Promise<IMessagePassingProtocol> {
|
||||
if (!this._protocolPromise) {
|
||||
if (WRAP_IN_IFRAME && platform.isWeb) {
|
||||
if (platform.isWeb && this._environmentService.options && this._environmentService.options._wrapWebWorkerExtHostInIframe) {
|
||||
this._protocolPromise = this._startInsideIframe();
|
||||
} else {
|
||||
this._protocolPromise = this._startOutsideIframe();
|
||||
@@ -98,10 +96,11 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
|
||||
const escapeAttribute = (value: string): string => {
|
||||
return value.replace(/"/g, '"');
|
||||
};
|
||||
const isBuilt = this._environmentService.isBuilt;
|
||||
const html = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-eval' '${WEB_WORKER_IFRAME.sha}' *; worker-src data:; connect-src *" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-eval' '${WEB_WORKER_IFRAME.sha}' ${isBuilt ? 'https:' : 'http: https:'}; worker-src data:; connect-src ${isBuilt ? 'https:' : 'http: https:'}" />
|
||||
<meta id="vscode-worker-src" data-value="${escapeAttribute(workerSrc)}" />
|
||||
<meta id="vscode-web-worker-ext-host-id" data-value="${escapeAttribute(vscodeWebWorkerExtHostId)}" />
|
||||
</head>
|
||||
|
||||
@@ -44,6 +44,7 @@ import { joinPath } from 'vs/base/common/resources';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IOutputChannelRegistry, Extensions } from 'vs/workbench/services/output/common/output';
|
||||
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
|
||||
import { isUUID } from 'vs/base/common/uuid';
|
||||
|
||||
export interface ILocalProcessExtensionHostInitData {
|
||||
readonly autoStart: boolean;
|
||||
@@ -182,18 +183,23 @@ export class LocalProcessExtensionHost implements IExtensionHost {
|
||||
opts.execArgv = ['--inspect-port=0'];
|
||||
}
|
||||
|
||||
// Enable the crash reporter depending on environment for local reporting
|
||||
const crashesDirectory = this._environmentService.crashReporterDirectory;
|
||||
if (crashesDirectory) {
|
||||
const crashReporterOptions: CrashReporterStartOptions = {
|
||||
// On linux crash reporter needs to be started on child node processes explicitly
|
||||
if (platform.isLinux) {
|
||||
const crashReporterStartOptions: CrashReporterStartOptions = {
|
||||
companyName: this._productService.crashReporter?.companyName || 'Microsoft',
|
||||
productName: this._productService.crashReporter?.productName || this._productService.nameShort,
|
||||
submitURL: '',
|
||||
uploadToServer: false,
|
||||
crashesDirectory
|
||||
uploadToServer: false
|
||||
};
|
||||
|
||||
opts.env.CRASH_REPORTER_START_OPTIONS = JSON.stringify(crashReporterOptions);
|
||||
const crashReporterId = this._environmentService.crashReporterId; // crashReporterId is set by the main process only when crash reporting is enabled by the user.
|
||||
const appcenter = this._productService.appCenter;
|
||||
const uploadCrashesToServer = !this._environmentService.crashReporterDirectory; // only upload unless --crash-reporter-directory is provided
|
||||
if (uploadCrashesToServer && appcenter && crashReporterId && isUUID(crashReporterId)) {
|
||||
const submitURL = appcenter[`linux-x64`];
|
||||
crashReporterStartOptions.submitURL = submitURL.concat('&uid=', crashReporterId, '&iid=', crashReporterId, '&sid=', crashReporterId);
|
||||
crashReporterStartOptions.uploadToServer = true;
|
||||
}
|
||||
opts.env.CRASH_REPORTER_START_OPTIONS = JSON.stringify(crashReporterStartOptions);
|
||||
}
|
||||
|
||||
// Run Extension Host as fork of current process
|
||||
|
||||
@@ -139,11 +139,9 @@ suite('RPCProtocol', () => {
|
||||
let p = bProxy.$m(4, tokenSource.token);
|
||||
p.then((res: number) => {
|
||||
assert.equal(res, 7);
|
||||
done(null);
|
||||
}, (err) => {
|
||||
assert.fail('should not receive error');
|
||||
done();
|
||||
});
|
||||
}).finally(done);
|
||||
tokenSource.cancel();
|
||||
});
|
||||
|
||||
@@ -153,11 +151,9 @@ suite('RPCProtocol', () => {
|
||||
};
|
||||
bProxy.$m(4, 1).then((res) => {
|
||||
assert.fail('unexpected');
|
||||
done(null);
|
||||
}, (err) => {
|
||||
assert.equal(err.message, 'nope');
|
||||
done(null);
|
||||
});
|
||||
}).finally(done);
|
||||
});
|
||||
|
||||
test('error promise', function (done) {
|
||||
@@ -166,11 +162,9 @@ suite('RPCProtocol', () => {
|
||||
};
|
||||
bProxy.$m(4, 1).then((res) => {
|
||||
assert.fail('unexpected');
|
||||
done(null);
|
||||
}, (err) => {
|
||||
assert.equal(err, undefined);
|
||||
done(null);
|
||||
});
|
||||
}).finally(done);
|
||||
});
|
||||
|
||||
test('issue #60450: Converting circular structure to JSON', function (done) {
|
||||
@@ -181,11 +175,9 @@ suite('RPCProtocol', () => {
|
||||
};
|
||||
bProxy.$m(4, 1).then((res) => {
|
||||
assert.equal(res, null);
|
||||
done(null);
|
||||
}, (err) => {
|
||||
assert.fail('unexpected');
|
||||
done(null);
|
||||
});
|
||||
}).finally(done);
|
||||
});
|
||||
|
||||
test('issue #72798: null errors are hard to digest', function (done) {
|
||||
@@ -195,11 +187,9 @@ suite('RPCProtocol', () => {
|
||||
};
|
||||
bProxy.$m(4, 1).then((res) => {
|
||||
assert.fail('unexpected');
|
||||
done(null);
|
||||
}, (err) => {
|
||||
assert.equal(err.what, 'what');
|
||||
done(null);
|
||||
});
|
||||
}).finally(done);
|
||||
});
|
||||
|
||||
test('undefined arguments arrive as null', function () {
|
||||
|
||||
@@ -109,4 +109,10 @@ export interface IHoverTarget extends IDisposable {
|
||||
* wrapped text.
|
||||
*/
|
||||
readonly targetElements: readonly HTMLElement[];
|
||||
|
||||
/**
|
||||
* An optional absolute x coordinate to position the hover with, for example to position the
|
||||
* hover using `MouseEvent.pageX`.
|
||||
*/
|
||||
x?: number;
|
||||
}
|
||||
|
||||
@@ -136,11 +136,12 @@ export class HoverWidget extends Widget {
|
||||
this._hover.containerDomNode.classList.remove('right-aligned');
|
||||
this._hover.contentsDomNode.style.maxHeight = '';
|
||||
|
||||
// Get horizontal alignment and position
|
||||
const targetBounds = this._target.targetElements.map(e => e.getBoundingClientRect());
|
||||
const targetLeft = Math.min(...targetBounds.map(e => e.left));
|
||||
|
||||
// Get horizontal alignment and position
|
||||
let targetLeft = this._target.x !== undefined ? this._target.x : Math.min(...targetBounds.map(e => e.left));
|
||||
if (targetLeft + this._hover.containerDomNode.clientWidth >= document.documentElement.clientWidth) {
|
||||
this._x = document.documentElement.clientWidth;
|
||||
this._x = document.documentElement.clientWidth - 1;
|
||||
this._hover.containerDomNode.classList.add('right-aligned');
|
||||
} else {
|
||||
this._x = targetLeft;
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
color: #3794ff;
|
||||
}
|
||||
|
||||
.monaco-workbench .workbench-hover.right-aligned {
|
||||
/* The context view service wraps strangely when it's right up against the edge without this */
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench .workbench-hover.right-aligned .hover-row.status-bar .actions {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
@@ -33,9 +33,8 @@ export function positionToString(position: Position): string {
|
||||
case Position.LEFT: return 'left';
|
||||
case Position.RIGHT: return 'right';
|
||||
case Position.BOTTOM: return 'bottom';
|
||||
default: return 'bottom';
|
||||
}
|
||||
|
||||
return 'bottom';
|
||||
}
|
||||
|
||||
const positionsByString: { [key: string]: Position } = {
|
||||
|
||||
@@ -135,16 +135,16 @@ export class NativeLifecycleService extends AbstractLifecycleService {
|
||||
let message: string;
|
||||
switch (reason) {
|
||||
case ShutdownReason.CLOSE:
|
||||
message = localize('errorClose', "An unexpected error prevented the window from closing ({0}).", toErrorMessage(error));
|
||||
message = localize('errorClose', "An unexpected error was thrown while attempting to close the window ({0}).", toErrorMessage(error));
|
||||
break;
|
||||
case ShutdownReason.QUIT:
|
||||
message = localize('errorQuit', "An unexpected error prevented the application from closing ({0}).", toErrorMessage(error));
|
||||
message = localize('errorQuit', "An unexpected error was thrown while attempting to quit the application ({0}).", toErrorMessage(error));
|
||||
break;
|
||||
case ShutdownReason.RELOAD:
|
||||
message = localize('errorReload', "An unexpected error prevented the window from reloading ({0}).", toErrorMessage(error));
|
||||
message = localize('errorReload', "An unexpected error was thrown while attempting to reload the window ({0}).", toErrorMessage(error));
|
||||
break;
|
||||
case ShutdownReason.LOAD:
|
||||
message = localize('errorLoad', "An unexpected error prevented the window from changing it's workspace ({0}).", toErrorMessage(error));
|
||||
message = localize('errorLoad', "An unexpected error was thrown while attempting to change the workspace of the window ({0}).", toErrorMessage(error));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ export interface ISettingsGroup {
|
||||
title: string;
|
||||
titleRange: IRange;
|
||||
sections: ISettingsSection[];
|
||||
contributedByExtension: boolean;
|
||||
extensionInfo?: IConfigurationExtensionInfo;
|
||||
}
|
||||
|
||||
export interface ISettingsSection {
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { flatten, tail, find, coalesce } from 'vs/base/common/arrays';
|
||||
import { flatten, tail, coalesce } from 'vs/base/common/arrays';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { JSONVisitor, visit } from 'vs/base/common/json';
|
||||
import { Disposable, IReference } from 'vs/base/common/lifecycle';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
@@ -198,7 +197,7 @@ export class SettingsEditorModel extends AbstractSettingsModel implements ISetti
|
||||
}],
|
||||
title: modelGroup.title,
|
||||
titleRange: modelGroup.titleRange,
|
||||
contributedByExtension: !!modelGroup.contributedByExtension
|
||||
extensionInfo: modelGroup.extensionInfo
|
||||
};
|
||||
}
|
||||
|
||||
@@ -291,7 +290,7 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string,
|
||||
endLineNumber: valueEndPosition.lineNumber,
|
||||
endColumn: valueEndPosition.column
|
||||
};
|
||||
setting.range = assign(setting.range, {
|
||||
setting.range = Object.assign(setting.range, {
|
||||
endLineNumber: valueEndPosition.lineNumber,
|
||||
endColumn: valueEndPosition.column
|
||||
});
|
||||
@@ -357,11 +356,11 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string,
|
||||
const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1];
|
||||
if (setting) {
|
||||
const valueEndPosition = model.getPositionAt(offset + length);
|
||||
setting.valueRange = assign(setting.valueRange, {
|
||||
setting.valueRange = Object.assign(setting.valueRange, {
|
||||
endLineNumber: valueEndPosition.lineNumber,
|
||||
endColumn: valueEndPosition.column
|
||||
});
|
||||
setting.range = assign(setting.range, {
|
||||
setting.range = Object.assign(setting.range, {
|
||||
endLineNumber: valueEndPosition.lineNumber,
|
||||
endColumn: valueEndPosition.column
|
||||
});
|
||||
@@ -393,11 +392,11 @@ function parse(model: ITextModel, isSettingsProperty: (currentProperty: string,
|
||||
const setting = previousParents.length === settingsPropertyIndex + 1 ? settings[settings.length - 1] : overrideSetting!.overrides![overrideSetting!.overrides!.length - 1];
|
||||
if (setting) {
|
||||
const valueEndPosition = model.getPositionAt(offset + length);
|
||||
setting.valueRange = assign(setting.valueRange, {
|
||||
setting.valueRange = Object.assign(setting.valueRange, {
|
||||
endLineNumber: valueEndPosition.lineNumber,
|
||||
endColumn: valueEndPosition.column
|
||||
});
|
||||
setting.range = assign(setting.range, {
|
||||
setting.range = Object.assign(setting.range, {
|
||||
endLineNumber: valueEndPosition.lineNumber,
|
||||
endColumn: valueEndPosition.column
|
||||
});
|
||||
@@ -558,16 +557,16 @@ export class DefaultSettings extends Disposable {
|
||||
seenSettings = seenSettings ? seenSettings : {};
|
||||
let title = config.title;
|
||||
if (!title) {
|
||||
const configWithTitleAndSameId = find(configurations, c => (c.id === config.id) && c.title);
|
||||
const configWithTitleAndSameId = configurations.find(c => (c.id === config.id) && c.title);
|
||||
if (configWithTitleAndSameId) {
|
||||
title = configWithTitleAndSameId.title;
|
||||
}
|
||||
}
|
||||
if (title) {
|
||||
if (!settingsGroup) {
|
||||
settingsGroup = find(result, g => g.title === title);
|
||||
settingsGroup = result.find(g => g.title === title && g.extensionInfo?.id === config.extensionInfo?.id);
|
||||
if (!settingsGroup) {
|
||||
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: title || '', titleRange: nullRange, range: nullRange, contributedByExtension: !!config.extensionInfo };
|
||||
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: title || '', titleRange: nullRange, range: nullRange, extensionInfo: config.extensionInfo };
|
||||
result.push(settingsGroup);
|
||||
}
|
||||
} else {
|
||||
@@ -576,7 +575,7 @@ export class DefaultSettings extends Disposable {
|
||||
}
|
||||
if (config.properties) {
|
||||
if (!settingsGroup) {
|
||||
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: config.id || '', titleRange: nullRange, range: nullRange, contributedByExtension: !!config.extensionInfo };
|
||||
settingsGroup = { sections: [{ settings: [] }], id: config.id || '', title: config.id || '', titleRange: nullRange, range: nullRange, extensionInfo: config.extensionInfo };
|
||||
result.push(settingsGroup);
|
||||
}
|
||||
const configurationSettings: ISetting[] = [];
|
||||
|
||||
@@ -509,7 +509,9 @@ export class ProgressService extends Disposable implements IProgressService {
|
||||
'workbench.action.quit',
|
||||
'workbench.action.reloadWindow',
|
||||
'copy',
|
||||
'cut'
|
||||
'cut',
|
||||
'editor.action.clipboardCopyAction',
|
||||
'editor.action.clipboardCutAction'
|
||||
];
|
||||
|
||||
let dialog: Dialog;
|
||||
|
||||
@@ -48,15 +48,8 @@ export interface Tunnel {
|
||||
closeable?: boolean;
|
||||
}
|
||||
|
||||
function ToLocalHost(host: string): string {
|
||||
if (host === '127.0.0.1') {
|
||||
host = 'localhost';
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
export function MakeAddress(host: string, port: number): string {
|
||||
return ToLocalHost(host) + ':' + port;
|
||||
return host + ':' + port;
|
||||
}
|
||||
|
||||
export class TunnelModel extends Disposable {
|
||||
@@ -218,7 +211,7 @@ export class TunnelModel extends Disposable {
|
||||
const nullIndex = value.detail.indexOf('\0');
|
||||
const detail = value.detail.substr(0, nullIndex > 0 ? nullIndex : value.detail.length).trim();
|
||||
return {
|
||||
host: ToLocalHost(value.host),
|
||||
host: value.host,
|
||||
port: value.port,
|
||||
detail
|
||||
};
|
||||
|
||||
@@ -10,8 +10,6 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { RequestChannelClient } from 'vs/platform/request/common/requestIpc';
|
||||
import { IRemoteAgentService, IRemoteAgentConnection } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { RequestService } from 'vs/platform/request/browser/requestService';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
|
||||
export class BrowserRequestService extends RequestService {
|
||||
|
||||
@@ -44,5 +42,3 @@ export class BrowserRequestService extends RequestService {
|
||||
return connection.withChannel('request', channel => RequestChannelClient.request(channel, options, token));
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IRequestService, BrowserRequestService, true);
|
||||
|
||||
@@ -54,7 +54,7 @@ export class TextSearchManager {
|
||||
|
||||
const newResultSize = this.resultSize(result);
|
||||
this.resultCount += newResultSize;
|
||||
if (newResultSize > 0) {
|
||||
if (newResultSize > 0 || !extensionResultIsMatch(result)) {
|
||||
this.collector!.add(result, folderIdx);
|
||||
}
|
||||
}
|
||||
@@ -83,10 +83,15 @@ export class TextSearchManager {
|
||||
}
|
||||
|
||||
private resultSize(result: TextSearchResult): number {
|
||||
const match = <TextSearchMatch>result;
|
||||
return Array.isArray(match.ranges) ?
|
||||
match.ranges.length :
|
||||
1;
|
||||
if (extensionResultIsMatch(result)) {
|
||||
return Array.isArray(result.ranges) ?
|
||||
result.ranges.length :
|
||||
1;
|
||||
}
|
||||
else {
|
||||
// #104400 context lines shoudn't count towards result count
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private trimResultToSize(result: TextSearchMatch, size: number): TextSearchMatch {
|
||||
|
||||
@@ -462,15 +462,17 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
|
||||
}
|
||||
|
||||
suggestFilename(mode: string, untitledName: string) {
|
||||
// {{SQL CARBON EDIT}} - pass language not mode for getting the extension.
|
||||
const langName = this.modeService.getLanguageName(mode);
|
||||
const extension = langName ? this.modeService.getExtensions(langName)[0] : undefined;
|
||||
const languageName = this.modeService.getLanguageName(mode);
|
||||
if (!languageName) {
|
||||
return untitledName;
|
||||
}
|
||||
const extension = this.modeService.getExtensions(languageName)[0];
|
||||
if (extension) {
|
||||
if (!untitledName.endsWith(extension)) {
|
||||
return untitledName + extension;
|
||||
}
|
||||
}
|
||||
const filename = this.modeService.getFilenames(mode)[0];
|
||||
const filename = this.modeService.getFilenames(languageName)[0];
|
||||
return filename || untitledName;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ export class NativeTextFileService extends AbstractTextFileService {
|
||||
}
|
||||
|
||||
try {
|
||||
return super.write(resource, value, options);
|
||||
return await super.write(resource, value, options);
|
||||
} catch (error) {
|
||||
|
||||
// In case of permission denied, we need to check for readonly
|
||||
|
||||
170
src/vs/workbench/services/userData/browser/userDataInit.ts
Normal file
170
src/vs/workbench/services/userData/browser/userDataInit.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { AbstractInitializer } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { ExtensionsInitializer } from 'vs/platform/userDataSync/common/extensionsSync';
|
||||
import { GlobalStateInitializer } from 'vs/platform/userDataSync/common/globalStateSync';
|
||||
import { KeybindingsInitializer } from 'vs/platform/userDataSync/common/keybindingsSync';
|
||||
import { SettingsInitializer } from 'vs/platform/userDataSync/common/settingsSync';
|
||||
import { SnippetsInitializer } from 'vs/platform/userDataSync/common/snippetsSync';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { UserDataSyncStoreClient } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { CONFIGURATION_SYNC_STORE_KEY, IUserDataSyncStoreClient, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getCurrentAuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import { getSyncAreaLabel } from 'vs/workbench/services/userDataSync/common/userDataSync';
|
||||
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
|
||||
export const IUserDataInitializationService = createDecorator<IUserDataInitializationService>('IUserDataInitializationService');
|
||||
export interface IUserDataInitializationService {
|
||||
_serviceBrand: any;
|
||||
|
||||
initializeRequiredResources(): Promise<void>;
|
||||
initializeOtherResources(): Promise<void>;
|
||||
initializeExtensions(instantiationService: IInstantiationService): Promise<void>;
|
||||
}
|
||||
|
||||
export class UserDataInitializationService implements IUserDataInitializationService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly initialized: SyncResource[] = [];
|
||||
|
||||
constructor(
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IRequestService private readonly requestService: IRequestService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) { }
|
||||
|
||||
private _userDataSyncStoreClientPromise: Promise<IUserDataSyncStoreClient | undefined> | undefined;
|
||||
private createUserDataSyncStoreClient(): Promise<IUserDataSyncStoreClient | undefined> {
|
||||
if (!this._userDataSyncStoreClientPromise) {
|
||||
this._userDataSyncStoreClientPromise = (async (): Promise<IUserDataSyncStoreClient | undefined> => {
|
||||
if (!isWeb) {
|
||||
this.logService.trace(`Skipping initializing user data in desktop`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
if (!this.environmentService.options?.enableSyncByDefault) {
|
||||
this.logService.trace(`Skipping initializing user data as sync is not enabled by default`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
if (!this.storageService.isNew(StorageScope.GLOBAL)) {
|
||||
this.logService.trace(`Skipping initializing user data as application was opened before`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
if (!this.storageService.isNew(StorageScope.WORKSPACE)) {
|
||||
this.logService.trace(`Skipping initializing user data as workspace was opened before`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
const userDataSyncStore = this.productService[CONFIGURATION_SYNC_STORE_KEY];
|
||||
if (!userDataSyncStore) {
|
||||
this.logService.trace(`Skipping initializing user data as sync service is not provided`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
if (!this.environmentService.options?.credentialsProvider) {
|
||||
this.logService.trace(`Skipping initializing user data as credentials provider is not provided`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
let authenticationSession;
|
||||
try {
|
||||
authenticationSession = await getCurrentAuthenticationSessionInfo(this.environmentService, this.productService);
|
||||
} catch (error) {
|
||||
this.logService.error(error);
|
||||
}
|
||||
if (!authenticationSession) {
|
||||
this.logService.trace(`Skipping initializing user data as authentication session is not set`);
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
}
|
||||
|
||||
const userDataSyncStoreClient = new UserDataSyncStoreClient(URI.parse(userDataSyncStore.url), this.productService, this.requestService, this.logService, this.environmentService, this.fileService, this.storageService);
|
||||
userDataSyncStoreClient.setAuthToken(authenticationSession.accessToken, authenticationSession.providerId);
|
||||
return userDataSyncStoreClient;
|
||||
})();
|
||||
}
|
||||
|
||||
return this._userDataSyncStoreClientPromise;
|
||||
}
|
||||
|
||||
async initializeRequiredResources(): Promise<void> {
|
||||
return this.initialize([SyncResource.Settings, SyncResource.GlobalState]);
|
||||
}
|
||||
|
||||
async initializeOtherResources(): Promise<void> {
|
||||
return this.initialize([SyncResource.Keybindings, SyncResource.Snippets]);
|
||||
}
|
||||
|
||||
async initializeExtensions(instantiationService: IInstantiationService): Promise<void> {
|
||||
return this.initialize([SyncResource.Extensions], instantiationService);
|
||||
}
|
||||
|
||||
private async initialize(syncResources: SyncResource[], instantiationService?: IInstantiationService): Promise<void> {
|
||||
const userDataSyncStoreClient = await this.createUserDataSyncStoreClient();
|
||||
if (!userDataSyncStoreClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
await Promise.all(syncResources.map(async syncResource => {
|
||||
try {
|
||||
if (this.initialized.includes(syncResource)) {
|
||||
this.logService.info(`${getSyncAreaLabel(syncResource)} initialized already.`);
|
||||
return;
|
||||
}
|
||||
this.initialized.push(syncResource);
|
||||
this.logService.trace(`Initializing ${getSyncAreaLabel(syncResource)}`);
|
||||
const initializer = this.createSyncResourceInitializer(syncResource, instantiationService);
|
||||
const userData = await userDataSyncStoreClient.read(syncResource, null);
|
||||
await initializer.initialize(userData);
|
||||
this.logService.info(`Initialized ${getSyncAreaLabel(syncResource)}`);
|
||||
} catch (error) {
|
||||
this.logService.info(`Error while initializing ${getSyncAreaLabel(syncResource)}`);
|
||||
this.logService.error(error);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private createSyncResourceInitializer(syncResource: SyncResource, instantiationService?: IInstantiationService): AbstractInitializer {
|
||||
switch (syncResource) {
|
||||
case SyncResource.Settings: return new SettingsInitializer(this.fileService, this.environmentService, this.logService);
|
||||
case SyncResource.Keybindings: return new KeybindingsInitializer(this.fileService, this.environmentService, this.logService);
|
||||
case SyncResource.Snippets: return new SnippetsInitializer(this.fileService, this.environmentService, this.logService);
|
||||
case SyncResource.GlobalState: return new GlobalStateInitializer(this.storageService, this.fileService, this.environmentService, this.logService);
|
||||
case SyncResource.Extensions:
|
||||
if (!instantiationService) {
|
||||
throw new Error('Instantiation Service is required to initialize extension');
|
||||
}
|
||||
return instantiationService.createInstance(ExtensionsInitializer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InitializeOtherResourcesContribution implements IWorkbenchContribution {
|
||||
constructor(@IUserDataInitializationService userDataInitializeService: IUserDataInitializationService) {
|
||||
userDataInitializeService.initializeOtherResources();
|
||||
}
|
||||
}
|
||||
|
||||
if (isWeb) {
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench);
|
||||
workbenchRegistry.registerWorkbenchContribution(InitializeOtherResourcesContribution, LifecyclePhase.Restored);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import { AuthenticationSession, AuthenticationSessionsChangeEvent } from 'vs/edi
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { flatten, equals } from 'vs/base/common/arrays';
|
||||
import { getAuthenticationProviderActivationEvent, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import { getAuthenticationProviderActivationEvent, getCurrentAuthenticationSessionInfo, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount';
|
||||
import { IQuickInputService, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IStorageService, IWorkspaceStorageChangeEvent, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
@@ -153,8 +153,9 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
}
|
||||
|
||||
private async initialize(): Promise<void> {
|
||||
if (this.currentSessionId === undefined && this.useWorkbenchSessionId && this.environmentService.options?.authenticationSessionId) {
|
||||
this.currentSessionId = this.environmentService.options.authenticationSessionId;
|
||||
const authenticationSession = this.environmentService.options?.credentialsProvider ? await getCurrentAuthenticationSessionInfo(this.environmentService, this.productService) : undefined;
|
||||
if (this.currentSessionId === undefined && this.useWorkbenchSessionId && (authenticationSession?.id || this.environmentService.options?.authenticationSessionId)) {
|
||||
this.currentSessionId = authenticationSession?.id || this.environmentService.options?.authenticationSessionId;
|
||||
this.useWorkbenchSessionId = false;
|
||||
}
|
||||
|
||||
@@ -331,9 +332,14 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
|
||||
}
|
||||
});
|
||||
if (manualSyncTask.status === SyncStatus.HasConflicts) {
|
||||
await this.dialogService.show(Severity.Warning, localize('conflicts detected', "Conflicts Detected"), [], {
|
||||
detail: localize('resolve', "Unable to merge due to conflicts. Please merge manually to continue...")
|
||||
});
|
||||
await this.dialogService.show(
|
||||
Severity.Warning,
|
||||
localize('conflicts detected', "Conflicts Detected"),
|
||||
[localize('merge Manually', "Merge Manually...")],
|
||||
{
|
||||
detail: localize('resolve', "Unable to merge due to conflicts. Please merge manually to continue..."),
|
||||
}
|
||||
);
|
||||
await manualSyncTask.discardConflicts();
|
||||
action = 'manual';
|
||||
}
|
||||
|
||||
@@ -692,7 +692,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
|
||||
});
|
||||
});
|
||||
|
||||
this.getViewContainerModel(container).add(views.map(view => { return { viewDescriptor: view, collapsed: expandViews ? false : undefined }; }));
|
||||
this.getViewContainerModel(container).add(views.map(view => { return { viewDescriptor: view, collapsed: expandViews ? false : undefined, visible: expandViews }; }));
|
||||
}
|
||||
|
||||
private removeViews(container: ViewContainer, views: IViewDescriptor[]): void {
|
||||
|
||||
@@ -478,16 +478,16 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode
|
||||
if (state) {
|
||||
// set defaults if not set
|
||||
if (viewDescriptor.workspace) {
|
||||
state.visibleWorkspace = isUndefinedOrNull(state.visibleWorkspace) ? !viewDescriptor.hideByDefault : state.visibleWorkspace;
|
||||
state.visibleWorkspace = isUndefinedOrNull(addedViewDescriptorState.visible) ? (isUndefinedOrNull(state.visibleWorkspace) ? !viewDescriptor.hideByDefault : state.visibleWorkspace) : addedViewDescriptorState.visible;
|
||||
} else {
|
||||
state.visibleGlobal = isUndefinedOrNull(state.visibleGlobal) ? !viewDescriptor.hideByDefault : state.visibleGlobal;
|
||||
state.visibleGlobal = isUndefinedOrNull(addedViewDescriptorState.visible) ? (isUndefinedOrNull(state.visibleGlobal) ? !viewDescriptor.hideByDefault : state.visibleGlobal) : addedViewDescriptorState.visible;
|
||||
}
|
||||
state.collapsed = isUndefinedOrNull(addedViewDescriptorState.collapsed) ? (isUndefinedOrNull(state.collapsed) ? !!viewDescriptor.collapsed : state.collapsed) : addedViewDescriptorState.collapsed;
|
||||
} else {
|
||||
state = {
|
||||
active: false,
|
||||
visibleGlobal: !viewDescriptor.hideByDefault,
|
||||
visibleWorkspace: !viewDescriptor.hideByDefault,
|
||||
visibleGlobal: isUndefinedOrNull(addedViewDescriptorState.visible) ? !viewDescriptor.hideByDefault : addedViewDescriptorState.visible,
|
||||
visibleWorkspace: isUndefinedOrNull(addedViewDescriptorState.visible) ? !viewDescriptor.hideByDefault : addedViewDescriptorState.visible,
|
||||
collapsed: isUndefinedOrNull(addedViewDescriptorState.collapsed) ? !!viewDescriptor.collapsed : addedViewDescriptorState.collapsed,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user