diff --git a/CHANGELOG.md b/CHANGELOG.md index ffd1bb4..361680c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v0.0.7 (03/13/2020) + +- Added the ability to move steps back/forward in order to rearrange steps in a tour + ## v0.0.6 (03/13/2020) - Added the `'Resume Tour`, `End Tour`, `Change Title`, `Change Description` and `Delete Tour` commands to the `Code Tours` tree view to enable easily managing existing tours diff --git a/package.json b/package.json index 1f2341a..8e781af 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,16 @@ "category": "Code Tour", "icon": "$(close)" }, + { + "command": "codetour.moveTourStepBack", + "title": "Move Up", + "icon": "$(arrow-up)" + }, + { + "command": "codetour.moveTourStepForward", + "title": "Move Down", + "icon": "$(arrow-down)" + }, { "command": "codetour.nextTourStep", "title": "Next", @@ -270,9 +280,29 @@ "when": "viewItem =~ /^codetour.tour/", "group": "delete@1" }, + { + "command": "codetour.moveTourStepBack", + "when": "viewItem =~ /^codetour.tourStep.hasPrevious/", + "group": "inline@1" + }, + { + "command": "codetour.moveTourStepForward", + "when": "viewItem =~ /codetour.tourStep.*(.hasNext)/", + "group": "inline@2" + }, + { + "command": "codetour.moveTourStepBack", + "when": "viewItem =~ /^codetour.tourStep.hasPrevious/", + "group": "basic@1" + }, + { + "command": "codetour.moveTourStepForward", + "when": "viewItem =~ /codetour.tourStep.*(.hasNext)/", + "group": "basic@2" + }, { "command": "codetour.deleteTourStep", - "when": "viewItem == codetour.tour.step", + "when": "viewItem == codetour.tourStep", "group": "manage@1" } ] diff --git a/src/commands.ts b/src/commands.ts index 3edaf05..3b5ca16 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -13,7 +13,7 @@ import { updateCurrentThread } from "./store/actions"; import { discoverTours } from "./store/provider"; -import { CodeTourNode } from "./tree/nodes"; +import { CodeTourNode, CodeTourStepNode } from "./tree/nodes"; interface CodeTourQuickPickItem extends vscode.QuickPickItem { tour: CodeTour; @@ -191,6 +191,15 @@ export function registerCommands() { } ); + function saveTourIfNeccessary(tour: CodeTour) { + if (tour.id) { + const uri = vscode.Uri.parse(tour.id); + delete tour.id; + const tourContent = JSON.stringify(tour, null, 2); + vscode.workspace.fs.writeFile(uri, new Buffer(tourContent)); + } + } + async function updateTourProperty(tour: CodeTour, property: string) { const propertyValue = await vscode.window.showInputBox({ prompt: `Enter the ${property} for this tour`, @@ -205,16 +214,27 @@ export function registerCommands() { // @ts-ignore tour[property] = propertyValue; - // We don't need to persist the tour change - // if it doesn't have an id (e.g. is pending being saved) - if (tour.id) { - const uri = vscode.Uri.parse(tour.id); - delete tour.id; - const tourContent = JSON.stringify(tour, null, 2); - vscode.workspace.fs.writeFile(uri, new Buffer(tourContent)); - } + saveTourIfNeccessary(tour); } + function moveStep(tour: CodeTour, stepNumber: number, movement: number) { + const step = tour.steps[stepNumber]; + tour.steps.splice(stepNumber, 1); + tour.steps.splice(stepNumber + movement, 0, step); + + saveTourIfNeccessary(tour); + } + + vscode.commands.registerCommand( + `${EXTENSION_NAME}.moveTourStepBack`, + (node: CodeTourStepNode) => moveStep(node.tour, node.stepNumber, -1) + ); + + vscode.commands.registerCommand( + `${EXTENSION_NAME}.moveTourStepForward`, + (node: CodeTourStepNode) => moveStep(node.tour, node.stepNumber, 1) + ); + vscode.commands.registerCommand( `${EXTENSION_NAME}.changeTourDescription`, (node: CodeTourNode) => updateTourProperty(node.tour, "description") diff --git a/src/status.ts b/src/status.ts index af1701f..6dcb0c8 100644 --- a/src/status.ts +++ b/src/status.ts @@ -1,5 +1,5 @@ import * as vscode from "vscode"; -import { store, CodeTour } from "./store"; +import { store } from "./store"; import { EXTENSION_NAME } from "./constants"; import { reaction } from "mobx"; @@ -38,23 +38,25 @@ export function registerStatusBar() { reaction( // @ts-ignore () => [ - store.currentTour, + store.currentTour + ? [store.currentTour.title, store.currentTour.steps.length] + : null, store.currentStep, - store.isRecording, - store.currentTour ? store.currentTour.steps.length : null + store.isRecording ], - ([tour, step, isRecording]: [CodeTour | null, number, boolean]) => { - if (tour) { + () => { + if (store.currentTour) { if (!currentTourItem) { currentTourItem = createCurrentTourItem(); } - const prefix = isRecording ? "Recording " : ""; - currentTourItem.text = `${prefix}Code Tour: #${step + 1} of ${ - tour.steps.length - } (${tour.title})`; + const prefix = store.isRecording ? "Recording " : ""; + currentTourItem.text = `${prefix}Code Tour: #${store.currentStep + + 1} of ${store.currentTour.steps.length} (${ + store.currentTour.title + })`; - if (step === 0) { + if (store.currentStep === 0) { startTourItem.hide(); } } else { diff --git a/src/tree/nodes.ts b/src/tree/nodes.ts index 05605e6..67b8ed4 100644 --- a/src/tree/nodes.ts +++ b/src/tree/nodes.ts @@ -56,7 +56,7 @@ function getStepLabel(tour: CodeTour, step: number) { } export class CodeTourStepNode extends TreeItem { - constructor(tour: CodeTour, stepNumber: number) { + constructor(public tour: CodeTour, public stepNumber: number) { super(getStepLabel(tour, stepNumber)); const step = tour.steps[stepNumber]; @@ -76,6 +76,17 @@ export class CodeTourStepNode extends TreeItem { ); this.iconPath = ThemeIcon.File; + + const contextValues = ["codetour.tourStep"]; + if (stepNumber > 0) { + contextValues.push("hasPrevious"); + } + + if (stepNumber < tour.steps.length - 1) { + contextValues.push("hasNext"); + } + + this.contextValue = contextValues.join("."); } }