Skip to content

Commit bc7dead

Browse files
committed
Add in product changelog
1 parent 494f7eb commit bc7dead

File tree

7 files changed

+343
-3
lines changed

7 files changed

+343
-3
lines changed

extensions/gitpod-remote/package.nls.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"openTwitter": "Gitpod: Follow us on Twitter",
1111
"reportIssue": "Gitpod: Report Issue",
1212
"stopWorkspace": "Gitpod: Stop Workspace",
13+
"showReleaseNote": "Gitpod: Show Release Note",
14+
"cleanReleaseNoteCache": "Gitpod: Debug Clean Release Note Cache",
1315
"upgradeSubscription": "Gitpod: Upgrade Subscription",
1416
"extendTimeout": "Gitpod: Extend Workspace Timeout",
1517
"takeSnapshot": "Gitpod: Share Workspace Snapshot",

extensions/gitpod-shared/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"prepare": "node scripts/inflate.js"
1313
},
1414
"devDependencies": {
15+
"@types/js-yaml": "^4.0.5",
1516
"@types/node": "16.x",
1617
"@types/uuid": "^8.3.1",
1718
"@types/ws": "^7.2.6"
@@ -20,8 +21,9 @@
2021
"@gitpod/gitpod-protocol": "main",
2122
"@gitpod/supervisor-api-grpc": "main",
2223
"bufferutil": "^4.0.1",
23-
"utf-8-validate": "^5.0.2",
24+
"js-yaml": "^4.1.0",
2425
"reconnecting-websocket": "^4.4.0",
26+
"utf-8-validate": "^5.0.2",
2527
"uuid": "^8.3.1",
2628
"vscode-nls": "^5.0.0",
2729
"ws": "^7.4.6",

extensions/gitpod-shared/src/extension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import * as vscode from 'vscode';
66
import { registerActiveLanguageAnalytics, registerUsageAnalytics } from './analytics';
77
import { createGitpodExtensionContext, GitpodExtensionContext, registerDefaultLayout, registerNotifications, registerWorkspaceCommands, registerWorkspaceSharing, registerWorkspaceTimeout } from './features';
8+
import { registerReleaseNoteView } from './releaseNote';
89

910
export { GitpodExtensionContext, registerTasks, SupervisorConnection, registerIpcHookCli } from './features';
1011
export * from './gitpod-plugin-model';
@@ -32,6 +33,7 @@ export async function setupGitpodContext(context: vscode.ExtensionContext): Prom
3233
registerWorkspaceTimeout(gitpodContext);
3334
registerNotifications(gitpodContext);
3435
registerDefaultLayout(gitpodContext);
36+
registerReleaseNoteView(gitpodContext);
3537
return gitpodContext;
3638
}
3739

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Gitpod. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import fetch from 'node-fetch';
7+
import * as vscode from 'vscode';
8+
import { load } from 'js-yaml';
9+
10+
const LAST_READ_RELEASE_DATE = 'gitpod:releaseNote';
11+
12+
export function registerReleaseNoteView(context: vscode.ExtensionContext) {
13+
context.subscriptions.push(
14+
vscode.commands.registerCommand('gitpod.releaseNote', () => {
15+
ReleaseNotePanel.createOrShow(context);
16+
})
17+
);
18+
19+
// TODO(hw): Remove
20+
context.subscriptions.push(
21+
vscode.commands.registerCommand('gitpod.cleanReleaseNoteCache', async () => {
22+
await context.globalState.update(LAST_READ_RELEASE_DATE, undefined);
23+
})
24+
);
25+
26+
const lastRead = context.globalState.get<string>(LAST_READ_RELEASE_DATE);
27+
shouldShowReleaseNote(lastRead).then(shouldShow => {
28+
if (shouldShow) {
29+
ReleaseNotePanel.createOrShow(context);
30+
}
31+
});
32+
}
33+
34+
async function getLastPublish() {
35+
// TODO(hw): fetch from somewhere
36+
return '2022-07-04';
37+
}
38+
39+
async function shouldShowReleaseNote(lastRead: string | undefined) {
40+
const date = await getLastPublish();
41+
console.log(`lastSeen: ${lastRead}, latest publish: ${date} => ${date !== lastRead ? 'show' : 'not-show'} ===============hwen.shouldShow`);
42+
return date !== lastRead;
43+
}
44+
45+
class ReleaseNotePanel {
46+
public static currentPanel: ReleaseNotePanel | undefined;
47+
public static readonly viewType = 'gitpodReleaseNote';
48+
private readonly panel: vscode.WebviewPanel;
49+
private lastRead: string | undefined;
50+
private _disposables: vscode.Disposable[] = [];
51+
52+
private async loadChangelog(date: string) {
53+
// TODO(hw): fetch from somewhere
54+
console.log(date, fetch, 'ignore');
55+
const resp = await fetch(`https://github.com/raw/gitpod-io/website/main/src/lib/contents/changelog/${date}.md`);
56+
if (!resp.ok) {
57+
throw new Error(`Getting GitHub account info failed: ${resp.statusText}`);
58+
}
59+
const md = await resp.text();
60+
61+
const parseInfo = (md: string) => {
62+
if (!md.startsWith('---')) {
63+
return;
64+
}
65+
const lines = md.split('\n');
66+
const end = lines.indexOf('---', 1);
67+
const content = lines.slice(1, end).join('\n');
68+
return load(content) as { title: string; date: string; image: string; alt: string; excerpt: string };
69+
};
70+
const info = parseInfo(md);
71+
72+
const content = md
73+
.replace(/---.*?---/gms, '')
74+
.replace(/<script>.*?<\/script>/gms, '')
75+
.replace(/<Badge.*?text="(.*?)".*?\/>/gim, '`$1`')
76+
.replace(/<Contributors usernames="(.*?)" \/>/gim, (_, p1) => {
77+
const users = p1
78+
.split(',')
79+
.map((e: string) => `[${e}](https://github.com/${e})`);
80+
return `Contributors: ${users.join(', ')}`;
81+
})
82+
.replace(/<p>(.*?)<\/p>/gm, '$1')
83+
.replace(/^[\n]+/m, '');
84+
if (!info) {
85+
return content;
86+
}
87+
88+
return [
89+
`# ${info.title}`,
90+
`> Published at ${date}, see also https://gitpod.io/changelog`,
91+
`![${info.alt ?? 'image'}](https://www.gitpod.io/images/changelog/${info.image})`,
92+
content,
93+
].join('\n\n');
94+
}
95+
96+
public async updateHtml(date?: string) {
97+
if (!date) {
98+
date = await getLastPublish();
99+
}
100+
const mdContent = await this.loadChangelog(date);
101+
const html = await vscode.commands.executeCommand('markdown.api.render', mdContent) as string;
102+
this.panel.webview.html = `<!DOCTYPE html>
103+
<html lang="en">
104+
<head>
105+
<meta charset="UTF-8">
106+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
107+
<title>Gitpod Release Note</title>
108+
<style>
109+
${DEFAULT_MARKDOWN_STYLES}
110+
</style>
111+
</head>
112+
<body>
113+
${html}
114+
</body>
115+
</html>`;
116+
if (!this.lastRead || date > this.lastRead) {
117+
await this.context.globalState.update(LAST_READ_RELEASE_DATE, date);
118+
this.lastRead = date;
119+
}
120+
}
121+
122+
public static createOrShow(context: vscode.ExtensionContext) {
123+
const column = vscode.window.activeTextEditor
124+
? vscode.window.activeTextEditor.viewColumn
125+
: undefined;
126+
127+
if (ReleaseNotePanel.currentPanel) {
128+
ReleaseNotePanel.currentPanel.panel.reveal(column);
129+
return;
130+
}
131+
132+
const panel = vscode.window.createWebviewPanel(
133+
ReleaseNotePanel.viewType,
134+
'Gitpod Release Note',
135+
column || vscode.ViewColumn.One,
136+
{ enableScripts: true },
137+
);
138+
139+
ReleaseNotePanel.currentPanel = new ReleaseNotePanel(context, panel);
140+
}
141+
142+
public static revive(context: vscode.ExtensionContext, panel: vscode.WebviewPanel) {
143+
ReleaseNotePanel.currentPanel = new ReleaseNotePanel(context, panel);
144+
}
145+
146+
private constructor(
147+
private readonly context: vscode.ExtensionContext,
148+
panel: vscode.WebviewPanel
149+
) {
150+
this.lastRead = this.context.globalState.get<string>(LAST_READ_RELEASE_DATE);
151+
this.panel = panel;
152+
153+
this.updateHtml();
154+
155+
this.panel.onDidDispose(() => this.dispose(), null, this._disposables);
156+
this.panel.onDidChangeViewState(
157+
() => {
158+
if (this.panel.visible) {
159+
this.updateHtml();
160+
}
161+
},
162+
null,
163+
this._disposables
164+
);
165+
}
166+
167+
public dispose() {
168+
ReleaseNotePanel.currentPanel = undefined;
169+
this.panel.dispose();
170+
while (this._disposables.length) {
171+
const x = this._disposables.pop();
172+
if (x) {
173+
x.dispose();
174+
}
175+
}
176+
}
177+
}
178+
179+
// Align with https://github.com/gitpod-io/openvscode-server/blob/494f7eba3615344ee634e6bec0b20a1903e5881d/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts#L14
180+
export const DEFAULT_MARKDOWN_STYLES = `
181+
body {
182+
padding: 10px 20px;
183+
line-height: 22px;
184+
max-width: 882px;
185+
margin: 0 auto;
186+
}
187+
188+
body *:last-child {
189+
margin-bottom: 0;
190+
}
191+
192+
img {
193+
max-width: 100%;
194+
max-height: 100%;
195+
}
196+
197+
a {
198+
text-decoration: none;
199+
}
200+
201+
a:hover {
202+
text-decoration: underline;
203+
}
204+
205+
a:focus,
206+
input:focus,
207+
select:focus,
208+
textarea:focus {
209+
outline: 1px solid -webkit-focus-ring-color;
210+
outline-offset: -1px;
211+
}
212+
213+
hr {
214+
border: 0;
215+
height: 2px;
216+
border-bottom: 2px solid;
217+
}
218+
219+
h1 {
220+
padding-bottom: 0.3em;
221+
line-height: 1.2;
222+
border-bottom-width: 1px;
223+
border-bottom-style: solid;
224+
}
225+
226+
h1, h2, h3 {
227+
font-weight: normal;
228+
}
229+
230+
table {
231+
border-collapse: collapse;
232+
}
233+
234+
table > thead > tr > th {
235+
text-align: left;
236+
border-bottom: 1px solid;
237+
}
238+
239+
table > thead > tr > th,
240+
table > thead > tr > td,
241+
table > tbody > tr > th,
242+
table > tbody > tr > td {
243+
padding: 5px 10px;
244+
}
245+
246+
table > tbody > tr + tr > td {
247+
border-top-width: 1px;
248+
border-top-style: solid;
249+
}
250+
251+
blockquote {
252+
margin: 0 7px 0 5px;
253+
padding: 0 16px 0 10px;
254+
border-left-width: 5px;
255+
border-left-style: solid;
256+
}
257+
258+
code {
259+
font-family: "SF Mono", Monaco, Menlo, Consolas, "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace;
260+
}
261+
262+
pre code {
263+
font-family: var(--vscode-editor-font-family);
264+
font-weight: var(--vscode-editor-font-weight);
265+
font-size: var(--vscode-editor-font-size);
266+
line-height: 1.5;
267+
}
268+
269+
code > div {
270+
padding: 16px;
271+
border-radius: 3px;
272+
overflow: auto;
273+
}
274+
275+
.monaco-tokenized-source {
276+
white-space: pre;
277+
}
278+
279+
/** Theming */
280+
281+
.vscode-light code > div {
282+
background-color: rgba(220, 220, 220, 0.4);
283+
}
284+
285+
.vscode-dark code > div {
286+
background-color: rgba(10, 10, 10, 0.4);
287+
}
288+
289+
.vscode-high-contrast code > div {
290+
background-color: var(--vscode-textCodeBlock-background);
291+
}
292+
293+
.vscode-high-contrast h1 {
294+
border-color: rgb(0, 0, 0);
295+
}
296+
297+
.vscode-light table > thead > tr > th {
298+
border-color: rgba(0, 0, 0, 0.69);
299+
}
300+
301+
.vscode-dark table > thead > tr > th {
302+
border-color: rgba(255, 255, 255, 0.69);
303+
}
304+
305+
.vscode-light h1,
306+
.vscode-light hr,
307+
.vscode-light table > tbody > tr + tr > td {
308+
border-color: rgba(0, 0, 0, 0.18);
309+
}
310+
311+
.vscode-dark h1,
312+
.vscode-dark hr,
313+
.vscode-dark table > tbody > tr + tr > td {
314+
border-color: rgba(255, 255, 255, 0.18);
315+
}
316+
317+
`;

