Remove legacy welcome page code

Closes #130005
This commit is contained in:
Jackson Kearl 2021-08-02 15:38:25 -07:00
parent e53be27652
commit 3590a629b1
No known key found for this signature in database
GPG key ID: DA09A59C409FC400
5 changed files with 6 additions and 941 deletions

View file

@ -1,75 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { escape } from 'vs/base/common/strings';
import { localize } from 'vs/nls';
export default () => `
<div class="welcomePageContainer">
<div class="welcomePage" role="document">
<div class="title">
<h1 class="caption">${escape(localize('welcomePage.vscode', "Visual Studio Code"))}</h1>
<p class="subtitle detail">${escape(localize({ key: 'welcomePage.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))}</p>
</div>
<div class="row">
<div class="splash">
<div class="section start">
<h2 class="caption">${escape(localize('welcomePage.start', "Start"))}</h2>
<ul>
<li><a href="command:workbench.action.files.newUntitledFile">${escape(localize('welcomePage.newFile', "New file"))}</a></li>
<li class="mac-only"><a href="command:workbench.action.files.openFileFolder">${escape(localize('welcomePage.openFolder', "Open folder..."))}</a> or <a href="command:git.clone">${escape(localize('welcomePage.gitClone', "clone repository..."))}</a></li>
<li class="windows-only linux-only"><a href="command:workbench.action.files.openFolder">${escape(localize('welcomePage.openFolder', "Open folder..."))}</a> or <a href="command:git.clone">${escape(localize('welcomePage.gitClone', "clone repository..."))}</a></li>
</ul>
</div>
<div class="section recent">
<h2 class="caption">${escape(localize('welcomePage.recent', "Recent"))}</h2>
<ul class="list">
<!-- Filled programmatically -->
<li class="moreRecent"><a href="command:workbench.action.openRecent">${escape(localize('welcomePage.moreRecent', "More..."))}</a><span class="path detail if_shortcut" data-command="workbench.action.openRecent">(<span class="shortcut" data-command="workbench.action.openRecent"></span>)</span></li>
</ul>
<p class="none detail">${escape(localize('welcomePage.noRecentFolders', "No recent folders"))}</p>
</div>
<div class="section help">
<h2 class="caption">${escape(localize('welcomePage.help', "Help"))}</h2>
<ul>
<li class="keybindingsReferenceLink"><a href="command:workbench.action.keybindingsReference">${escape(localize('welcomePage.keybindingsCheatsheet', "Printable keyboard cheatsheet"))}</a></li>
<li><a href="command:workbench.action.openIntroductoryVideosUrl">${escape(localize('welcomePage.introductoryVideos', "Introductory videos"))}</a></li>
<li><a href="command:workbench.action.openTipsAndTricksUrl">${escape(localize('welcomePage.tipsAndTricks', "Tips and Tricks"))}</a></li>
<li><a href="command:workbench.action.openDocumentationUrl">${escape(localize('welcomePage.productDocumentation', "Product documentation"))}</a></li>
<li><a href="https://github.com/microsoft/vscode">${escape(localize('welcomePage.gitHubRepository', "GitHub repository"))}</a></li>
<li><a href="https://stackoverflow.com/questions/tagged/vscode?sort=votes&pageSize=50">${escape(localize('welcomePage.stackOverflow', "Stack Overflow"))}</a></li>
<li><a href="command:workbench.action.openNewsletterSignupUrl">${escape(localize('welcomePage.newsletterSignup', "Join our Newsletter"))}</a></li>
</ul>
</div>
<p class="showOnStartup"><input type="checkbox" id="showOnStartup" class="checkbox"> <label class="caption" for="showOnStartup">${escape(localize('welcomePage.showOnStartup', "Show welcome page on startup"))}</label></p>
</div>
<div class="commands">
<div class="section customize">
<h2 class="caption">${escape(localize('welcomePage.customize', "Customize"))}</h2>
<div class="list">
<div class="item showLanguageExtensions"><button data-href="command:workbench.extensions.action.showLanguageExtensions"><h3 class="caption">${escape(localize('welcomePage.installExtensionPacks', "Tools and languages"))}</h3> <span class="detail">${escape(localize('welcomePage.installExtensionPacksDescription', "Install support for {0} and {1}"))
.replace('{0}', `<span class="extensionPackList"></span>`)
.replace('{1}', `<a href="command:workbench.extensions.action.showLanguageExtensions" title="${localize('welcomePage.showLanguageExtensions', "Show more language extensions")}">${escape(localize('welcomePage.moreExtensions', "more"))}</a>`)}
</span></button></div>
<div class="item showRecommendedKeymapExtensions"><button data-href="command:workbench.extensions.action.showRecommendedKeymapExtensions"><h3 class="caption">${escape(localize('welcomePage.installKeymapDescription', "Settings and keybindings"))}</h3> <span class="detail">${escape(localize('welcomePage.installKeymapExtension', "Install the settings and keyboard shortcuts of {0} and {1}"))
.replace('{0}', `<span class="keymapList"></span>`)
.replace('{1}', `<a href="command:workbench.extensions.action.showRecommendedKeymapExtensions" title="${localize('welcomePage.showKeymapExtensions', "Show other keymap extensions")}">${escape(localize('welcomePage.others', "others"))}</a>`)}
</span></button></div>
<div class="item selectTheme"><button data-href="command:workbench.action.selectTheme"><h3 class="caption">${escape(localize('welcomePage.colorTheme', "Color theme"))}</h3> <span class="detail">${escape(localize('welcomePage.colorThemeDescription', "Make the editor and your code look the way you love"))}</span></button></div>
</div>
</div>
<div class="section learn">
<h2 class="caption">${escape(localize('welcomePage.learn', "Learn"))}</h2>
<div class="list">
<div class="item showCommands"><button data-href="command:workbench.action.showCommands"><h3 class="caption">${escape(localize('welcomePage.showCommands', "Find and run all commands"))}</h3> <span class="detail">${escape(localize('welcomePage.showCommandsDescription', "Rapidly access and search commands from the Command Palette ({0})")).replace('{0}', '<span class="shortcut" data-command="workbench.action.showCommands"></span>')}</span></button></div>
<div class="item showInterfaceOverview"><button data-href="command:workbench.action.showInterfaceOverview"><h3 class="caption">${escape(localize('welcomePage.interfaceOverview', "Interface overview"))}</h3> <span class="detail">${escape(localize('welcomePage.interfaceOverviewDescription', "Get a visual overlay highlighting the major components of the UI"))}</span></button></div>
<div class="item showInteractivePlayground"><button data-href="command:workbench.action.showInteractivePlayground"><h3 class="caption">${escape(localize('welcomePage.interactivePlayground', "Interactive playground"))}</h3> <span class="detail">${escape(localize('welcomePage.interactivePlaygroundDescription', "Try out essential editor features in a short walkthrough"))}</span></button></div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -6,9 +6,8 @@
import { localize } from 'vs/nls';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { Registry } from 'vs/platform/registry/common/platform';
import { WelcomePageContribution, WelcomeInputSerializer } from 'vs/workbench/contrib/welcome/page/browser/welcomePage';
import { WelcomePageContribution, } from 'vs/workbench/contrib/welcome/page/browser/welcomePage';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration';
@ -35,5 +34,3 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(WelcomePageContribution, LifecyclePhase.Restored);
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(WelcomeInputSerializer.ID, WelcomeInputSerializer);

View file

@ -1,256 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench .part.editor > .content .welcomePageContainer {
align-items: center;
display: flex;
justify-content: center;
min-width: 100%;
min-height: 100%;
}
.monaco-workbench .part.editor > .content .welcomePage {
width: 90%;
max-width: 1200px;
font-size: 10px;
}
.monaco-workbench .part.editor > .content .welcomePage .row {
display: flex;
flex-flow: row;
}
.monaco-workbench .part.editor > .content .welcomePage .row .section {
overflow: hidden;
}
.monaco-workbench .part.editor > .content .welcomePage .row .splash {
overflow: hidden;
}
.monaco-workbench .part.editor > .content .welcomePage .row .commands {
overflow: hidden;
}
.monaco-workbench .part.editor > .content .welcomePage .row .commands .list {
overflow: hidden;
}
.monaco-workbench .part.editor > .content .welcomePage p {
font-size: 1.3em;
}
.monaco-workbench .part.editor > .content .welcomePage .keyboard {
font-family: "Lucida Grande", sans-serif;/* Keyboard shortcuts */
}
.monaco-workbench .part.editor > .content .welcomePage a {
text-decoration: none;
}
.monaco-workbench .part.editor > .content .welcomePage a:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px;
}
.monaco-workbench .part.editor > .content .welcomePage h1 {
padding: 0;
margin: 0;
border: none;
font-weight: normal;
font-size: 3.6em;
white-space: nowrap;
}
.monaco-workbench .part.editor > .content .welcomePage .title {
margin-top: 1em;
margin-bottom: 1em;
flex: 1 100%;
}
.monaco-workbench .part.editor > .content .welcomePage .subtitle {
margin-top: .8em;
font-size: 2.6em;
display: block;
}
.monaco-workbench.hc-black .part.editor > .content .welcomePage .subtitle {
font-weight: 200;
}
.monaco-workbench .part.editor > .content .welcomePage .splash,
.monaco-workbench .part.editor > .content .welcomePage .commands {
flex: 1 1 0;
}
.monaco-workbench .part.editor > .content .welcomePage h2 {
font-weight: 200;
margin-top: 17px;
margin-bottom: 5px;
font-size: 1.9em;
line-height: initial;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .section {
margin-bottom: 5em;
}
.monaco-workbench .part.editor > .content .welcomePage .splash ul {
margin: 0;
font-size: 1.3em;
list-style: none;
padding: 0;
}
.monaco-workbench .part.editor > .content .welcomePage .splash li {
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .recent {
min-height: 160px;
}
.monaco-workbench .part.editor > .content .welcomePageContainer.max-height-685px .splash .recent {
min-height: unset;
}
.monaco-workbench .part.editor > .content .welcomePage.emptyRecent .splash .recent .list {
display: none;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .recent .none {
display: none;
}
.monaco-workbench .part.editor > .content .welcomePage.emptyRecent .splash .recent .none {
display: initial;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .recent li.moreRecent {
margin-top: 5px;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .recent .path {
padding-left: 1em;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .title,
.monaco-workbench .part.editor > .content .welcomePage .splash .showOnStartup {
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.monaco-workbench .part.editor > .content .welcomePage .splash .showOnStartup > .checkbox {
vertical-align: bottom;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .list {
list-style: none;
padding: 0;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item {
margin: 7px 0px;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button {
margin: 1px;
padding: 12px 10px;
width: calc(100% - 2px);
height: 5em;
font-size: 1.3em;
text-align: left;
cursor: pointer;
white-space: nowrap;
font-family: inherit;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button > span {
display: inline-block;
width:100%;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button h3 {
font-weight: normal;
font-size: 1em;
margin: 0;
margin-bottom: .25em;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button {
border: none;
}
.monaco-workbench.hc-black .part.editor > .content .welcomePage .commands .item button > h3 {
font-weight: bold;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button:focus {
outline-style: solid;
outline-width: 1px;
}
.monaco-workbench.hc-black .part.editor > .content .welcomePage .commands .item button {
border-width: 1px;
border-style: solid;
}
.monaco-workbench.hc-black .part.editor > .content .welcomePage .commands .item button:hover {
outline-width: 1px;
outline-style: dashed;
outline-offset: -5px;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button .enabledExtension {
display: none;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button .installExtension.installed {
display: none;
}
.monaco-workbench .part.editor > .content .welcomePage .commands .item button .enabledExtension.installed {
display: inline;
}
.monaco-workbench .part.editor > .content .welcomePageContainer.max-height-685px .title {
display: none;
}
.file-icons-enabled .show-file-icons .vs_code_welcome_page-name-file-icon.file-icon::before {
content: ' ';
background-image: url('../../../../browser/media/code-icon.svg');
}
.monaco-workbench .part.editor > .content .welcomePage .mac-only,
.monaco-workbench .part.editor > .content .welcomePage .windows-only,
.monaco-workbench .part.editor > .content .welcomePage .linux-only {
display: none;
}
.monaco-workbench.mac .part.editor > .content .welcomePage .mac-only {
display: initial;
}
.monaco-workbench.windows .part.editor > .content .welcomePage .windows-only {
display: initial;
}
.monaco-workbench.linux .part.editor > .content .welcomePage .linux-only {
display: initial;
}
.monaco-workbench.mac .part.editor > .content .welcomePage li.mac-only {
display: list-item;
}
.monaco-workbench.windows .part.editor > .content .welcomePage li.windows-only {
display: list-item;
}
.monaco-workbench.linux .part.editor > .content .welcomePage li.linux-only {
display: list-item;
}

View file

@ -6,55 +6,25 @@
import 'vs/css!./welcomePage';
import 'vs/workbench/contrib/welcome/page/browser/vs_code_welcome_page';
import { URI } from 'vs/base/common/uri';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { ICommandService } from 'vs/platform/commands/common/commands';
import * as arrays from 'vs/base/common/arrays';
import { WalkThroughInput } from 'vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors';
import { IWindowOpenable } from 'vs/platform/windows/common/windows';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { localize } from 'vs/nls';
import { Action, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { FileAccess, Schemas } from 'vs/base/common/network';
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
import { getInstalledExtensions, IExtensionStatus, onExtensionChanged, isKeymapExtension } from 'vs/workbench/contrib/extensions/common/extensionsUtils';
import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
import { ILifecycleService, StartupKind } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { splitName } from 'vs/base/common/labels';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { focusBorder, textLinkForeground, textLinkActiveForeground, foreground, descriptionForeground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService, VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { IEditorSerializer } from 'vs/workbench/common/editor';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { TimeoutTimer } from 'vs/base/common/async';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ILabelService } from 'vs/platform/label/common/label';
import { IFileService } from 'vs/platform/files/common/files';
import { joinPath } from 'vs/base/common/resources';
import { IRecentlyOpened, isRecentWorkspace, IRecentWorkspace, IRecentFolder, isRecentFolder, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IProductService } from 'vs/platform/product/common/productService';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { GettingStartedInput, gettingStartedInputTypeId } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedInput';
import { welcomeButtonBackground, welcomeButtonHoverBackground, welcomePageBackground } from 'vs/workbench/contrib/welcome/page/browser/welcomePageColors';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
const configurationKey = 'workbench.startupEditor';
const oldConfigurationKey = 'workbench.welcome.enabled';
const telemetryFrom = 'welcomePage';
export class WelcomePageContribution implements IWorkbenchContribution {
@ -123,19 +93,17 @@ export class WelcomePageContribution implements IWorkbenchContribution {
}
private async openWelcome() {
const startupEditorSetting = this.configurationService.getValue(configurationKey);
const startupEditorTypeID = (startupEditorSetting === 'welcomePage' || startupEditorSetting === 'welcomePageInEmptyWorkbench') ? gettingStartedInputTypeId : welcomeInputTypeId;
const startupEditorTypeID = gettingStartedInputTypeId;
const editor = this.editorService.activeEditor;
// Ensure that the welcome editor won't get opened more than once
if (editor?.typeId === startupEditorTypeID || this.editorService.editors.some(e => e.typeId === startupEditorTypeID)) {
return;
}
const options: IEditorOptions = editor ? { pinned: false, index: 0 } : { pinned: false };
if (startupEditorTypeID === gettingStartedInputTypeId) {
this.editorService.openEditor(this.instantiationService.createInstance(GettingStartedInput, {}), options);
} else {
this.instantiationService.createInstance(WelcomePage).openEditor(options);
}
}
}
@ -157,556 +125,6 @@ function isWelcomePageEnabled(configurationService: IConfigurationService, conte
console.error(`Warning: 'workbench.startupEditor: readme' setting ignored due to being set somewhere other than user or default settings (user=${startupEditor.userValue}, default=${startupEditor.defaultValue})`);
}
return startupEditor.value === 'welcomePage'
|| startupEditor.value === 'legacy_welcomePage'
|| startupEditor.value === 'readme' && (startupEditor.userValue === 'readme' || startupEditor.defaultValue === 'readme')
|| ((contextService.getWorkbenchState() === WorkbenchState.EMPTY) && (startupEditor.value === 'legacy_welcomePageInEmptyWorkbench' || startupEditor.value === 'welcomePageInEmptyWorkbench'));
|| (contextService.getWorkbenchState() === WorkbenchState.EMPTY && startupEditor.value === 'welcomePageInEmptyWorkbench');
}
export class WelcomePageAction extends Action {
public static readonly ID = 'workbench.action.showWelcomePage';
public static readonly LABEL = localize('welcomePage', "Welcome");
constructor(
id: string,
label: string,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super(id, label);
}
public override run(): Promise<void> {
return this.instantiationService.createInstance(WelcomePage)
.openEditor()
.then(() => undefined);
}
}
interface ExtensionSuggestion {
name: string;
title?: string;
id: string;
isKeymap?: boolean;
isCommand?: boolean;
}
const extensionPacks: ExtensionSuggestion[] = [
{ name: localize('welcomePage.javaScript', "JavaScript"), id: 'dbaeumer.vscode-eslint' },
{ name: localize('welcomePage.python', "Python"), id: 'ms-python.python' },
{ name: localize('welcomePage.java', "Java"), id: 'vscjava.vscode-java-pack' },
{ name: localize('welcomePage.php', "PHP"), id: 'felixfbecker.php-pack' },
{ name: localize('welcomePage.azure', "Azure"), title: localize('welcomePage.showAzureExtensions', "Show Azure extensions"), id: 'workbench.extensions.action.showAzureExtensions', isCommand: true },
{ name: localize('welcomePage.docker', "Docker"), id: 'ms-azuretools.vscode-docker' },
];
const keymapExtensions: ExtensionSuggestion[] = [
{ name: localize('welcomePage.vim', "Vim"), id: 'vscodevim.vim', isKeymap: true },
{ name: localize('welcomePage.sublime', "Sublime"), id: 'ms-vscode.sublime-keybindings', isKeymap: true },
{ name: localize('welcomePage.atom', "Atom"), id: 'ms-vscode.atom-keybindings', isKeymap: true },
];
interface Strings {
installEvent: string;
installedEvent: string;
detailsEvent: string;
alreadyInstalled: string;
reloadAfterInstall: string;
installing: string;
extensionNotFound: string;
}
/* __GDPR__
"installExtension" : {
"${include}": [
"${WelcomePageInstall-1}"
]
}
*/
/* __GDPR__
"installedExtension" : {
"${include}": [
"${WelcomePageInstalled-1}",
"${WelcomePageInstalled-2}",
"${WelcomePageInstalled-3}",
"${WelcomePageInstalled-4}",
"${WelcomePageInstalled-6}"
]
}
*/
/* __GDPR__
"detailsExtension" : {
"${include}": [
"${WelcomePageDetails-1}"
]
}
*/
const extensionPackStrings: Strings = {
installEvent: 'installExtension',
installedEvent: 'installedExtension',
detailsEvent: 'detailsExtension',
alreadyInstalled: localize('welcomePage.extensionPackAlreadyInstalled', "Support for {0} is already installed."),
reloadAfterInstall: localize('welcomePage.willReloadAfterInstallingExtensionPack', "The window will reload after installing additional support for {0}."),
installing: localize('welcomePage.installingExtensionPack', "Installing additional support for {0}..."),
extensionNotFound: localize('welcomePage.extensionPackNotFound', "Support for {0} with id {1} could not be found."),
};
CommandsRegistry.registerCommand('workbench.extensions.action.showAzureExtensions', accessor => {
const viewletService = accessor.get(IViewletService);
return viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer)
.then(viewlet => {
viewlet.search('@sort:installs azure ');
viewlet.focus();
});
});
/* __GDPR__
"installKeymap" : {
"${include}": [
"${WelcomePageInstall-1}"
]
}
*/
/* __GDPR__
"installedKeymap" : {
"${include}": [
"${WelcomePageInstalled-1}",
"${WelcomePageInstalled-2}",
"${WelcomePageInstalled-3}",
"${WelcomePageInstalled-4}",
"${WelcomePageInstalled-6}"
]
}
*/
/* __GDPR__
"detailsKeymap" : {
"${include}": [
"${WelcomePageDetails-1}"
]
}
*/
const keymapStrings: Strings = {
installEvent: 'installKeymap',
installedEvent: 'installedKeymap',
detailsEvent: 'detailsKeymap',
alreadyInstalled: localize('welcomePage.keymapAlreadyInstalled', "The {0} keyboard shortcuts are already installed."),
reloadAfterInstall: localize('welcomePage.willReloadAfterInstallingKeymap', "The window will reload after installing the {0} keyboard shortcuts."),
installing: localize('welcomePage.installingKeymap', "Installing the {0} keyboard shortcuts..."),
extensionNotFound: localize('welcomePage.keymapNotFound', "The {0} keyboard shortcuts with id {1} could not be found."),
};
const welcomeInputTypeId = 'workbench.editors.welcomePageInput';
class WelcomePage extends Disposable {
readonly editorInput: WalkThroughInput;
constructor(
@IEditorService private readonly editorService: IEditorService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IWorkspacesService private readonly workspacesService: IWorkspacesService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ILabelService private readonly labelService: ILabelService,
@INotificationService private readonly notificationService: INotificationService,
@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionRecommendationsService private readonly tipsService: IExtensionRecommendationsService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@ILifecycleService lifecycleService: ILifecycleService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IHostService private readonly hostService: IHostService,
@IProductService private readonly productService: IProductService,
) {
super();
this._register(lifecycleService.onDidShutdown(() => this.dispose()));
const recentlyOpened = this.workspacesService.getRecentlyOpened();
const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions);
const resource = FileAccess.asBrowserUri('./vs_code_welcome_page', require)
.with({
scheme: Schemas.walkThrough,
query: JSON.stringify({ moduleId: 'vs/workbench/contrib/welcome/page/browser/vs_code_welcome_page' })
});
this.editorInput = this.instantiationService.createInstance(WalkThroughInput, {
typeId: welcomeInputTypeId,
name: localize('welcome.title', "Welcome"),
resource,
telemetryFrom,
onReady: (container: HTMLElement) => this.onReady(container, recentlyOpened, installedExtensions)
});
}
public openEditor(options: IEditorOptions = { pinned: false }) {
return this.editorService.openEditor(this.editorInput, options);
}
private onReady(container: HTMLElement, recentlyOpened: Promise<IRecentlyOpened>, installedExtensions: Promise<IExtensionStatus[]>): void {
const enabled = this.configurationService.getValue(configurationKey) === 'welcomePage';
const showOnStartup = <HTMLInputElement>container.querySelector('#showOnStartup');
if (enabled) {
showOnStartup.setAttribute('checked', 'checked');
}
showOnStartup.addEventListener('click', e => {
this.configurationService.updateValue(configurationKey, showOnStartup.checked ? 'welcomePage' : 'newUntitledFile');
});
const prodName = container.querySelector('.welcomePage .title .caption') as HTMLElement;
if (prodName) {
prodName.textContent = this.productService.nameLong;
}
recentlyOpened.then(({ workspaces }) => {
// Filter out the current workspace
workspaces = workspaces.filter(recent => !this.contextService.isCurrentWorkspace(isRecentWorkspace(recent) ? recent.workspace : recent.folderUri));
if (!workspaces.length) {
const recent = container.querySelector('.welcomePage') as HTMLElement;
recent.classList.add('emptyRecent');
return;
}
const ul = container.querySelector('.recent ul');
if (!ul) {
return;
}
const moreRecent = ul.querySelector('.moreRecent')!;
const workspacesToShow = workspaces.slice(0, 5);
const updateEntries = () => {
const listEntries = this.createListEntries(workspacesToShow);
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
ul.append(...listEntries, moreRecent);
};
updateEntries();
this._register(this.labelService.onDidChangeFormatters(updateEntries));
}).then(undefined, onUnexpectedError);
this.addExtensionList(container, '.extensionPackList', extensionPacks, extensionPackStrings);
this.addExtensionList(container, '.keymapList', keymapExtensions, keymapStrings);
this.updateInstalledExtensions(container, installedExtensions);
this._register(this.instantiationService.invokeFunction(onExtensionChanged)(ids => {
for (const id of ids) {
if (container.querySelector(`.installExtension[data-extension="${id.id}"], .enabledExtension[data-extension="${id.id}"]`)) {
const installedExtensions = this.instantiationService.invokeFunction(getInstalledExtensions);
this.updateInstalledExtensions(container, installedExtensions);
break;
}
}
}));
}
private createListEntries(recents: (IRecentWorkspace | IRecentFolder)[]) {
return recents.map(recent => {
let fullPath: string;
let windowOpenable: IWindowOpenable;
if (isRecentFolder(recent)) {
windowOpenable = { folderUri: recent.folderUri };
fullPath = recent.label || this.labelService.getWorkspaceLabel(recent.folderUri, { verbose: true });
} else {
fullPath = recent.label || this.labelService.getWorkspaceLabel(recent.workspace, { verbose: true });
windowOpenable = { workspaceUri: recent.workspace.configPath };
}
const { name, parentPath } = splitName(fullPath);
const li = document.createElement('li');
const a = document.createElement('a');
a.innerText = name;
a.title = fullPath;
a.setAttribute('aria-label', localize('welcomePage.openFolderWithPath', "Open folder {0} with path {1}", name, parentPath));
a.href = 'javascript:void(0)';
a.addEventListener('click', e => {
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', {
id: 'openRecentFolder',
from: telemetryFrom
});
this.hostService.openWindow([windowOpenable], { forceNewWindow: e.ctrlKey || e.metaKey, remoteAuthority: recent.remoteAuthority });
e.preventDefault();
e.stopPropagation();
});
li.appendChild(a);
const span = document.createElement('span');
span.classList.add('path');
span.classList.add('detail');
span.innerText = parentPath;
span.title = fullPath;
li.appendChild(span);
return li;
});
}
private addExtensionList(container: HTMLElement, listSelector: string, suggestions: ExtensionSuggestion[], strings: Strings) {
const list = container.querySelector(listSelector);
if (list) {
suggestions.forEach((extension, i) => {
if (i) {
list.appendChild(document.createTextNode(localize('welcomePage.extensionListSeparator', ", ")));
}
const a = document.createElement('a');
a.innerText = extension.name;
a.title = extension.title || (extension.isKeymap ? localize('welcomePage.installKeymap', "Install {0} keymap", extension.name) : localize('welcomePage.installExtensionPack', "Install additional support for {0}", extension.name));
if (extension.isCommand) {
a.href = `command:${extension.id}`;
list.appendChild(a);
} else {
a.classList.add('installExtension');
a.setAttribute('data-extension', extension.id);
a.href = 'javascript:void(0)';
a.addEventListener('click', e => {
this.installExtension(extension, strings);
e.preventDefault();
e.stopPropagation();
});
list.appendChild(a);
const span = document.createElement('span');
span.innerText = extension.name;
span.title = extension.isKeymap ? localize('welcomePage.installedKeymap', "{0} keymap is already installed", extension.name) : localize('welcomePage.installedExtensionPack', "{0} support is already installed", extension.name);
span.classList.add('enabledExtension');
span.setAttribute('data-extension', extension.id);
list.appendChild(span);
}
});
}
}
private installExtension(extensionSuggestion: ExtensionSuggestion, strings: Strings): void {
/* __GDPR__FRAGMENT__
"WelcomePageInstall-1" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.installEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
});
this.instantiationService.invokeFunction(getInstalledExtensions).then(extensions => {
const installedExtension = extensions.find(extension => areSameExtensions(extension.identifier, { id: extensionSuggestion.id }));
if (installedExtension && installedExtension.globallyEnabled) {
/* __GDPR__FRAGMENT__
"WelcomePageInstalled-1" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"outcome": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.installedEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
outcome: 'already_enabled',
});
this.notificationService.info(strings.alreadyInstalled.replace('{0}', extensionSuggestion.name));
return;
}
const foundAndInstalled = installedExtension ? Promise.resolve(installedExtension.local) : this.extensionGalleryService.query({ names: [extensionSuggestion.id], source: telemetryFrom }, CancellationToken.None)
.then((result): null | Promise<ILocalExtension | null> => {
const [extension] = result.firstPage;
if (!extension) {
return null;
}
return this.extensionManagementService.installFromGallery(extension)
.then(() => this.extensionManagementService.getInstalled())
.then(installed => {
const local = installed.filter(i => areSameExtensions(extension.identifier, i.identifier))[0];
// TODO: Do this as part of the install to avoid multiple events.
return this.extensionEnablementService.setEnablement([local], EnablementState.DisabledGlobally).then(() => local);
});
});
this.notificationService.prompt(
Severity.Info,
strings.reloadAfterInstall.replace('{0}', extensionSuggestion.name),
[{
label: localize('ok', "OK"),
run: () => {
const messageDelay = new TimeoutTimer();
messageDelay.cancelAndSet(() => {
this.notificationService.info(strings.installing.replace('{0}', extensionSuggestion.name));
}, 300);
const extensionsToDisable = extensions.filter(extension => isKeymapExtension(this.tipsService, extension) && extension.globallyEnabled).map(extension => extension.local);
extensionsToDisable.length ? this.extensionEnablementService.setEnablement(extensionsToDisable, EnablementState.DisabledGlobally) : Promise.resolve()
.then(() => {
return foundAndInstalled.then(foundExtension => {
messageDelay.cancel();
if (foundExtension) {
return this.extensionEnablementService.setEnablement([foundExtension], EnablementState.EnabledGlobally)
.then(() => {
/* __GDPR__FRAGMENT__
"WelcomePageInstalled-2" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"outcome": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.installedEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
outcome: installedExtension ? 'enabled' : 'installed',
});
return this.hostService.reload();
});
} else {
/* __GDPR__FRAGMENT__
"WelcomePageInstalled-3" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"outcome": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.installedEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
outcome: 'not_found',
});
this.notificationService.error(strings.extensionNotFound.replace('{0}', extensionSuggestion.name).replace('{1}', extensionSuggestion.id));
return undefined;
}
});
}).then(undefined, err => {
/* __GDPR__FRAGMENT__
"WelcomePageInstalled-4" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"outcome": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.installedEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
outcome: isPromiseCanceledError(err) ? 'canceled' : 'error',
});
this.notificationService.error(err);
});
}
}, {
label: localize('details', "Details"),
run: () => {
/* __GDPR__FRAGMENT__
"WelcomePageDetails-1" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.detailsEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
});
this.extensionsWorkbenchService.queryGallery({ names: [extensionSuggestion.id] }, CancellationToken.None)
.then(result => this.extensionsWorkbenchService.open(result.firstPage[0]))
.then(undefined, onUnexpectedError);
}
}]
);
}).then(undefined, err => {
/* __GDPR__FRAGMENT__
"WelcomePageInstalled-6" : {
"from" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"outcome": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog(strings.installedEvent, {
from: telemetryFrom,
extensionId: extensionSuggestion.id,
outcome: isPromiseCanceledError(err) ? 'canceled' : 'error',
});
this.notificationService.error(err);
});
}
private updateInstalledExtensions(container: HTMLElement, installedExtensions: Promise<IExtensionStatus[]>) {
installedExtensions.then(extensions => {
const elements = container.querySelectorAll('.installExtension, .enabledExtension');
for (let i = 0; i < elements.length; i++) {
elements[i].classList.remove('installed');
}
extensions.filter(ext => ext.globallyEnabled)
.map(ext => ext.identifier.id)
.forEach(id => {
const install = container.querySelectorAll(`.installExtension[data-extension="${id}"]`);
for (let i = 0; i < install.length; i++) {
install[i].classList.add('installed');
}
const enabled = container.querySelectorAll(`.enabledExtension[data-extension="${id}"]`);
for (let i = 0; i < enabled.length; i++) {
enabled[i].classList.add('installed');
}
});
}).then(undefined, onUnexpectedError);
}
}
export class WelcomeInputSerializer implements IEditorSerializer {
static readonly ID = welcomeInputTypeId;
public canSerialize(editorInput: EditorInput): boolean {
return true;
}
public serialize(editorInput: EditorInput): string {
return '';
}
public deserialize(instantiationService: IInstantiationService): WalkThroughInput {
return instantiationService.createInstance(WelcomePage)
.editorInput;
}
}
// theming
registerThemingParticipant((theme, collector) => {
const backgroundColor = theme.getColor(welcomePageBackground);
if (backgroundColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePageContainer { background-color: ${backgroundColor}; }`);
}
const foregroundColor = theme.getColor(foreground);
if (foregroundColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .caption { color: ${foregroundColor}; }`);
}
const descriptionColor = theme.getColor(descriptionForeground);
if (descriptionColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .detail { color: ${descriptionColor}; }`);
}
const buttonColor = getExtraColor(theme, welcomeButtonBackground, { dark: 'rgba(0, 0, 0, .2)', extra_dark: 'rgba(200, 235, 255, .042)', light: 'rgba(0,0,0,.04)', hc: 'black' });
if (buttonColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .commands .item button { background: ${buttonColor}; }`);
}
const buttonHoverColor = getExtraColor(theme, welcomeButtonHoverBackground, { dark: 'rgba(200, 235, 255, .072)', extra_dark: 'rgba(200, 235, 255, .072)', light: 'rgba(0,0,0,.10)', hc: null });
if (buttonHoverColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .commands .item button:hover { background: ${buttonHoverColor}; }`);
}
const link = theme.getColor(textLinkForeground);
if (link) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage a { color: ${link}; }`);
}
const activeLink = theme.getColor(textLinkActiveForeground);
if (activeLink) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage a:hover,
.monaco-workbench .part.editor > .content .welcomePage a:active { color: ${activeLink}; }`);
}
const focusColor = theme.getColor(focusBorder);
if (focusColor) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage a:focus { outline-color: ${focusColor}; }`);
}
const border = theme.getColor(contrastBorder);
if (border) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .commands .item button { border-color: ${border}; }`);
}
const activeBorder = theme.getColor(activeContrastBorder);
if (activeBorder) {
collector.addRule(`.monaco-workbench .part.editor > .content .welcomePage .commands .item button:hover { outline-color: ${activeBorder}; }`);
}
});

