提交 4d8fe6df 编写于 作者: C Christof Marti

Add telemetry on outcome of open folder action (fixes #21238)

上级 03417bc9
......@@ -143,6 +143,8 @@ class KeybindingsResolver {
}
}
const telemetryFrom = 'menu';
export class VSCodeMenu {
private static MAX_MENU_RECENT_ENTRIES = 10;
......@@ -397,12 +399,12 @@ export class VSCodeMenu {
newFile = this.createMenuItem(nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File"), 'workbench.action.files.newUntitledFile');
}
const open = new MenuItem(this.likeAction('workbench.action.files.openFileFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")), click: (menuItem, win, event) => this.windowsService.openFileFolderPicker(this.isOptionClick(event)) }));
const openFolder = new MenuItem(this.likeAction('workbench.action.files.openFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")), click: (menuItem, win, event) => this.windowsService.openFolderPicker(this.isOptionClick(event)) }));
const open = new MenuItem(this.likeAction('workbench.action.files.openFileFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")), click: (menuItem, win, event) => this.windowsService.openFileFolderPicker(this.isOptionClick(event), { from: telemetryFrom }) }));
const openFolder = new MenuItem(this.likeAction('workbench.action.files.openFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")), click: (menuItem, win, event) => this.windowsService.openFolderPicker(this.isOptionClick(event), undefined, { from: telemetryFrom }) }));
let openFile: Electron.MenuItem;
if (hasNoWindows) {
openFile = new MenuItem(this.likeAction('workbench.action.files.openFile', { label: mnemonicLabel(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File...")), click: (menuItem, win, event) => this.windowsService.openFilePicker(this.isOptionClick(event)) }));
openFile = new MenuItem(this.likeAction('workbench.action.files.openFile', { label: mnemonicLabel(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File...")), click: (menuItem, win, event) => this.windowsService.openFilePicker(this.isOptionClick(event), undefined, undefined, { from: telemetryFrom }) }));
} else {
openFile = this.createMenuItem(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File..."), ['workbench.action.files.openFile', 'workbench.action.files.openFileInNewWindow']);
}
......@@ -1069,7 +1071,7 @@ export class VSCodeMenu {
}
private reportMenuActionTelemetry(id: string): void {
this.telemetryService.publicLog('workbenchActionExecuted', { id, from: 'menu' });
this.telemetryService.publicLog('workbenchActionExecuted', { id, from: telemetryFrom });
}
}
......
......@@ -30,6 +30,7 @@ import { getLastActiveWindow, findBestWindowOrFolder } from 'vs/code/node/window
import CommonEvent, { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/node/product';
import { OpenContext } from 'vs/code/common/windows';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
enum WindowError {
UNRESPONSIVE,
......@@ -101,9 +102,9 @@ export interface IWindowsMainService {
reload(win: VSCodeWindow, cli?: ParsedArgs): void;
open(openConfig: IOpenConfiguration): VSCodeWindow[];
openExtensionDevelopmentHostWindow(openConfig: IOpenConfiguration): void;
openFileFolderPicker(forceNewWindow?: boolean): void;
openFilePicker(forceNewWindow?: boolean, path?: string, window?: VSCodeWindow): void;
openFolderPicker(forceNewWindow?: boolean, window?: VSCodeWindow): void;
openFileFolderPicker(forceNewWindow?: boolean, data?: ITelemetryData): void;
openFilePicker(forceNewWindow?: boolean, path?: string, window?: VSCodeWindow, data?: ITelemetryData): void;
openFolderPicker(forceNewWindow?: boolean, window?: VSCodeWindow, data?: ITelemetryData): void;
openAccessibilityOptions(): void;
focusLastActive(cli: ParsedArgs, context: OpenContext): VSCodeWindow;
getLastActiveWindow(): VSCodeWindow;
......@@ -159,6 +160,7 @@ export class WindowsManager implements IWindowsMainService {
@IEnvironmentService private environmentService: IEnvironmentService,
@ILifecycleService private lifecycleService: ILifecycleService,
@IBackupMainService private backupService: IBackupMainService,
@ITelemetryService private telemetryService: ITelemetryService,
@IConfigurationService private configurationService: IConfigurationService
) { }
......@@ -940,16 +942,16 @@ export class WindowsManager implements IWindowsMainService {
return state;
}
public openFileFolderPicker(forceNewWindow?: boolean): void {
this.doPickAndOpen({ pickFolders: true, pickFiles: true, forceNewWindow });
public openFileFolderPicker(forceNewWindow?: boolean, data?: ITelemetryData): void {
this.doPickAndOpen({ pickFolders: true, pickFiles: true, forceNewWindow }, 'openFileFolder', data);
}
public openFilePicker(forceNewWindow?: boolean, path?: string, window?: VSCodeWindow): void {
this.doPickAndOpen({ pickFiles: true, forceNewWindow, path, window });
public openFilePicker(forceNewWindow?: boolean, path?: string, window?: VSCodeWindow, data?: ITelemetryData): void {
this.doPickAndOpen({ pickFiles: true, forceNewWindow, path, window }, 'openFile', data);
}
public openFolderPicker(forceNewWindow?: boolean, window?: VSCodeWindow): void {
this.doPickAndOpen({ pickFolders: true, forceNewWindow, window });
public openFolderPicker(forceNewWindow?: boolean, window?: VSCodeWindow, data?: ITelemetryData): void {
this.doPickAndOpen({ pickFolders: true, forceNewWindow, window }, 'openFolder', data);
}
public openAccessibilityOptions(): void {
......@@ -968,11 +970,17 @@ export class WindowsManager implements IWindowsMainService {
win.loadURL('chrome://accessibility');
}
private doPickAndOpen(options: INativeOpenDialogOptions): void {
private doPickAndOpen(options: INativeOpenDialogOptions, eventName: string, data?: ITelemetryData): void {
this.getFileOrFolderPaths(options, (paths: string[]) => {
if (paths && paths.length) {
const nOfPaths = paths ? paths.length : 0;
if (nOfPaths) {
this.open({ context: OpenContext.DIALOG, cli: this.environmentService.args, pathsToOpen: paths, forceNewWindow: options.forceNewWindow });
}
this.telemetryService.publicLog(eventName, {
...data,
outcome: nOfPaths ? 'success' : 'canceled',
nOfPaths
});
});
}
......
......@@ -8,6 +8,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import Event from 'vs/base/common/event';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export const IWindowsService = createDecorator<IWindowsService>('windowsService');
......@@ -18,9 +19,9 @@ export interface IWindowsService {
onWindowOpen: Event<number>;
onWindowFocus: Event<number>;
openFileFolderPicker(windowId: number, forceNewWindow?: boolean): TPromise<void>;
openFilePicker(windowId: number, forceNewWindow?: boolean, path?: string): TPromise<void>;
openFolderPicker(windowId: number, forceNewWindow?: boolean): TPromise<void>;
openFileFolderPicker(windowId: number, forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void>;
openFilePicker(windowId: number, forceNewWindow?: boolean, path?: string, data?: ITelemetryData): TPromise<void>;
openFolderPicker(windowId: number, forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void>;
reloadWindow(windowId: number): TPromise<void>;
openDevTools(windowId: number): TPromise<void>;
toggleDevTools(windowId: number): TPromise<void>;
......@@ -63,9 +64,9 @@ export interface IWindowService {
_serviceBrand: any;
getCurrentWindowId(): number;
openFileFolderPicker(forceNewWindow?: boolean): TPromise<void>;
openFilePicker(forceNewWindow?: boolean, path?: string): TPromise<void>;
openFolderPicker(forceNewWindow?: boolean): TPromise<void>;
openFileFolderPicker(forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void>;
openFilePicker(forceNewWindow?: boolean, path?: string, data?: ITelemetryData): TPromise<void>;
openFolderPicker(forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void>;
reloadWindow(): TPromise<void>;
openDevTools(): TPromise<void>;
toggleDevTools(): TPromise<void>;
......
......@@ -9,13 +9,14 @@ import { TPromise } from 'vs/base/common/winjs.base';
import Event, { buffer } from 'vs/base/common/event';
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
import { IWindowsService } from './windows';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export interface IWindowsChannel extends IChannel {
call(command: 'event:onWindowOpen'): TPromise<number>;
call(command: 'event:onWindowFocus'): TPromise<number>;
call(command: 'openFileFolderPicker', arg: [number, boolean]): TPromise<void>;
call(command: 'openFilePicker', arg: [number, boolean, string]): TPromise<void>;
call(command: 'openFolderPicker', arg: [number, boolean]): TPromise<void>;
call(command: 'openFileFolderPicker', arg: [number, boolean, ITelemetryData]): TPromise<void>;
call(command: 'openFilePicker', arg: [number, boolean, string, ITelemetryData]): TPromise<void>;
call(command: 'openFolderPicker', arg: [number, boolean, ITelemetryData]): TPromise<void>;
call(command: 'reloadWindow', arg: number): TPromise<void>;
call(command: 'toggleDevTools', arg: number): TPromise<void>;
call(command: 'closeFolder', arg: number): TPromise<void>;
......@@ -57,9 +58,9 @@ export class WindowsChannel implements IWindowsChannel {
switch (command) {
case 'event:onWindowOpen': return eventToCall(this.onWindowOpen);
case 'event:onWindowFocus': return eventToCall(this.onWindowFocus);
case 'openFileFolderPicker': return this.service.openFileFolderPicker(arg[0], arg[1]);
case 'openFilePicker': return this.service.openFilePicker(arg[0], arg[1], arg[2]);
case 'openFolderPicker': return this.service.openFolderPicker(arg[0], arg[1]);
case 'openFileFolderPicker': return this.service.openFileFolderPicker(arg[0], arg[1], arg[2]);
case 'openFilePicker': return this.service.openFilePicker(arg[0], arg[1], arg[2], arg[3]);
case 'openFolderPicker': return this.service.openFolderPicker(arg[0], arg[1], arg[2]);
case 'reloadWindow': return this.service.reloadWindow(arg);
case 'openDevTools': return this.service.openDevTools(arg);
case 'toggleDevTools': return this.service.toggleDevTools(arg);
......@@ -102,16 +103,16 @@ export class WindowsChannelClient implements IWindowsService {
private _onWindowFocus: Event<number> = eventFromCall<number>(this.channel, 'event:onWindowFocus');
get onWindowFocus(): Event<number> { return this._onWindowFocus; }
openFileFolderPicker(windowId: number, forceNewWindow?: boolean): TPromise<void> {
return this.channel.call('openFileFolderPicker', [windowId, forceNewWindow]);
openFileFolderPicker(windowId: number, forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void> {
return this.channel.call('openFileFolderPicker', [windowId, forceNewWindow, data]);
}
openFilePicker(windowId: number, forceNewWindow?: boolean, path?: string): TPromise<void> {
return this.channel.call('openFilePicker', [windowId, forceNewWindow, path]);
openFilePicker(windowId: number, forceNewWindow?: boolean, path?: string, data?: ITelemetryData): TPromise<void> {
return this.channel.call('openFilePicker', [windowId, forceNewWindow, path, data]);
}
openFolderPicker(windowId: number, forceNewWindow?: boolean): TPromise<void> {
return this.channel.call('openFolderPicker', [windowId, forceNewWindow]);
openFolderPicker(windowId: number, forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void> {
return this.channel.call('openFolderPicker', [windowId, forceNewWindow, data]);
}
reloadWindow(windowId: number): TPromise<void> {
......
......@@ -7,6 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export class WindowService implements IWindowService {
......@@ -21,16 +22,16 @@ export class WindowService implements IWindowService {
return this.windowId;
}
openFileFolderPicker(forceNewWindow?: boolean): TPromise<void> {
return this.windowsService.openFileFolderPicker(this.windowId, forceNewWindow);
openFileFolderPicker(forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void> {
return this.windowsService.openFileFolderPicker(this.windowId, forceNewWindow, data);
}
openFilePicker(forceNewWindow?: boolean, path?: string): TPromise<void> {
return this.windowsService.openFilePicker(this.windowId, forceNewWindow, path);
openFilePicker(forceNewWindow?: boolean, path?: string, data?: ITelemetryData): TPromise<void> {
return this.windowsService.openFilePicker(this.windowId, forceNewWindow, path, data);
}
openFolderPicker(forceNewWindow?: boolean): TPromise<void> {
return this.windowsService.openFolderPicker(this.windowId, forceNewWindow);
openFolderPicker(forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void> {
return this.windowsService.openFolderPicker(this.windowId, forceNewWindow, data);
}
reloadWindow(): TPromise<void> {
......
......@@ -14,6 +14,7 @@ import { shell, crashReporter, app } from 'electron';
import Event, { chain } from 'vs/base/common/event';
import { fromEventEmitter } from 'vs/base/node/event';
import { IURLService } from 'vs/platform/url/common/url';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
// TODO@Joao: remove this dependency, move all implementation to this class
import { OpenContext } from 'vs/code/common/windows';
......@@ -39,19 +40,19 @@ export class WindowsService implements IWindowsService, IDisposable {
.on(this.openFileForURI, this, this.disposables);
}
openFileFolderPicker(windowId: number, forceNewWindow?: boolean): TPromise<void> {
this.windowsMainService.openFileFolderPicker(forceNewWindow);
openFileFolderPicker(windowId: number, forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void> {
this.windowsMainService.openFileFolderPicker(forceNewWindow, data);
return TPromise.as(null);
}
openFilePicker(windowId: number, forceNewWindow?: boolean, path?: string): TPromise<void> {
this.windowsMainService.openFilePicker(forceNewWindow, path);
openFilePicker(windowId: number, forceNewWindow?: boolean, path?: string, data?: ITelemetryData): TPromise<void> {
this.windowsMainService.openFilePicker(forceNewWindow, path, undefined, data);
return TPromise.as(null);
}
openFolderPicker(windowId: number, forceNewWindow?: boolean): TPromise<void> {
openFolderPicker(windowId: number, forceNewWindow?: boolean, data?: ITelemetryData): TPromise<void> {
const vscodeWindow = this.windowsMainService.getWindowById(windowId);
this.windowsMainService.openFolderPicker(forceNewWindow, vscodeWindow);
this.windowsMainService.openFolderPicker(forceNewWindow, vscodeWindow, data);
return TPromise.as(null);
}
......
......@@ -9,6 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions';
import nls = require('vs/nls');
import { IWindowService } from 'vs/platform/windows/common/windows';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export class OpenFolderAction extends Action {
......@@ -23,8 +24,8 @@ export class OpenFolderAction extends Action {
super(id, label);
}
run(): TPromise<any> {
return this.windowService.openFolderPicker();
run(event?: any, data?: ITelemetryData): TPromise<any> {
return this.windowService.openFolderPicker(undefined, data);
}
}
......@@ -41,7 +42,7 @@ export class OpenFileFolderAction extends Action {
super(id, label);
}
run(): TPromise<any> {
return this.windowService.openFileFolderPicker();
run(event?: any, data?: ITelemetryData): TPromise<any> {
return this.windowService.openFileFolderPicker(undefined, data);
}
}
......@@ -50,6 +50,7 @@ import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { ITextModelResolverService } from 'vs/editor/common/services/resolverService';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { withFocussedFilesExplorerViewItem, revealInOSCommand, revealInExplorerCommand, copyPathCommand } from 'vs/workbench/parts/files/browser/fileCommands';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export interface IEditableData {
action: IAction;
......@@ -1802,10 +1803,10 @@ export class OpenFileAction extends Action {
super(id, label);
}
run(): TPromise<any> {
run(event?: any, data?: ITelemetryData): TPromise<any> {
const fileResource = toResource(this.editorService.getActiveEditorInput(), { supportSideBySide: true, filter: 'file' });
return this.windowService.openFilePicker(false, fileResource ? paths.dirname(fileResource.fsPath) : void 0);
return this.windowService.openFilePicker(false, fileResource ? paths.dirname(fileResource.fsPath) : void 0, data);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册