extensions/gitpod-web/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@
4141
"title": "%stopWorkspace%",
4242
"enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true"
4343
},
44+
{
45+
"command": "gitpod.releaseNote",
46+
"title": "%showReleaseNote%",
47+
"enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true"
48+
},
49+
{
50+
"command": "gitpod.cleanReleaseNoteCache",
51+
"title": "%cleanReleaseNoteCache%",
52+
"enablement": "gitpod.inWorkspace == true && gitpod.workspaceOwned == true"
53+
},
4454
{
4555
"command": "gitpod.open.settings",
4656
"title": "%openSettings%",

extensions/gitpod-web/package.nls.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"openTwitter": "Gitpod: Follow us on Twitter",
2121
"reportIssue": "Gitpod: Report Issue",
2222
"stopWorkspace": "Gitpod: Stop Workspace",
23+
"showReleaseNote": "Gitpod: Show Release Note",
24+
"cleanReleaseNoteCache": "Gitpod: Debug Clean Release Note Cache",
2325
"upgradeSubscription": "Gitpod: Upgrade Subscription",
2426
"extendTimeout": "Gitpod: Extend Workspace Timeout",
2527
"takeSnapshot": "Gitpod: Share Workspace Snapshot",
@@ -28,4 +30,4 @@
2830
"openInStable": "Gitpod: Open in VS Code",
2931
"openInInsiders": "Gitpod: Open in VS Code Insiders",
3032
"openInBrowser": "Gitpod: Open in Browser"
31-
}
33+
}

0 commit comments

Comments
 (0)