View file

@ -1,19 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { darken, inputBackground, editorWidgetBackground, lighten, registerColor, textLinkForeground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { localize } from 'vs/nls';
// Seprate from main module to break dependency cycles between welcomePage and gettingStarted.
export const welcomeButtonBackground = registerColor('welcomePage.buttonBackground', { dark: null, light: null, hc: null }, localize('welcomePage.buttonBackground', 'Background color for the buttons on the Welcome page.'));
export const welcomeButtonHoverBackground = registerColor('welcomePage.buttonHoverBackground', { dark: null, light: null, hc: null }, localize('welcomePage.buttonHoverBackground', 'Hover background color for the buttons on the Welcome page.'));
export const welcomePageBackground = registerColor('welcomePage.background', { light: null, dark: null, hc: null }, localize('welcomePage.background', 'Background color for the Welcome page.'));
export const welcomePageTileBackground = registerColor('welcomePage.tileBackground', { dark: editorWidgetBackground, light: editorWidgetBackground, hc: '#000' }, localize('welcomePage.tileBackground', 'Background color for the tiles on the Get Started page.'));
export const welcomePageTileHoverBackground = registerColor('welcomePage.tileHoverBackground', { dark: lighten(editorWidgetBackground, .2), light: darken(editorWidgetBackground, .1), hc: null }, localize('welcomePage.tileHoverBackground', 'Hover background color for the tiles on the Get Started.'));
export const welcomePageTileShadow = registerColor('welcomePage.tileShadow.', { light: widgetShadow, dark: widgetShadow, hc: null }, localize('welcomePage.tileShadow', 'Shadow color for the Welcome page walkthrough category buttons.'));
export const welcomePageProgressBackground = registerColor('welcomePage.progress.background', { light: inputBackground, dark: inputBackground, hc: inputBackground }, localize('welcomePage.progress.background', 'Foreground color for the Welcome page progress bars.'));
export const welcomePageProgressForeground = registerColor('welcomePage.progress.foreground', { light: textLinkForeground, dark: textLinkForeground, hc: textLinkForeground }, localize('welcomePage.progress.foreground', 'Background color for the Welcome page progress bars.'));