diff --git a/docs/commands.md b/docs/commands.md index f1450e93ca..6914126251 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -95,6 +95,10 @@ Generates method stub for implementing the provided interface and inserts at the Extract logs in the `gopls (server)` output channel to the editor. +### `Go: Welcome` + +Open the welcome page for the Go extension. + ### `Go: Toggle gc details` Toggle the display of compiler optimization choices diff --git a/images/go-logo-blue.png b/media/go-logo-blue.png similarity index 100% rename from images/go-logo-blue.png rename to media/go-logo-blue.png diff --git a/images/gutter-blockblue.svg b/media/gutter-blockblue.svg similarity index 100% rename from images/gutter-blockblue.svg rename to media/gutter-blockblue.svg diff --git a/images/gutter-blockgreen.svg b/media/gutter-blockgreen.svg similarity index 100% rename from images/gutter-blockgreen.svg rename to media/gutter-blockgreen.svg diff --git a/images/gutter-blockred.svg b/media/gutter-blockred.svg similarity index 100% rename from images/gutter-blockred.svg rename to media/gutter-blockred.svg diff --git a/images/gutter-blockyellow.svg b/media/gutter-blockyellow.svg similarity index 100% rename from images/gutter-blockyellow.svg rename to media/gutter-blockyellow.svg diff --git a/images/gutter-slashblue.svg b/media/gutter-slashblue.svg similarity index 100% rename from images/gutter-slashblue.svg rename to media/gutter-slashblue.svg diff --git a/images/gutter-slashgreen.svg b/media/gutter-slashgreen.svg similarity index 100% rename from images/gutter-slashgreen.svg rename to media/gutter-slashgreen.svg diff --git a/images/gutter-slashred.svg b/media/gutter-slashred.svg similarity index 100% rename from images/gutter-slashred.svg rename to media/gutter-slashred.svg diff --git a/images/gutter-slashyellow.svg b/media/gutter-slashyellow.svg similarity index 100% rename from images/gutter-slashyellow.svg rename to media/gutter-slashyellow.svg diff --git a/images/gutter-vertblue.svg b/media/gutter-vertblue.svg similarity index 100% rename from images/gutter-vertblue.svg rename to media/gutter-vertblue.svg diff --git a/images/gutter-vertgreen.svg b/media/gutter-vertgreen.svg similarity index 100% rename from images/gutter-vertgreen.svg rename to media/gutter-vertgreen.svg diff --git a/images/gutter-vertred.svg b/media/gutter-vertred.svg similarity index 100% rename from images/gutter-vertred.svg rename to media/gutter-vertred.svg diff --git a/images/gutter-vertyellow.svg b/media/gutter-vertyellow.svg similarity index 100% rename from images/gutter-vertyellow.svg rename to media/gutter-vertyellow.svg diff --git a/media/welcome.css b/media/welcome.css new file mode 100644 index 0000000000..caee018ef4 --- /dev/null +++ b/media/welcome.css @@ -0,0 +1,4 @@ +/*--------------------------------------------------------- + * Copyright 2020 The Go Authors. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------*/ diff --git a/media/welcome.js b/media/welcome.js new file mode 100644 index 0000000000..8457bbe890 --- /dev/null +++ b/media/welcome.js @@ -0,0 +1,22 @@ +/*--------------------------------------------------------- + * Copyright 2020 The Go Authors. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------*/ + +// This script will be run within the webview itself +// It cannot access the main VS Code APIs directly. +(function () { + const vscode = acquireVsCodeApi(); + + function showReleaseNotes() { + vscode.postMessage({ + command: 'showReleaseNotes', + }); + } + + document.querySelector(".release-notes").addEventListener('click', () => { + showReleaseNotes(); + }); + +}()); + diff --git a/package.json b/package.json index d530bc524a..e1a1188ccb 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "name": "Go Team at Google" }, "license": "MIT", - "icon": "images/go-logo-blue.png", + "icon": "media/go-logo-blue.png", "categories": [ "Programming Languages", "Snippets", @@ -97,7 +97,8 @@ "onCommand:go.locate.tools", "onCommand:go.show.commands", "onDebugInitialConfigurations", - "onDebugResolve:go" + "onDebugResolve:go", + "onWebviewPanel:welcomeGo" ], "main": "./dist/goMain.js", "contributes": { @@ -250,6 +251,11 @@ "title": "Go: Extract Language Server Logs To Editor", "description": "Extract logs in the `gopls (server)` output channel to the editor." }, + { + "command": "go.welcome", + "title": "Go: Welcome", + "description": "Open the welcome page for the Go extension." + }, { "command": "go.toggle.gc_details", "title": "Go: Toggle gc details", diff --git a/src/goCover.ts b/src/goCover.ts index f1e96a5419..2d525b3376 100644 --- a/src/goCover.ts +++ b/src/goCover.ts @@ -54,18 +54,18 @@ let modifiedFiles: { export function initCoverageDecorators(ctx: vscode.ExtensionContext) { // Initialize gutter svgs gutterSvgs = { - blockred: ctx.asAbsolutePath('images/gutter-blockred.svg'), - blockgreen: ctx.asAbsolutePath('images/gutter-blockgreen.svg'), - blockblue: ctx.asAbsolutePath('images/gutter-blockblue.svg'), - blockyellow: ctx.asAbsolutePath('images/gutter-blockyellow.svg'), - slashred: ctx.asAbsolutePath('images/gutter-slashred.svg'), - slashgreen: ctx.asAbsolutePath('images/gutter-slashgreen.svg'), - slashblue: ctx.asAbsolutePath('images/gutter-slashblue.svg'), - slashyellow: ctx.asAbsolutePath('images/gutter-slashyellow.svg'), - verticalred: ctx.asAbsolutePath('images/gutter-vertred.svg'), - verticalgreen: ctx.asAbsolutePath('images/gutter-vertgreen.svg'), - verticalblue: ctx.asAbsolutePath('images/gutter-vertblue.svg'), - verticalyellow: ctx.asAbsolutePath('images/gutter-vertyellow.svg') + blockred: ctx.asAbsolutePath('media/gutter-blockred.svg'), + blockgreen: ctx.asAbsolutePath('media/gutter-blockgreen.svg'), + blockblue: ctx.asAbsolutePath('media/gutter-blockblue.svg'), + blockyellow: ctx.asAbsolutePath('media/gutter-blockyellow.svg'), + slashred: ctx.asAbsolutePath('media/gutter-slashred.svg'), + slashgreen: ctx.asAbsolutePath('media/gutter-slashgreen.svg'), + slashblue: ctx.asAbsolutePath('media/gutter-slashblue.svg'), + slashyellow: ctx.asAbsolutePath('media/gutter-slashyellow.svg'), + verticalred: ctx.asAbsolutePath('media/gutter-vertred.svg'), + verticalgreen: ctx.asAbsolutePath('media/gutter-vertgreen.svg'), + verticalblue: ctx.asAbsolutePath('media/gutter-vertblue.svg'), + verticalyellow: ctx.asAbsolutePath('media/gutter-vertyellow.svg') }; const goConfig = getGoConfig(); diff --git a/src/goMain.ts b/src/goMain.ts index 197363fa37..c7cd808d11 100644 --- a/src/goMain.ts +++ b/src/goMain.ts @@ -70,6 +70,7 @@ import { resolvePath, } from './util'; import { clearCacheForTools, fileExists, getCurrentGoRoot, setCurrentGoRoot } from './utils/pathUtils'; +import { WelcomePanel } from './welcome'; export let buildDiagnosticCollection: vscode.DiagnosticCollection; export let lintDiagnosticCollection: vscode.DiagnosticCollection; @@ -91,6 +92,15 @@ export function activate(ctx: vscode.ExtensionContext) { setWorkspaceState(ctx.workspaceState); setEnvironmentVariableCollection(ctx.environmentVariableCollection); + if (vscode.window.registerWebviewPanelSerializer) { + // Make sure we register a serializer in activation event + vscode.window.registerWebviewPanelSerializer(WelcomePanel.viewType, { + async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: any) { + WelcomePanel.revive(webviewPanel, ctx.extensionUri); + } + }); + } + if (isNightly()) { promptForLanguageServerDefaultChange(cfg); @@ -470,6 +480,11 @@ See https://github.com/golang/tools/blob/master/gopls/doc/settings.md#importshor showServerOutputChannel(); })); + ctx.subscriptions.push( + vscode.commands.registerCommand('go.welcome', () => { + WelcomePanel.createOrShow(ctx.extensionUri); + })); + ctx.subscriptions.push(vscode.commands.registerCommand('go.toggle.gc_details', () => { if (!languageServerIsRunning) { vscode.window.showErrorMessage('"Go: Toggle gc details" command is available only when the language server is running'); diff --git a/src/welcome.ts b/src/welcome.ts new file mode 100644 index 0000000000..3300888af7 --- /dev/null +++ b/src/welcome.ts @@ -0,0 +1,158 @@ +/*--------------------------------------------------------- + * Copyright 2020 The Go Authors. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------*/ + +// This code is modified from: +// https://github.com/microsoft/vscode-extension-samples/tree/master/webview-sample + +import vscode = require('vscode'); + +export class WelcomePanel { + public static currentPanel: WelcomePanel | undefined; + + public static readonly viewType = 'welcomeGo'; + + public static createOrShow(extensionUri: vscode.Uri) { + const column = vscode.window.activeTextEditor + ? vscode.window.activeTextEditor.viewColumn + : undefined; + + // If we already have a panel, show it. + if (WelcomePanel.currentPanel) { + WelcomePanel.currentPanel.panel.reveal(column); + return; + } + + // Otherwise, create a new panel. + const panel = vscode.window.createWebviewPanel( + WelcomePanel.viewType, + 'Go - Welcome', + column || vscode.ViewColumn.One, + { + // Enable javascript in the webview + enableScripts: true, + + // And restrict the webview to only loading content from our extension's directory. + localResourceRoots: [vscode.Uri.joinPath(extensionUri)], + } + ); + panel.iconPath = vscode.Uri.joinPath(extensionUri, 'media', 'go-logo-blue.png'); + + WelcomePanel.currentPanel = new WelcomePanel(panel, extensionUri); + } + + public static revive(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { + WelcomePanel.currentPanel = new WelcomePanel(panel, extensionUri); + } + + private readonly panel: vscode.WebviewPanel; + private readonly extensionUri: vscode.Uri; + private readonly dataroot: vscode.Uri; + private disposables: vscode.Disposable[] = []; + + private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { + this.panel = panel; + this.extensionUri = extensionUri; + this.dataroot = vscode.Uri.joinPath(this.extensionUri, 'media'); + + // Set the webview's initial html content + this.update(); + + // Listen for when the panel is disposed + // This happens when the user closes the panel or when the panel is closed programatically + this.panel.onDidDispose(() => this.dispose(), null, this.disposables); + + // Handle messages from the webview + this.panel.webview.onDidReceiveMessage( + (message) => { + console.log(message); + switch (message.command) { + case 'alert': + vscode.window.showErrorMessage(message.text); + return; + case 'showReleaseNotes': + const uri = vscode.Uri.joinPath(this.extensionUri, 'CHANGELOG.md'); + vscode.commands.executeCommand('markdown.showPreviewToSide', uri); + return; + } + }, + null, + this.disposables + ); + } + + public dispose() { + WelcomePanel.currentPanel = undefined; + + // Clean up our resources + this.panel.dispose(); + + while (this.disposables.length) { + const x = this.disposables.pop(); + if (x) { + x.dispose(); + } + } + } + + private update() { + const webview = this.panel.webview; + this.panel.webview.html = this.getHtmlForWebview(webview); + } + + private getHtmlForWebview(webview: vscode.Webview) { + // Local path to css styles and images + const scriptPathOnDisk = vscode.Uri.joinPath(this.dataroot, 'welcome.js'); + const stylePath = vscode.Uri.joinPath(this.dataroot, 'welcome.css'); + const gopherPath = vscode.Uri.joinPath(this.dataroot, 'go-logo-blue.png'); + + // Uri to load styles and images into webview + const scriptURI = webview.asWebviewUri(scriptPathOnDisk); + const stylesURI = webview.asWebviewUri(stylePath); + const gopherURI = webview.asWebviewUri(gopherPath); + + // Use a nonce to only allow specific scripts to be run + const nonce = getNonce(); + return ` + + + + + + + + + + + + Go - Welcome + + +
+ logo +

Go - Welcome

+
+ +

Rich Go language support for Visual Studio Code

+ +

Release Notes

+ + + + `; + } +} + +function getNonce() { + let text = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < 32; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +}