Skip to content

Commit

Permalink
debt - introduce electron service and adopt for showMessageBox
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero committed Sep 17, 2019
1 parent 4aa94e2 commit 2105bce
Show file tree
Hide file tree
Showing 20 changed files with 232 additions and 125 deletions.
9 changes: 7 additions & 2 deletions src/vs/code/electron-main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ import { FileService } from 'vs/platform/files/common/fileService';
import { IFileService } from 'vs/platform/files/common/files';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { ElectronMainService, ElectronChannel } from 'vs/platform/electron/electron-main/electronMainService';

export class CodeApplication extends Disposable {

Expand Down Expand Up @@ -423,7 +425,6 @@ export class CodeApplication extends Disposable {
private async createServices(machineId: string, trueMachineId: string | undefined, sharedProcess: SharedProcess, sharedProcessClient: Promise<Client<string>>): Promise<IInstantiationService> {
const services = new ServiceCollection();

// Files
const fileService = this._register(new FileService(this.logService));
services.set(IFileService, fileService);

Expand Down Expand Up @@ -456,6 +457,7 @@ export class CodeApplication extends Disposable {
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService, [diagnosticsChannel]));

services.set(IIssueService, new SyncDescriptor(IssueService, [machineId, this.userEnv]));
services.set(IElectronService, new SyncDescriptor(ElectronMainService));
services.set(IMenubarService, new SyncDescriptor(MenubarService));

const storageMainService = new StorageMainService(this.logService, this.environmentService);
Expand Down Expand Up @@ -541,6 +543,10 @@ export class CodeApplication extends Disposable {
const issueChannel = new IssueChannel(issueService);
electronIpcServer.registerChannel('issue', issueChannel);

const electronService = accessor.get(IElectronService);
const electronChannel = new ElectronChannel(electronService);
electronIpcServer.registerChannel('electron', electronChannel);

const workspacesService = accessor.get(IWorkspacesMainService);
const workspacesChannel = new WorkspacesChannel(workspacesService);
electronIpcServer.registerChannel('workspaces', workspacesChannel);
Expand All @@ -562,7 +568,6 @@ export class CodeApplication extends Disposable {
const storageChannel = this._register(new GlobalStorageDatabaseChannel(this.logService, storageMainService));
electronIpcServer.registerChannel('storage', storageChannel);

// Log level management
const logLevelChannel = new LogLevelSetterChannel(accessor.get(ILogService));
electronIpcServer.registerChannel('loglevel', logLevelChannel);
sharedProcessClient.then(client => client.registerChannel('loglevel', logLevelChannel));
Expand Down
4 changes: 4 additions & 0 deletions src/vs/editor/standalone/browser/simpleServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ export class SimpleDialogService implements IDialogService {
public show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise<IShowResult> {
return Promise.resolve({ choice: 0 });
}

public about(): Promise<void> {
return Promise.resolve(undefined);
}
}

export class SimpleNotificationService implements INotificationService {
Expand Down
6 changes: 5 additions & 1 deletion src/vs/platform/dialogs/common/dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ export interface IDialogService {
* option then promise with index `0` is returned.
*/
show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise<IShowResult>;

/**
* Present the about dialog to the user.
*/
about(): Promise<void>;
}

export const IFileDialogService = createDecorator<IFileDialogService>('fileDialogService');
Expand Down Expand Up @@ -235,7 +240,6 @@ export interface IFileDialogService {
* Shows a open file dialog and returns the chosen file URI.
*/
showOpenDialog(options: IOpenDialogOptions): Promise<URI[] | undefined>;

}

const MAX_CONFIRM_FILES = 10;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IDialogService, IConfirmation, IConfirmationResult, IShowResult } from 'vs/platform/dialogs/common/dialogs';
import Severity from 'vs/base/common/severity';
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { Event } from 'vs/base/common/event';

export class DialogChannel implements IServerChannel {
Expand All @@ -20,22 +19,8 @@ export class DialogChannel implements IServerChannel {
switch (command) {
case 'show': return this.dialogService.show(args![0], args![1], args![2]);
case 'confirm': return this.dialogService.confirm(args![0]);
case 'about': return this.dialogService.about();
}
return Promise.reject(new Error('invalid command'));
}
}

export class DialogChannelClient implements IDialogService {

_serviceBrand: undefined;

constructor(private channel: IChannel) { }

show(severity: Severity, message: string, options: string[]): Promise<IShowResult> {
return this.channel.call('show', [severity, message, options]);
}

confirm(confirmation: IConfirmation): Promise<IConfirmationResult> {
return this.channel.call('confirm', [confirmation]);
}
}
28 changes: 28 additions & 0 deletions src/vs/platform/electron/electron-browser/electronService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';

export class ElectronService {

_serviceBrand: undefined;

constructor(@IMainProcessService mainProcessService: IMainProcessService) {
const channel = mainProcessService.getChannel('electron');

// Proxy: forward any property access to the channel
return new Proxy({}, {
get(_target, propKey, _receiver) {
if (typeof propKey === 'string') {
return function (...args: any[]) {
return channel.call(propKey, ...args);
};
}

throw new Error(`Not Implemented in ElectronService: ${String(propKey)}`);
}
}) as ElectronService;
}
}
59 changes: 59 additions & 0 deletions src/vs/platform/electron/electron-main/electronMainService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IElectronService } from 'vs/platform/electron/node/electron';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { MessageBoxOptions, MessageBoxReturnValue } from 'electron';
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';

export class ElectronMainService implements IElectronService {

_serviceBrand: undefined;

constructor(
@IWindowsMainService private readonly windowsMainService: IWindowsMainService
) {
}

private get window(): ICodeWindow | undefined {
return this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow();
}

async showMessageBox(options: MessageBoxOptions): Promise<MessageBoxReturnValue> {
const result = await this.windowsMainService.showMessageBox(options, this.window);

return {
response: result.button,
checkboxChecked: !!result.checkboxChecked
};
}
}

export class ElectronChannel implements IServerChannel {

private service: { [key: string]: unknown };

constructor(service: IElectronService) {
this.service = service as unknown as { [key: string]: unknown };
}

listen<T>(_: unknown, event: string): Event<T> {
throw new Error(`Event not found: ${event}`);
}

call(_: unknown, command: string, arg?: any): Promise<any> {
const target = this.service[command];
if (typeof target === 'function') {
if (Array.isArray(arg)) {
return target.apply(this.service, arg);
}

return target.call(this.service, arg);
}

throw new Error(`Call Not Found in ElectronService: ${command}`);
}
}
17 changes: 17 additions & 0 deletions src/vs/platform/electron/node/electron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { MessageBoxOptions, MessageBoxReturnValue } from 'electron';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';

export const IElectronService = createDecorator<IElectronService>('electronService');

export interface IElectronService {

_serviceBrand: undefined;

// Dialogs
showMessageBox(options: MessageBoxOptions): Promise<MessageBoxReturnValue>;
}
1 change: 0 additions & 1 deletion src/vs/platform/windows/common/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ export interface IWindowsService {
// TODO: this is a bit backwards
startCrashReporter(config: CrashReporterStartOptions): Promise<void>;

openAboutDialog(): Promise<void>;
resolveProxy(windowId: number, url: string): Promise<string | undefined>;
}

Expand Down
1 change: 0 additions & 1 deletion src/vs/platform/windows/common/windowsIpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ export class WindowsChannel implements IServerChannel {
case 'getActiveWindowId': return this.service.getActiveWindowId();
case 'openExternal': return this.service.openExternal(arg);
case 'startCrashReporter': return this.service.startCrashReporter(arg);
case 'openAboutDialog': return this.service.openAboutDialog();
case 'resolveProxy': return this.service.resolveProxy(arg[0], arg[1]);
}

Expand Down
4 changes: 0 additions & 4 deletions src/vs/platform/windows/electron-browser/windowsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,6 @@ export class WindowsService implements IWindowsService {
return this.channel.call('updateTouchBar', [windowId, items]);
}

openAboutDialog(): Promise<void> {
return this.channel.call('openAboutDialog');
}

resolveProxy(windowId: number, url: string): Promise<string | undefined> {
return Promise.resolve(this.channel.call('resolveProxy', [windowId, url]));
}
Expand Down
54 changes: 2 additions & 52 deletions src/vs/platform/windows/electron-main/windowsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as nls from 'vs/nls';
import * as os from 'os';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import product from 'vs/platform/product/common/product';
import { IWindowsService, OpenContext, INativeOpenDialogOptions, IEnterWorkspaceResult, IMessageBoxResult, IDevToolsOptions, INewWindowOptions, IOpenSettings, IURIToOpen } from 'vs/platform/windows/common/windows';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { shell, crashReporter, app, Menu, clipboard } from 'electron';
import { shell, crashReporter, app, Menu } from 'electron';
import { Event } from 'vs/base/common/event';
import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
Expand All @@ -20,8 +17,7 @@ import { IHistoryMainService, IRecentlyOpened, IRecent } from 'vs/platform/histo
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { Schemas } from 'vs/base/common/network';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { isMacintosh, isLinux, IProcessEnvironment } from 'vs/base/common/platform';
import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';

export class WindowsService extends Disposable implements IWindowsService, IURLHandler {
Expand Down Expand Up @@ -407,52 +403,6 @@ export class WindowsService extends Disposable implements IWindowsService, IURLH

}

async openAboutDialog(): Promise<void> {
this.logService.trace('windowsService#openAboutDialog');

let version = app.getVersion();
if (product.target) {
version = `${version} (${product.target} setup)`;
}

const isSnap = process.platform === 'linux' && process.env.SNAP && process.env.SNAP_REVISION;
const detail = nls.localize('aboutDetail',
"Version: {0}\nCommit: {1}\nDate: {2}\nElectron: {3}\nChrome: {4}\nNode.js: {5}\nV8: {6}\nOS: {7}",
version,
product.commit || 'Unknown',
product.date || 'Unknown',
process.versions['electron'],
process.versions['chrome'],
process.versions['node'],
process.versions['v8'],
`${os.type()} ${os.arch()} ${os.release()}${isSnap ? ' snap' : ''}`
);

const ok = nls.localize('okButton', "OK");
const copy = mnemonicButtonLabel(nls.localize({ key: 'copy', comment: ['&& denotes a mnemonic'] }, "&&Copy"));
let buttons: string[];
if (isLinux) {
buttons = [copy, ok];
} else {
buttons = [ok, copy];
}

const result = await this.windowsMainService.showMessageBox({
title: product.nameLong,
type: 'info',
message: product.nameLong,
detail: `\n${detail}`,
buttons,
noLink: true,
defaultId: buttons.indexOf(ok),
cancelId: buttons.indexOf(ok)
}, this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow());

if (buttons[result.button] === copy) {
clipboard.writeText(detail);
}
}

async handleURL(uri: URI): Promise<boolean> {

// Catch file URLs
Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/browser/actions/windowActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import 'vs/css!./media/actions';

import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { IWindowService, IURIToOpen, IWindowsService } from 'vs/platform/windows/common/windows';
import { IWindowService, IURIToOpen } from 'vs/platform/windows/common/windows';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
Expand Down Expand Up @@ -234,13 +235,13 @@ class ShowAboutDialogAction extends Action {
constructor(
id: string,
label: string,
@IWindowsService private readonly windowsService: IWindowsService
@IDialogService private readonly dialogService: IDialogService
) {
super(id, label);
}

run(): Promise<void> {
return this.windowsService.openAboutDialog();
return this.dialogService.about();
}
}

Expand Down
28 changes: 0 additions & 28 deletions src/vs/workbench/browser/web.simpleservices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { toStoreData, restoreRecentlyOpened } from 'vs/platform/history/common/historyStorage';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IProductService } from 'vs/platform/product/common/productService';
import Severity from 'vs/base/common/severity';
import { localize } from 'vs/nls';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';

//#region Window

Expand Down Expand Up @@ -332,13 +327,6 @@ export class SimpleWindowsService implements IWindowsService {
readonly onWindowUnmaximize: Event<number> = Event.None;
readonly onRecentlyOpenedChange: Event<void> = Event.None;

constructor(
@IDialogService private readonly dialogService: IDialogService,
@IProductService private readonly productService: IProductService,
@IClipboardService private readonly clipboardService: IClipboardService
) {
}

isFocused(_windowId: number): Promise<boolean> {
return Promise.resolve(true);
}
Expand Down Expand Up @@ -585,22 +573,6 @@ export class SimpleWindowsService implements IWindowsService {
throw new Error('not implemented');
}

async openAboutDialog(): Promise<void> {
const detail = localize('aboutDetail',
"Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
this.productService.version || 'Unknown',
this.productService.commit || 'Unknown',
this.productService.date || 'Unknown',
navigator.userAgent
);

const { choice } = await this.dialogService.show(Severity.Info, this.productService.nameLong, [localize('copy', "Copy"), localize('ok', "OK")], { detail });

if (choice === 0) {
this.clipboardService.writeText(detail);
}
}

resolveProxy(windowId: number, url: string): Promise<string | undefined> {
return Promise.resolve(undefined);
}
Expand Down
Loading

0 comments on commit 2105bce

Please sign in to comment.