From 570b8d5417a31f086038d2316ca230f7df18ec83 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Mon, 19 Jun 2017 15:36:00 -0700 Subject: [PATCH] Remove experiments and add new setting (#12387) --- src/vs/platform/telemetry/common/telemetry.ts | 3 - .../telemetry/common/telemetryUtils.ts | 64 ++++--------------- .../workbench/electron-browser/workbench.ts | 15 ++++- .../watermark/electron-browser/watermark.ts | 34 +--------- .../welcomePage.contribution.ts | 21 ++++++ .../page/electron-browser/welcomePage.ts | 37 +++++------ 6 files changed, 63 insertions(+), 111 deletions(-) diff --git a/src/vs/platform/telemetry/common/telemetry.ts b/src/vs/platform/telemetry/common/telemetry.ts index 983743b9205..2d57d289534 100644 --- a/src/vs/platform/telemetry/common/telemetry.ts +++ b/src/vs/platform/telemetry/common/telemetry.ts @@ -22,9 +22,6 @@ export interface ITelemetryData { } export interface ITelemetryExperiments { - showNewUserWatermark: boolean; - openUntitledFile: boolean; - enableWelcomePage: boolean; mergeQuickLinks: boolean; } diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 4a8231e3d3a..ee9c9bf05e1 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -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) : {}; -} - -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 { diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index b598c69f953..60d3d8f017c 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -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; diff --git a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts index 466f854261e..a8c4f863306 100644 --- a/src/vs/workbench/parts/watermark/electron-browser/watermark.ts +++ b/src/vs/workbench/parts/watermark/electron-browser/watermark.ts @@ -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); diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution.ts index 89337fe2a01..b924959f037 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution.ts @@ -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(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(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(WelcomePageContribution); diff --git a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts index 11fa510fc64..323050e6c26 100644 --- a/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts +++ b/src/vs/workbench/parts/welcome/page/electron-browser/welcomePage.ts @@ -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(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(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): void { - const enabled = this.configurationService.lookup(enabledKey).value; + const enabled = isWelcomePageEnabled(this.configurationService); const showOnStartup = 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 }) => { -- GitLab