Notify IDE users about new daml-driven blog posts (#3623)

* Successfully parse rss xml and find latest blog post object

* Show notification with link to blog (on every ide startup...)

* Only show blog post if not seen before

* Formatting

CHANGELOG_BEGIN

- [SDK] Notify IDE users about new daml-driven blog posts

CHANGELOG_END

* Add setting for user to opt out of notifications

* Use await rather than then

* Catch and swallow exceptions

* Another await and minor cleanup
This commit is contained in:
Rohan Jacob-Rao 2019-11-26 14:34:56 -05:00 committed by mergify[bot]
parent 4d922e763b
commit 094214aa55
3 changed files with 191 additions and 9 deletions

View File

@ -107,6 +107,11 @@
"default": "From consent popup",
"description": "Controls whether you send DAML usage data to Digital Asset"
},
"daml.showNewBlogPosts": {
"type": "boolean",
"default": true,
"description": "Notify when new DAML Driven blog posts are available"
},
"daml.extraArguments": {
"type": "string",
"default": "",
@ -138,11 +143,13 @@
"@types/node-fetch": "^2.5.3",
"@types/tmp": "0.0.29",
"@types/which": "1.3.1",
"@types/xml2js": "^0.4.5",
"fp-ts": "^2.1.1",
"node-fetch": "^2.6.0",
"tmp": "0.0.29",
"vscode-languageclient": "6.0.0-next.1",
"which": "1.3.1"
"which": "1.3.1",
"xml2js": "^0.4.22"
},
"devDependencies": {
"@bazel/hide-bazel-files": "0.32.2",

View File

@ -17,10 +17,12 @@ import * as util from 'util';
import fetch, { Response } from 'node-fetch';
import { getOrd } from 'fp-ts/lib/Array';
import { ordNumber } from 'fp-ts/lib/Ord';
import { parseStringPromise } from 'xml2js';
let damlRoot: string = path.join(os.homedir(), '.daml');
const versionContextKey = 'version'
const recentBlogContextKey = 'lastSeenBlog'
var damlLanguageClient: LanguageClient;
// Extension activation
@ -33,8 +35,10 @@ export async function activate(context: vscode.ExtensionContext) {
// Get telemetry consent
const consent = getTelemetryConsent(config, context);
// Check extension version to display release notes on updates
// Display release notes on updates
showReleaseNotesIfNewVersion(context);
// Notify about new blog posts
showBlogIfNotSeen(config, context);
damlLanguageClient = createLanguageClient(config, await consent);
damlLanguageClient.registerProposedFeatures();
@ -113,7 +117,7 @@ async function showReleaseNotesIfNewVersion(context: ExtensionContext) {
// the next update.
if (typeof extensionVersion === 'string' && extensionVersion !== '' &&
(!recordedVersion || typeof recordedVersion === 'string' && checkVersionUpgrade(recordedVersion, extensionVersion))) {
showReleaseNotes(extensionVersion);
await showReleaseNotes(extensionVersion);
await context.globalState.update(versionContextKey, extensionVersion);
}
}
@ -132,19 +136,49 @@ function checkVersionUpgrade(version1: string, version2: string) {
// We display the HTML in a new editor tab using a "webview":
// https://code.visualstudio.com/api/extension-guides/webview
async function showReleaseNotes(version: string) {
const releaseNotesUrl = 'https://blog.daml.com/release-notes/';
const url = releaseNotesUrl + version;
fetch(url).then(async (result: Response) => {
if (result.ok) {
try {
const releaseNotesUrl = 'https://blog.daml.com/release-notes/' + version;
const res = await fetch(releaseNotesUrl);
if (res.ok) {
const panel = vscode.window.createWebviewPanel(
'releaseNotes', // Identifies the type of the webview. Used internally
`New DAML SDK ${version} Available`, // Title of the panel displayed to the user
vscode.ViewColumn.One, // Editor column to show the new webview panel in
{} // No webview options for now
);
panel.webview.html = await result.text();
panel.webview.html = await res.text();
}
});
} catch (_error) {}
}
// Check if there is a new blog post which the user has not yet seen.
// If so, display a notification with the link to the new post.
// Update the user state so we don't notify about the same blog post again.
// The user can opt out of these notifications entirely by changing the
// 'daml.showNewBlogPosts' setting.
async function showBlogIfNotSeen(config: WorkspaceConfiguration, context: ExtensionContext) {
if (!config.get('showNewBlogPosts')) { return; }
try {
const feedUrl = 'https://blog.daml.com/daml-driven/rss.xml';
const res = await fetch(feedUrl);
if (res.ok) {
const rssXml = await res.text();
const rss = await parseStringPromise(rssXml);
const latestBlog = rss.rss.channel[0].item[0];
const lastSeenBlog = context.globalState.get(recentBlogContextKey);
if (latestBlog &&
(!lastSeenBlog || typeof lastSeenBlog === 'string' && lastSeenBlog !== latestBlog.title)) {
const clicked = await window.showInformationMessage(
`New blog post: ${latestBlog.title}`,
'Go to blog'
);
if (clicked === 'Go to blog') {
env.openExternal(Uri.parse(latestBlog.link));
}
await context.globalState.update(recentBlogContextKey, latestBlog.title);
}
}
} catch (_error) {}
}
function getViewColumnForShowResource(): ViewColumn {

View File

@ -39,6 +39,13 @@
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.1.tgz#7802c380887986ca909008afea4e08025b130f8d"
integrity sha512-ZrJDWpvg75LTGX4XwuneY9s6bF3OeZcGTpoGh3zDV9ytzcHMFsRrMIaLBRJZQMBoGyKs6unBQfVdrLZiYfb1zQ==
"@types/xml2js@^0.4.5":
version "0.4.5"
resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.5.tgz#d21759b056f282d9c7066f15bbf5c19b908f22fa"
integrity sha512-yohU3zMn0fkhlape1nxXG2bLEGZRc1FeqF80RoHaYXJN7uibaauXfhzhOJr1Xh36sn+/tx21QAOf07b/xYVk1w==
dependencies:
"@types/node" "*"
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@ -144,6 +151,13 @@ css-what@2.1:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
define-properties@^1.1.2, define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
dependencies:
object-keys "^1.0.12"
denodeify@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
@ -195,6 +209,31 @@ entities@^1.1.1, entities@~1.1.1:
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
es-abstract@^1.5.1:
version "1.16.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d"
integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==
dependencies:
es-to-primitive "^1.2.0"
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.0"
is-callable "^1.1.4"
is-regex "^1.0.4"
object-inspect "^1.6.0"
object-keys "^1.1.1"
string.prototype.trimleft "^2.1.0"
string.prototype.trimright "^2.1.0"
es-to-primitive@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
dependencies:
is-callable "^1.1.4"
is-date-object "^1.0.1"
is-symbol "^1.0.2"
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
@ -217,6 +256,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
glob@^7.0.6:
version "7.1.4"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
@ -234,6 +278,18 @@ has-flag@^3.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
has-symbols@^1.0.0, has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
has@^1.0.1, has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
htmlparser2@^3.9.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
@ -259,6 +315,30 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
dependencies:
has "^1.0.1"
is-symbol@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
dependencies:
has-symbols "^1.0.1"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -321,6 +401,24 @@ nth-check@~1.0.1:
dependencies:
boolbase "~1.0.0"
object-inspect@^1.6.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
object.getownpropertydescriptors@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=
dependencies:
define-properties "^1.1.2"
es-abstract "^1.5.1"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@ -396,6 +494,11 @@ safe-buffer@~5.1.0:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
semver@^5.1.0:
version "5.7.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
@ -411,6 +514,22 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
string.prototype.trimleft@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634"
integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==
dependencies:
define-properties "^1.1.3"
function-bind "^1.1.1"
string.prototype.trimright@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58"
integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==
dependencies:
define-properties "^1.1.3"
function-bind "^1.1.1"
string_decoder@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
@ -470,6 +589,14 @@ util-deprecate@^1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
util.promisify@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
dependencies:
define-properties "^1.1.2"
object.getownpropertydescriptors "^2.0.3"
vsce@1.66.0:
version "1.66.0"
resolved "https://registry.yarnpkg.com/vsce/-/vsce-1.66.0.tgz#8cf1d64a4825d5d0523ea5efd0bf41e2c6829565"
@ -534,6 +661,20 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xml2js@^0.4.22:
version "0.4.22"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02"
integrity sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==
dependencies:
sax ">=0.6.0"
util.promisify "~1.0.0"
xmlbuilder "~11.0.0"
xmlbuilder@~11.0.0:
version "11.0.1"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
yauzl@^2.3.1:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"