mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-25 09:06:21 +01:00
very happy to delete settings.ts on main side
This commit is contained in:
@@ -16,7 +16,6 @@ import { IProcessEnvironment, IEnvService, EnvService } from 'vs/code/electron-m
|
||||
import { IWindowsService, WindowsManager } from 'vs/code/electron-main/windows';
|
||||
import { ILifecycleService, LifecycleService } from 'vs/code/electron-main/lifecycle';
|
||||
import { VSCodeMenu } from 'vs/code/electron-main/menus';
|
||||
import { ISettingsService, SettingsManager } from 'vs/code/electron-main/settings';
|
||||
import { IUpdateService, UpdateManager } from 'vs/code/electron-main/update-manager';
|
||||
import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/common/ipc.electron';
|
||||
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
@@ -70,7 +69,7 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: IProce
|
||||
const windowsService = accessor.get(IWindowsService);
|
||||
const lifecycleService = accessor.get(ILifecycleService);
|
||||
const updateService = accessor.get(IUpdateService);
|
||||
const settingsService = accessor.get(ISettingsService);
|
||||
const configurationService = <ConfigurationService>accessor.get(IConfigurationService);
|
||||
|
||||
// We handle uncaught exceptions here to prevent electron from opening a dialog to the user
|
||||
process.on('uncaughtException', (err: any) => {
|
||||
@@ -146,6 +145,8 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: IProce
|
||||
if (windowsMutex) {
|
||||
windowsMutex.release();
|
||||
}
|
||||
|
||||
configurationService.dispose();
|
||||
}
|
||||
|
||||
// Dispose on app quit
|
||||
@@ -166,8 +167,8 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: IProce
|
||||
// Lifecycle
|
||||
lifecycleService.ready();
|
||||
|
||||
// Load settings
|
||||
settingsService.loadSync();
|
||||
// Load settings (TODO@Ben remove)
|
||||
global.globalSettingsValue = JSON.stringify(configurationService.getConfiguration());
|
||||
|
||||
// Propagate to clients
|
||||
windowsService.ready(userEnv);
|
||||
@@ -396,7 +397,6 @@ function start(): void {
|
||||
services.set(IConfigurationService, new SyncDescriptor(ConfigurationService));
|
||||
services.set(IRequestService, new SyncDescriptor(RequestService));
|
||||
services.set(IUpdateService, new SyncDescriptor(UpdateManager));
|
||||
services.set(ISettingsService, new SyncDescriptor(SettingsManager));
|
||||
|
||||
const instantiationService = new InstantiationService(services);
|
||||
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { app } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEnvService } from 'vs/code/electron-main/env';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
|
||||
export const ISettingsService = createDecorator<ISettingsService>('settingsService');
|
||||
|
||||
export interface ISettings {
|
||||
settings: any;
|
||||
settingsParseErrors?: string[];
|
||||
}
|
||||
|
||||
export interface ISettingsService {
|
||||
_serviceBrand: any;
|
||||
globalSettings: ISettings;
|
||||
loadSync(): boolean;
|
||||
getValue<T>(key: string, fallback?: T): T;
|
||||
onChange: Event<ISettings>;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO@Joao TODO@Ben - this needs to die
|
||||
*
|
||||
* We need to have each participant (renderer, main, cli, shared) be able
|
||||
* to listen on changes to each of these files, independently.
|
||||
*/
|
||||
|
||||
export class SettingsManager implements ISettingsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private static CHANGE_BUFFER_DELAY = 300;
|
||||
|
||||
globalSettings: ISettings;
|
||||
|
||||
private timeoutHandle: number;
|
||||
private watcher: fs.FSWatcher;
|
||||
private appSettingsPath: string;
|
||||
|
||||
private _onChange: Emitter<ISettings>;
|
||||
|
||||
constructor(@IEnvService envService: IEnvService) {
|
||||
this.appSettingsPath = envService.appSettingsPath;
|
||||
this._onChange = new Emitter<ISettings>();
|
||||
|
||||
this.registerWatchers();
|
||||
app.on('will-quit', () => this.dispose());
|
||||
}
|
||||
|
||||
loadSync(): boolean {
|
||||
let settingsChanged = false;
|
||||
|
||||
const loadedSettings = this.doLoadSync();
|
||||
if (!objects.equals(loadedSettings, this.globalSettings)) {
|
||||
|
||||
// Keep in class
|
||||
this.globalSettings = loadedSettings;
|
||||
settingsChanged = true; // changed value
|
||||
}
|
||||
|
||||
// Store into global so that any renderer can access the value with remote.getGlobal()
|
||||
if (settingsChanged) {
|
||||
global.globalSettingsValue = JSON.stringify(this.globalSettings);
|
||||
}
|
||||
|
||||
return settingsChanged;
|
||||
}
|
||||
|
||||
get onChange(): Event<ISettings> {
|
||||
return this._onChange.event;
|
||||
}
|
||||
|
||||
getValue(key: string, fallback?: any): any {
|
||||
return this.doGetValue(key, fallback);
|
||||
}
|
||||
|
||||
private doGetValue(key: string, fallback?: any): any {
|
||||
if (!key) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
let value = this.globalSettings.settings;
|
||||
|
||||
const parts = key.split('\.');
|
||||
while (parts.length && value) {
|
||||
const part = parts.shift();
|
||||
value = value[part];
|
||||
}
|
||||
|
||||
return typeof value !== 'undefined' ? value : fallback;
|
||||
}
|
||||
|
||||
private registerWatchers(): void {
|
||||
const self = this;
|
||||
function attachSettingsChangeWatcher(watchPath: string): void {
|
||||
self.watcher = fs.watch(watchPath);
|
||||
self.watcher.on('change', () => self.onSettingsFileChange());
|
||||
}
|
||||
|
||||
// Attach a watcher to the settings directory
|
||||
attachSettingsChangeWatcher(path.dirname(this.appSettingsPath));
|
||||
|
||||
// Follow symlinks and attach watchers if they resolve
|
||||
fs.lstat(this.appSettingsPath, (err, stats) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.isSymbolicLink() && !stats.isDirectory()) {
|
||||
fs.readlink(this.appSettingsPath, (err, realPath) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachSettingsChangeWatcher(realPath);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private onSettingsFileChange(): void {
|
||||
|
||||
// we can get multiple change events for one change, so we buffer through a timeout
|
||||
if (this.timeoutHandle) {
|
||||
global.clearTimeout(this.timeoutHandle);
|
||||
this.timeoutHandle = null;
|
||||
}
|
||||
|
||||
this.timeoutHandle = global.setTimeout(() => {
|
||||
|
||||
// Reload
|
||||
const didChange = this.loadSync();
|
||||
|
||||
// Emit event
|
||||
if (didChange) {
|
||||
this._onChange.fire(this.globalSettings);
|
||||
}
|
||||
|
||||
}, SettingsManager.CHANGE_BUFFER_DELAY);
|
||||
}
|
||||
|
||||
private doLoadSync(): ISettings {
|
||||
const settings = this.doLoadSettingsSync();
|
||||
|
||||
return {
|
||||
settings: settings.contents,
|
||||
settingsParseErrors: settings.parseErrors
|
||||
};
|
||||
}
|
||||
|
||||
private doLoadSettingsSync(): { contents: any; parseErrors?: string[]; } {
|
||||
const root = Object.create(null);
|
||||
let content = '{}';
|
||||
try {
|
||||
content = fs.readFileSync(this.appSettingsPath).toString();
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
let contents = Object.create(null);
|
||||
try {
|
||||
contents = json.parse(content);
|
||||
} catch (error) {
|
||||
// parse problem
|
||||
return {
|
||||
contents: Object.create(null),
|
||||
parseErrors: [this.appSettingsPath]
|
||||
};
|
||||
}
|
||||
|
||||
for (let key in contents) {
|
||||
this.setNode(root, key, contents[key]);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: root
|
||||
};
|
||||
}
|
||||
|
||||
private setNode(root: any, key: string, value: any): any {
|
||||
const segments = key.split('.');
|
||||
const last = segments.pop();
|
||||
|
||||
let curr = root;
|
||||
segments.forEach((s) => {
|
||||
let obj = curr[s];
|
||||
switch (typeof obj) {
|
||||
case 'undefined':
|
||||
obj = curr[s] = {};
|
||||
break;
|
||||
case 'object':
|
||||
break;
|
||||
default:
|
||||
console.log('Conflicting user settings: ' + key + ' at ' + s + ' with ' + JSON.stringify(obj));
|
||||
}
|
||||
curr = obj;
|
||||
});
|
||||
curr[last] = value;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.watcher) {
|
||||
this.watcher.close();
|
||||
this.watcher = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import { shell, screen, BrowserWindow } from 'electron';
|
||||
import { TPromise, TValueCallback } from 'vs/base/common/winjs.base';
|
||||
import { ICommandLineArguments, IEnvService, IProcessEnvironment } from 'vs/code/electron-main/env';
|
||||
import { ILogService } from 'vs/code/electron-main/log';
|
||||
import { ISettingsService } from 'vs/code/electron-main/settings';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { parseArgs } from 'vs/code/node/argv';
|
||||
|
||||
export interface IWindowState {
|
||||
@@ -106,6 +106,13 @@ export interface IWindowConfiguration extends ICommandLineArguments {
|
||||
extensionsToInstall: string[];
|
||||
}
|
||||
|
||||
export interface IWindowSettings {
|
||||
openFilesInNewWindow: boolean;
|
||||
reopenFolders: 'all' | 'one' | 'none';
|
||||
restoreFullscreen: boolean;
|
||||
zoomLevel: number;
|
||||
}
|
||||
|
||||
export class VSCodeWindow {
|
||||
|
||||
public static menuBarHiddenKey = 'menuBarHidden';
|
||||
@@ -133,7 +140,7 @@ export class VSCodeWindow {
|
||||
config: IWindowCreationOptions,
|
||||
@ILogService private logService: ILogService,
|
||||
@IEnvService private envService: IEnvService,
|
||||
@ISettingsService private settingsService: ISettingsService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IStorageService private storageService: IStorageService
|
||||
) {
|
||||
this.options = config;
|
||||
@@ -395,7 +402,8 @@ export class VSCodeWindow {
|
||||
let url = require.toUrl('vs/workbench/electron-browser/bootstrap/index.html');
|
||||
|
||||
// Set zoomlevel
|
||||
const zoomLevel = this.settingsService.getValue('window.zoomLevel');
|
||||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
const zoomLevel = windowConfig && windowConfig.zoomLevel;
|
||||
if (typeof zoomLevel === 'number') {
|
||||
windowConfiguration.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ import * as arrays from 'vs/base/common/arrays';
|
||||
import { assign, mixin } from 'vs/base/common/objects';
|
||||
import { EventEmitter } from 'events';
|
||||
import { IStorageService } from 'vs/code/electron-main/storage';
|
||||
import { IPath, VSCodeWindow, ReadyState, IWindowConfiguration, IWindowState as ISingleWindowState, defaultWindowState } from 'vs/code/electron-main/window';
|
||||
import { IPath, VSCodeWindow, ReadyState, IWindowConfiguration, IWindowState as ISingleWindowState, defaultWindowState, IWindowSettings } from 'vs/code/electron-main/window';
|
||||
import { ipcMain as ipc, app, screen, crashReporter, BrowserWindow, dialog } from 'electron';
|
||||
import { ICommandLineArguments, IProcessEnvironment, IEnvService, IParsedPath, parseLineAndColumnAware } from 'vs/code/electron-main/env';
|
||||
import { ILifecycleService } from 'vs/code/electron-main/lifecycle';
|
||||
import { ISettingsService } from 'vs/code/electron-main/settings';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IUpdateService, IUpdate } from 'vs/code/electron-main/update-manager';
|
||||
import { ILogService } from 'vs/code/electron-main/log';
|
||||
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -132,8 +132,8 @@ export class WindowsManager implements IWindowsService {
|
||||
@IEnvService private envService: IEnvService,
|
||||
@ILifecycleService private lifecycleService: ILifecycleService,
|
||||
@IUpdateService private updateService: IUpdateService,
|
||||
@ISettingsService private settingsService: ISettingsService
|
||||
) { }
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) { }
|
||||
|
||||
onOpen(clb: (path: IPath) => void): () => void {
|
||||
this.eventEmitter.addListener(EventTypes.OPEN, clb);
|
||||
@@ -193,8 +193,9 @@ export class WindowsManager implements IWindowsService {
|
||||
}, 100);
|
||||
});
|
||||
|
||||
this.settingsService.onChange((newSettings) => {
|
||||
this.sendToAll('vscode:optionsChange', JSON.stringify({ globalSettings: newSettings }));
|
||||
this.configurationService.onDidUpdateConfiguration(event => {
|
||||
global.globalSettingsValue = JSON.stringify(event.config); // Load settings (TODO@Ben remove)
|
||||
this.sendToAll('vscode:optionsChange', JSON.stringify(event.config));
|
||||
}, this);
|
||||
|
||||
ipc.on('vscode:startCrashReporter', (event: any, config: any) => {
|
||||
@@ -516,7 +517,7 @@ export class WindowsManager implements IWindowsService {
|
||||
|
||||
// Warn if the requested path to open does not exist
|
||||
if (!iPath) {
|
||||
let options:Electron.ShowMessageBoxOptions = {
|
||||
let options: Electron.ShowMessageBoxOptions = {
|
||||
title: this.envService.product.nameLong,
|
||||
type: 'info',
|
||||
buttons: [nls.localize('ok', "OK")],
|
||||
@@ -589,7 +590,10 @@ export class WindowsManager implements IWindowsService {
|
||||
} else {
|
||||
openFilesInNewWindow = openConfig.preferNewWindow;
|
||||
if (openFilesInNewWindow && !openConfig.cli.extensionDevelopmentPath) { // can be overriden via settings (not for PDE though!)
|
||||
openFilesInNewWindow = this.settingsService.getValue('window.openFilesInNewWindow', openFilesInNewWindow);
|
||||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
if (windowConfig && !windowConfig.openFilesInNewWindow) {
|
||||
openFilesInNewWindow = false; // do not open in new window if user configured this explicitly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -831,7 +835,8 @@ export class WindowsManager implements IWindowsService {
|
||||
if (this.lifecycleService.wasUpdated) {
|
||||
reopenFolders = ReopenFoldersSetting.ALL; // always reopen all folders when an update was applied
|
||||
} else {
|
||||
reopenFolders = this.settingsService.getValue('window.reopenFolders', ReopenFoldersSetting.ONE);
|
||||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
reopenFolders = (windowConfig && windowConfig.reopenFolders) || ReopenFoldersSetting.ONE;
|
||||
}
|
||||
|
||||
let lastActiveFolder = this.windowsState.lastActiveWindow && this.windowsState.lastActiveWindow.workspacePath;
|
||||
@@ -877,10 +882,12 @@ export class WindowsManager implements IWindowsService {
|
||||
|
||||
// New window
|
||||
if (!vscodeWindow) {
|
||||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
|
||||
vscodeWindow = this.instantiationService.createInstance(VSCodeWindow, {
|
||||
state: this.getNewWindowState(configuration),
|
||||
extensionDevelopmentPath: configuration.extensionDevelopmentPath,
|
||||
allowFullscreen: this.lifecycleService.wasUpdated || this.settingsService.getValue('window.restoreFullscreen', false)
|
||||
allowFullscreen: this.lifecycleService.wasUpdated || (windowConfig && windowConfig.restoreFullscreen)
|
||||
});
|
||||
|
||||
WindowsManager.WINDOWS.push(vscodeWindow);
|
||||
@@ -1000,7 +1007,7 @@ export class WindowsManager implements IWindowsService {
|
||||
}
|
||||
|
||||
public openFileFolderPicker(forceNewWindow?: boolean): void {
|
||||
this.doPickAndOpen({ pickFolders: true, pickFiles: true , forceNewWindow});
|
||||
this.doPickAndOpen({ pickFolders: true, pickFiles: true, forceNewWindow });
|
||||
}
|
||||
|
||||
public openFilePicker(forceNewWindow?: boolean, path?: string): void {
|
||||
@@ -1020,7 +1027,7 @@ export class WindowsManager implements IWindowsService {
|
||||
}
|
||||
|
||||
private getFileOrFolderPaths(options: INativeOpenDialogOptions, clb: (paths: string[]) => void): void {
|
||||
let workingDir = options.path || this.storageService.getItem<string>(WindowsManager.workingDirPickerStorageKey);
|
||||
let workingDir = options.path || this.storageService.getItem<string>(WindowsManager.workingDirPickerStorageKey);
|
||||
let focussedWindow = this.getFocusedWindow();
|
||||
|
||||
let pickerProperties: ('openFile' | 'openDirectory' | 'multiSelections' | 'createDirectory')[];
|
||||
|
||||
Reference in New Issue
Block a user