Skip to content

Commit

Permalink
release notes in product
Browse files Browse the repository at this point in the history
fixes #10179
  • Loading branch information
joaomoreno committed Sep 23, 2016
1 parent bb70f24 commit 1e0779d
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/vs/code/electron-main/auto-updater.linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class LinuxAutoUpdaterImpl extends EventEmitter {
if (!update || !update.url || !update.version) {
this.emit('update-not-available');
} else {
this.emit('update-available', null, this.envService.product.downloadUrl);
this.emit('update-available', null, this.envService.product.downloadUrl, update.version);
}
})
.then(null, e => {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/code/electron-main/update-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ export class UpdateManager extends EventEmitter implements IUpdateService {
this.setState(State.CheckingForUpdate);
});

this.raw.on('update-available', (event, url: string) => {
this.emit('update-available', url);
this.raw.on('update-available', (event, url: string, version: string) => {
this.emit('update-available', url, version);

let data: IUpdate = null;

Expand Down
4 changes: 2 additions & 2 deletions src/vs/code/electron-main/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,9 @@ export class WindowsManager implements IWindowsService {
}
});

this.updateService.on('update-available', (url: string) => {
this.updateService.on('update-available', (url: string, version: string) => {
if (url) {
this.sendToFocused('vscode:update-available', url);
this.sendToFocused('vscode:update-available', url, version);
}
});

Expand Down
39 changes: 28 additions & 11 deletions src/vs/workbench/electron-browser/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {Action} from 'vs/base/common/actions';
import {ipcRenderer as ipc, shell} from 'electron';
import {IMessageService} from 'vs/platform/message/common/message';
import product from 'vs/platform/product';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput';

interface IUpdate {
releaseNotes: string;
Expand All @@ -35,13 +38,22 @@ const NotNowAction = new Action(
() => TPromise.as(true)
);

export const ShowReleaseNotesAction = (releaseNotesUrl: string, returnValue = false) => new Action(
'update.showReleaseNotes',
nls.localize('releaseNotes', "Release Notes"),
null,
true,
() => { shell.openExternal(releaseNotesUrl); return TPromise.as(returnValue); }
);
export class ShowReleaseNotesAction extends Action {

constructor(
private returnValue: boolean,
private version: string,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super('update.showReleaseNotes', nls.localize('releaseNotes', "Release Notes"), null, true);
}

run(): TPromise<boolean> {
return this.editorService.openEditor(this.instantiationService.createInstance(ReleaseNotesInput, this.version))
.then(() => this.returnValue);
}
}

export const DownloadAction = (url: string) => new Action(
'update.download',
Expand All @@ -54,19 +66,24 @@ export const DownloadAction = (url: string) => new Action(
export class Update {

constructor(
@IMessageService private messageService: IMessageService
@IMessageService private messageService: IMessageService,
@IInstantiationService private instantiationService: IInstantiationService
) {
ipc.on('vscode:update-downloaded', (event, update: IUpdate) => {
const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, false, update.version);

this.messageService.show(severity.Info, {
message: nls.localize('updateAvailable', "{0} will be updated after it restarts.", product.nameLong),
actions: [ApplyUpdateAction, NotNowAction, ShowReleaseNotesAction(product.releaseNotesUrl)]
actions: [ApplyUpdateAction, NotNowAction, releaseNotesAction]
});
});

ipc.on('vscode:update-available', (event, url: string) => {
ipc.on('vscode:update-available', (event, url: string, version: string) => {
const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, false, version);

this.messageService.show(severity.Info, {
message: nls.localize('thereIsUpdateAvailable', "There is an available update."),
actions: [DownloadAction(url), NotNowAction, ShowReleaseNotesAction(product.releaseNotesUrl)]
actions: [DownloadAction(url), NotNowAction, releaseNotesAction]
});
});

Expand Down
161 changes: 161 additions & 0 deletions src/vs/workbench/parts/update/electron-browser/media/markdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

body {
padding: 10px 20px;
line-height: 22px;
}

img {
max-width: 100%;
max-height: 100%;
}

a {
color: #4080D0;
text-decoration: none;
}

a:focus,
input:focus,
select:focus,
textarea:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px;
}

hr {
border: 0;
height: 2px;
border-bottom: 2px solid;
}

h1 {
padding-bottom: 0.3em;
line-height: 1.2;
border-bottom-width: 1px;
border-bottom-style: solid;
}

h1, h2, h3 {
font-weight: normal;
}

a:hover {
color: #4080D0;
text-decoration: underline;
}

table {
border-collapse: collapse;
}

table > thead > tr > th {
text-align: left;
border-bottom: 1px solid;
}

table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
padding: 5px 10px;
}

table > tbody > tr + tr > td {
border-top: 1px solid;
}

blockquote {
margin: 0 7px 0 5px;
padding: 0 16px 0 10px;
border-left: 5px solid;
}

code {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-size: 14px;
line-height: 19px;
}

.mac code {
font-size: 12px;
line-height: 18px;
}

code > div {
padding: 16px;
border-radius: 3px;
overflow: auto;
}

/** Theming */

.vscode-light {
color: rgb(30, 30, 30);
}

.vscode-dark {
color: #DDD;
}

.vscode-high-contrast {
color: white;
}

.vscode-light code {
color: #A31515;
}

.vscode-dark code {
color: #D7BA7D;
}

.vscode-light code > div {
background-color: rgba(220, 220, 220, 0.4);
}

.vscode-dark code > div {
background-color: rgba(10, 10, 10, 0.4);
}

.vscode-high-contrast code > div {
background-color: rgb(0, 0, 0);
}

.vscode-high-contrast h1 {
border-color: rgb(0, 0, 0);
}

.vscode-light table > thead > tr > th {
border-color: rgba(0, 0, 0, 0.69);
}

.vscode-dark table > thead > tr > th {
border-color: rgba(255, 255, 255, 0.69);
}

.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
border-color: rgba(0, 0, 0, 0.18);
}

.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
border-color: rgba(255, 255, 255, 0.18);
}

.vscode-light blockquote,
.vscode-dark blockquote {
background: rgba(127, 127, 127, 0.1);
border-color: rgba(0, 122, 204, 0.5);
}

.vscode-high-contrast blockquote {
background: transparent;
border-color: #fff;
}
131 changes: 131 additions & 0 deletions src/vs/workbench/parts/update/electron-browser/releaseNotesEditor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import { TPromise } from 'vs/base/common/winjs.base';
import { marked } from 'vs/base/common/marked/marked';
import { always } from 'vs/base/common/async';
import URI from 'vs/base/common/uri';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { Builder } from 'vs/base/browser/builder';
import { append, $, addClass, removeClass } from 'vs/base/browser/dom';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IThemeService } from 'vs/workbench/services/themes/common/themeService';
import { ReleaseNotesInput } from './releaseNotesInput';
import { EditorOptions } from 'vs/workbench/common/editor';
import WebView from 'vs/workbench/parts/html/browser/webview';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IMessageService } from 'vs/platform/message/common/message';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { asText } from 'vs/base/node/request';
import { IRequestService } from 'vs/platform/request/common/request';
import product from 'vs/platform/product';

function renderBody(body: string): string {
return `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<link rel="stylesheet" type="text/css" href="${ require.toUrl('./media/markdown.css') }" >
</head>
<body>${ body }</body>
</html>`;
}

export class ReleaseNotesEditor extends BaseEditor {

static ID: string = 'workbench.editor.releaseNotes';

private content: HTMLElement;

private contentDisposables: IDisposable[] = [];
private disposables: IDisposable[];

constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IKeybindingService private keybindingService: IKeybindingService,
@IMessageService private messageService: IMessageService,
@IRequestService private requestService: IRequestService,
@IOpenerService private openerService: IOpenerService
) {
super(ReleaseNotesEditor.ID, telemetryService);
this.disposables = [];
}

createEditor(parent: Builder): void {
const container = parent.getHTMLElement();
this.content = append(container, $('.release-notes', { 'style': 'height: 100%' }));
}

setInput(input: ReleaseNotesInput, options: EditorOptions): TPromise<void> {
const version = input.version;

this.content.innerHTML = '';

const match = /^(\d+\.\d)\./.exec(version);

if (!match) {
return TPromise.as(null);
}

const versionLabel = match[1].replace(/\./g, '_');
const baseUrl = 'https://code.visualstudio.com/raw';
const url = `${ baseUrl }/v${ versionLabel }.md`;

this.loadContents(() => this.requestService.request({ url })
.then(asText)
.then(marked.parse)
.then(renderBody)
.then<void>(body => {
const webview = new WebView(
this.content,
document.querySelector('.monaco-editor-background')
);

webview.baseUrl = `${ baseUrl }/`;
webview.style(this.themeService.getColorTheme());
webview.contents = [body];

webview.onDidClickLink(link => this.openerService.open(link), null, this.contentDisposables);
this.themeService.onDidColorThemeChange(themeId => webview.style(themeId), null, this.contentDisposables);
this.contentDisposables.push(webview);
})
.then(null, () => {
const uri = URI.parse(product.releaseNotesUrl);
this.openerService.open(uri);
this.editorService.closeEditor(this.position, this.input);
}));

return super.setInput(input, options);
}

private loadContents(loadingTask: ()=>TPromise<any>): void {
this.contentDisposables = dispose(this.contentDisposables);

this.content.innerHTML = '';
addClass(this.content, 'loading');

let promise = loadingTask();
promise = always(promise, () => removeClass(this.content, 'loading'));

this.contentDisposables.push(toDisposable(() => promise.cancel()));
}

layout(): void {
// noop
}

dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
Loading

0 comments on commit 1e0779d

Please sign in to comment.