diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index b1046a3e613d2..d252616bc614a 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -556,6 +556,17 @@ left: -4px; } +.monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-arrow-small-right { + position: relative; + top: 3px; + left: 2px; +} + +.monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-check-all { + position: relative; + top: 3px; +} + .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlide .skip { display: block; margin: 2px auto; @@ -605,6 +616,11 @@ max-width: 100%; } +.monaco-workbench .part.editor > .content .gettingStartedContainer .button-link.next { + position: absolute; + right: 0; +} + .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link:hover { background: transparent; } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 9f5cd95c4907a..69a09d7258a6f 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -290,10 +290,7 @@ export class GettingStartedPage extends EditorPane { break; } case 'hideCategory': { - const selectedCategory = this.gettingStartedCategories.find(category => category.id === argument); - if (!selectedCategory) { throw Error('Could not find category with ID ' + argument); } - this.setHiddenCategories([...this.getHiddenCategories().add(argument)]); - this.gettingStartedList?.rerender(); + this.hideCategory(argument); break; } // Use selectTask over selectStep to keep telemetry consistant:https://github.com/microsoft/vscode/issues/122256 @@ -305,6 +302,19 @@ export class GettingStartedPage extends EditorPane { this.toggleStepCompletion(argument); break; } + case 'allDone': { + this.markAllStepsComplete(); + break; + } + case 'nextSection': { + const next = this.currentCategory?.next; + if (next) { + this.scrollToCategory(next); + } else { + console.error('Error scrolling to next section of', this.currentCategory); + } + break; + } default: { console.error('Dispatch to', command, argument, 'not defined'); break; @@ -317,6 +327,27 @@ export class GettingStartedPage extends EditorPane { }); } + private hideCategory(categoryId: string) { + const selectedCategory = this.gettingStartedCategories.find(category => category.id === categoryId); + if (!selectedCategory) { throw Error('Could not find category with ID ' + categoryId); } + this.setHiddenCategories([...this.getHiddenCategories().add(categoryId)]); + this.gettingStartedList?.rerender(); + } + + private markAllStepsComplete() { + if (!this.currentCategory || this.currentCategory.content.type !== 'steps') { + throw Error('cannot run step action for category of non steps type' + this.currentCategory?.id); + } + + this.currentCategory.content.steps.forEach(step => { + if (!step.done) { + this.gettingStartedService.progressStep(step.id); + } + }); + this.hideCategory(this.currentCategory.id); + this.scrollPrev(); + } + private toggleStepCompletion(argument: string) { if (!this.currentCategory || this.currentCategory.content.type !== 'steps') { throw Error('cannot run step action for category of non steps type' + this.currentCategory?.id); @@ -989,7 +1020,19 @@ export class GettingStartedPage extends EditorPane { stepDescription); }); - const stepsContainer = $('.getting-started-detail-container', { 'role': 'list' }, ...categoryElements); + const showNextCategory = + this.gettingStartedCategories.find(_category => _category.id === category.next && _category.content.type === 'steps' && !_category.content.done); + + const stepsContainer = $( + '.getting-started-detail-container', { 'role': 'list' }, + ...categoryElements, + $('.done-next-container', {}, + $('button.button-link.all-done', { 'x-dispatch': 'allDone' }, $('span.codicon.codicon-check-all'), localize('allDone', "Mark Done")), + ...(showNextCategory + ? [$('button.button-link.next', { 'x-dispatch': 'nextSection' }, localize('nextOne', "Next Section"), $('span.codicon.codicon-arrow-small-right'))] + : []), + ) + ); this.detailsScrollbar = this._register(new DomScrollableElement(stepsContainer, { className: 'steps-container' })); const stepListComponent = this.detailsScrollbar.getDomNode(); @@ -1249,7 +1292,7 @@ registerThemingParticipant((theme, collector) => { if (link) { collector.addRule(`.monaco-workbench .part.editor > .content .gettingStartedContainer a:not(.codicon-close) { color: ${link}; }`); collector.addRule(`.monaco-workbench .part.editor > .content .gettingStartedContainer .button-link { color: ${link}; }`); - collector.addRule(`.monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .scroll-button { color: ${link}; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon { color: ${link}; }`); } const activeLink = theme.getColor(textLinkActiveForeground); if (activeLink) { diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts index 16eac49227e26..c3e75b8d7c9b1 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts @@ -62,6 +62,7 @@ export interface IGettingStartedWalkthroughDescriptor { title: string description: string order: number + next?: string icon: | { type: 'icon', icon: ThemeIcon } | { type: 'image', path: string } @@ -88,6 +89,7 @@ export interface IGettingStartedCategory { title: string description: string order: number + next?: string icon: | { type: 'icon', icon: ThemeIcon } | { type: 'image', path: string } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts index 17bcc01feef96..677c337f4e997 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts @@ -30,6 +30,7 @@ export type BuiltinGettingStartedCategory = { id: string title: string, description: string, + next?: string, icon: ThemeIcon, when?: string, content: @@ -172,6 +173,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ title: localize('gettingStarted.setup.title', "Customize your Setup"), description: localize('gettingStarted.setup.description', "Extend and customize VS Code to make it yours."), icon: setupIcon, + next: 'Beginner', when: 'remoteName != codespaces', content: { type: 'steps', @@ -267,6 +269,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ id: 'Beginner', title: localize('gettingStarted.beginner.title', "Learn the Fundamentals"), icon: beginnerIcon, + next: 'Intermediate', description: localize('gettingStarted.beginner.description', "Jump right into VS Code and get an overview of the must-have features."), content: { type: 'steps',