提交 570b8d54 编写于 作者: C Christof Marti

Remove experiments and add new setting (#12387)

上级 7bf01068
......@@ -22,9 +22,6 @@ export interface ITelemetryData {
}
export interface ITelemetryExperiments {
showNewUserWatermark: boolean;
openUntitledFile: boolean;
enableWelcomePage: boolean;
mergeQuickLinks: boolean;
}
......
......@@ -13,15 +13,10 @@ import { ConfigurationSource, IConfigurationService } from 'vs/platform/configur
import { IKeybindingService, KeybindingSource } from 'vs/platform/keybinding/common/keybinding';
import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ITelemetryService, ITelemetryExperiments, ITelemetryInfo, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import * as objects from 'vs/base/common/objects';
export const defaultExperiments: ITelemetryExperiments = {
showNewUserWatermark: false,
openUntitledFile: true,
enableWelcomePage: true,
mergeQuickLinks: false,
};
......@@ -45,43 +40,20 @@ export const NullTelemetryService = {
};
export function loadExperiments(accessor: ServicesAccessor): ITelemetryExperiments {
const contextService = accessor.get(IWorkspaceContextService);
const storageService = accessor.get(IStorageService);
const configurationService = accessor.get(IConfigurationService);
updateExperimentsOverrides(configurationService, storageService);
configurationService.onDidUpdateConfiguration(e => updateExperimentsOverrides(configurationService, storageService));
let {
showNewUserWatermark,
openUntitledFile,
enableWelcomePage,
mergeQuickLinks,
} = splitExperimentsRandomness(storageService);
const newUserDuration = 24 * 60 * 60 * 1000;
const firstSessionDate = storageService.get('telemetry.firstSessionDate');
const isNewUser = !firstSessionDate || Date.now() - Date.parse(firstSessionDate) < newUserDuration;
if (!isNewUser || contextService.hasWorkspace()) {
showNewUserWatermark = defaultExperiments.showNewUserWatermark;
openUntitledFile = defaultExperiments.openUntitledFile;
}
return applyOverrides({
showNewUserWatermark,
openUntitledFile,
enableWelcomePage,
mergeQuickLinks,
}, storageService);
}
export function isWelcomePageEnabled(storageService: IStorageService) {
const overrides = getExperimentsOverrides(storageService);
return 'enableWelcomePage' in overrides ? overrides.enableWelcomePage : splitExperimentsRandomness(storageService).enableWelcomePage;
}, configurationService);
}
function applyOverrides(experiments: ITelemetryExperiments, storageService: IStorageService): ITelemetryExperiments {
const experimentsConfig = getExperimentsOverrides(storageService);
function applyOverrides(experiments: ITelemetryExperiments, configurationService: IConfigurationService): ITelemetryExperiments {
const experimentsConfig = getExperimentsOverrides(configurationService);
Object.keys(experiments).forEach(key => {
if (key in experimentsConfig) {
experiments[key] = experimentsConfig[key];
......@@ -92,22 +64,18 @@ function applyOverrides(experiments: ITelemetryExperiments, storageService: ISto
function splitExperimentsRandomness(storageService: IStorageService): ITelemetryExperiments {
const random1 = getExperimentsRandomness(storageService);
const [random2, showNewUserWatermark] = splitRandom(random1);
const [random3, openUntitledFile] = splitRandom(random2);
const [random2, /* showNewUserWatermark */] = splitRandom(random1);
const [random3, /* openUntitledFile */] = splitRandom(random2);
const [random4, mergeQuickLinks] = splitRandom(random3);
const [, enableWelcomePage] = splitRandom(random4);
// tslint:disable-next-line:no-unused-variable (https://github.com/Microsoft/TypeScript/issues/16628)
const [random5, /* enableWelcomePage */] = splitRandom(random4);
return {
showNewUserWatermark,
openUntitledFile,
enableWelcomePage,
mergeQuickLinks,
};
}
const GLOBAL_PREFIX = `storage://global/`; // TODO@Christoph debt, why do you need to know? just use the storageservice?
function getExperimentsRandomness(storageService: IStorageService) {
const key = GLOBAL_PREFIX + 'experiments.randomness';
const key = 'experiments.randomness';
let valueString = storageService.get(key);
if (!valueString) {
valueString = Math.random().toString();
......@@ -123,20 +91,9 @@ function splitRandom(random: number): [number, boolean] {
return [scaled - i, i === 1];
}
const experimentsOverridesKey = GLOBAL_PREFIX + 'experiments.overrides';
function getExperimentsOverrides(storageService: IStorageService): ITelemetryExperiments {
const valueString = storageService.get(experimentsOverridesKey);
return valueString ? JSON.parse(valueString) : <any>{};
}
function updateExperimentsOverrides(configurationService: IConfigurationService, storageService: IStorageService) {
const storageOverrides = getExperimentsOverrides(storageService);
function getExperimentsOverrides(configurationService: IConfigurationService): ITelemetryExperiments {
const config: any = configurationService.getConfiguration('telemetry');
const configOverrides = config && config.experiments || {};
if (!objects.equals(storageOverrides, configOverrides)) {
storageService.store(experimentsOverridesKey, JSON.stringify(configOverrides));
}
return config && config.experiments || {};
}
export interface ITelemetryAppender {
......@@ -284,6 +241,7 @@ const configurationValueWhitelist = [
'php.validate.enable',
'php.validate.run',
'workbench.welcome.enabled',
'workbench.startupEditor',
];
export function configurationTelemetry(telemetryService: ITelemetryService, configurationService: IConfigurationService): IDisposable {
......
......@@ -449,8 +449,8 @@ export class Workbench implements IPartService {
}
}
// Empty workbench: some first time users will not have an untiled file; returning users will always have one
else if (!this.contextService.hasWorkspace() && this.telemetryService.getExperiments().openUntitledFile && !this.configurationService.lookup('workbench.welcome.enabled').value) {
// Empty workbench
else if (!this.contextService.hasWorkspace() && this.openUntitledFile()) {
if (this.editorPart.hasEditorsToRestore()) {
return TPromise.as([]); // do not open any empty untitled file if we have editors to restore
}
......@@ -467,6 +467,17 @@ export class Workbench implements IPartService {
return TPromise.as([]);
}
private openUntitledFile() {
const startupEditor = this.configurationService.lookup('workbench.startupEditor');
if (!startupEditor.user && !startupEditor.workspace) {
const welcomeEnabled = this.configurationService.lookup('workbench.welcome.enabled');
if (welcomeEnabled.value !== undefined && welcomeEnabled.value !== null) {
return !welcomeEnabled.value;
}
}
return startupEditor.value === 'newUntitledFile';
}
private initServices(): void {
const { serviceCollection } = this.workbenchParams;
......
......@@ -19,17 +19,14 @@ import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { GlobalQuickOpenAction } from 'vs/workbench/browser/parts/quickopen/quickopen';
import { KeybindingsReferenceAction, OpenRecentAction } from 'vs/workbench/electron-browser/actions';
import { ShowRecommendedKeymapExtensionsAction } from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { OpenRecentAction } from 'vs/workbench/electron-browser/actions';
import { GlobalNewUntitledFileAction, OpenFileAction } from 'vs/workbench/parts/files/browser/fileActions';
import { OpenFolderAction, OpenFileFolderAction } from 'vs/workbench/browser/actions/fileActions';
import { ShowAllCommandsAction } from 'vs/workbench/parts/quickopen/browser/commandsHandler';
import { Parts, IPartService } from 'vs/workbench/services/part/common/partService';
import { StartAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { FindInFilesActionId } from 'vs/workbench/parts/search/common/constants';
import { OpenGlobalKeybindingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import { ToggleTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions';
import { SelectColorThemeAction } from 'vs/workbench/parts/themes/electron-browser/themes.contribution';
interface WatermarkEntry {
text: string;
......@@ -83,32 +80,6 @@ const startDebugging: WatermarkEntry = {
ids: [StartAction.ID]
};
const selectTheme: WatermarkEntry = {
text: nls.localize('watermark.selectTheme', "Change Theme"),
ids: [SelectColorThemeAction.ID]
};
const selectKeymap: WatermarkEntry = {
text: nls.localize('watermark.selectKeymap', "Change Keymap"),
ids: [ShowRecommendedKeymapExtensionsAction.ID]
};
const keybindingsReference: WatermarkEntry = {
text: nls.localize('watermark.keybindingsReference', "Keyboard Reference"),
ids: [KeybindingsReferenceAction.ID]
};
const openGlobalKeybindings: WatermarkEntry = {
text: nls.localize('watermark.openGlobalKeybindings', "Keyboard Shortcuts"),
ids: [OpenGlobalKeybindingsAction.ID]
};
const newUserEntries = [
showCommands,
selectTheme,
selectKeymap,
openFolderNonMacOnly,
openFileOrFolderMacOnly,
KeybindingsReferenceAction.AVAILABLE ? keybindingsReference : openGlobalKeybindings
];
const noFolderEntries = [
showCommands,
openFileNonMacOnly,
......@@ -176,8 +147,7 @@ export class WatermarkContribution implements IWorkbenchContribution {
const box = $(this.watermark)
.div({ 'class': 'watermark-box' });
const folder = this.contextService.hasWorkspace();
const newUser = this.telemetryService.getExperiments().showNewUserWatermark;
const selected = (newUser ? newUserEntries : (folder ? folderEntries : noFolderEntries))
const selected = folder ? folderEntries : noFolderEntries
.filter(entry => !('mac' in entry) || entry.mac === isMacintosh);
const update = () => {
const builder = $(box);
......
......@@ -10,6 +10,27 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { WelcomePageContribution, WelcomePageAction } from 'vs/workbench/parts/welcome/page/electron-browser/welcomePage';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
.registerConfiguration({
'id': 'workbench',
'order': 7,
'title': localize('workbenchConfigurationTitle', "Workbench"),
'properties': {
'workbench.startupEditor': {
'type': 'string',
'enum': ['none', 'welcomePage', 'newUntitledFile'],
'enumDescriptions': [
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.none' }, "Start without an editor."),
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePage' }, "Open the Welcome page (default)."),
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.newUntitledFile' }, "Open a new untitled file."),
],
'default': 'welcomePage',
'description': localize('workbench.startupEditor', "Controls which editor is shown at startup, if none is restored from the previous session. Select 'none' to start without an editor, 'welcomePage' to open the Welcome page (default), 'newUntitledFile' to open a new untitled file (only when not opening a folder).")
},
}
});
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(WelcomePageContribution);
......
......@@ -38,14 +38,12 @@ import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/com
import { registerColor, focusBorder, textLinkForeground, textLinkActiveForeground, foreground, descriptionForeground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { getExtraColor } from 'vs/workbench/parts/welcome/walkThrough/node/walkThroughUtils';
import { IExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/common/extensions';
import { isWelcomePageEnabled } from 'vs/platform/telemetry/common/telemetryUtils';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IStorageService } from "vs/platform/storage/common/storage";
import { Registry } from 'vs/platform/registry/common/platform';
used();
const enabledKey = 'workbench.welcome.enabled';
const configurationKey = 'workbench.startupEditor';
const oldConfigurationKey = 'workbench.welcome.enabled';
const telemetryFrom = 'welcomePage';
export class WelcomePageContribution implements IWorkbenchContribution {
......@@ -59,7 +57,7 @@ export class WelcomePageContribution implements IWorkbenchContribution {
@ITelemetryService telemetryService: ITelemetryService,
@IStorageService storageService: IStorageService
) {
const enabled = configurationService.lookup<boolean>(enabledKey).value;
const enabled = isWelcomePageEnabled(configurationService);
if (enabled) {
TPromise.join([
backupFileService.hasBackups(),
......@@ -71,20 +69,6 @@ export class WelcomePageContribution implements IWorkbenchContribution {
}
}).then(null, onUnexpectedError);
}
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
.registerConfiguration({
'id': 'workbench',
'order': 7,
'title': localize('workbenchConfigurationTitle', "Workbench"),
'properties': {
'workbench.welcome.enabled': {
'type': 'boolean',
'default': isWelcomePageEnabled(storageService),
'description': localize('welcomePage.enabled', "When enabled, will show the Welcome page on startup.")
},
}
});
}
public getId() {
......@@ -92,6 +76,17 @@ export class WelcomePageContribution implements IWorkbenchContribution {
}
}
function isWelcomePageEnabled(configurationService: IConfigurationService) {
const startupEditor = configurationService.lookup(configurationKey);
if (!startupEditor.user && !startupEditor.workspace) {
const welcomeEnabled = configurationService.lookup(oldConfigurationKey);
if (welcomeEnabled.value !== undefined && welcomeEnabled.value !== null) {
return welcomeEnabled.value;
}
}
return startupEditor.value === 'welcomePage';
}
export class WelcomePageAction extends Action {
public static ID = 'workbench.action.showWelcomePage';
......@@ -216,13 +211,13 @@ class WelcomePage {
}
private onReady(container: HTMLElement, recentlyOpened: TPromise<{ files: string[]; folders: string[]; }>, installedExtensions: TPromise<IExtensionStatus[]>): void {
const enabled = this.configurationService.lookup<boolean>(enabledKey).value;
const enabled = isWelcomePageEnabled(this.configurationService);
const showOnStartup = <HTMLInputElement>container.querySelector('#showOnStartup');
if (enabled) {
showOnStartup.setAttribute('checked', 'checked');
}
showOnStartup.addEventListener('click', e => {
this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: enabledKey, value: showOnStartup.checked });
this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: configurationKey, value: showOnStartup.checked ? 'welcomePage' : 'newUntitledFile' });
});
recentlyOpened.then(({ folders }) => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册