diff --git a/vscode/powershellprotools/package-lock.json b/vscode/powershellprotools/package-lock.json index 887b760..1c0314a 100644 --- a/vscode/powershellprotools/package-lock.json +++ b/vscode/powershellprotools/package-lock.json @@ -8,6 +8,7 @@ "name": "powershellprotools", "version": "2024.7.5", "dependencies": { + "axios": "^0.21.1", "cheerio": "^1.0.0-rc.2", "extract-zip": "^2.0.1", "json-rpc2": "^2.0.0", @@ -115,6 +116,14 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -681,6 +690,25 @@ "pend": "~1.2.0" } }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1318,6 +1346,14 @@ "sprintf-js": "~1.0.2" } }, + "axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "requires": { + "follow-redirects": "^1.14.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1688,6 +1724,11 @@ "pend": "~1.2.0" } }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", diff --git a/vscode/powershellprotools/package.json b/vscode/powershellprotools/package.json index db63c70..a7e2de1 100644 --- a/vscode/powershellprotools/package.json +++ b/vscode/powershellprotools/package.json @@ -2,7 +2,7 @@ "name": "powershellprotools", "displayName": "PowerShell Pro Tools", "description": "Powerful extensions for PowerShell development.", - "version": "2024.7.5", + "version": "2024.7.6", "publisher": "ironmansoftware", "repository": { "type": "git", @@ -29,6 +29,7 @@ "onView:customView", "onView:historyView", "onView:sessionsView", + "onView:newsView", "onView:jobView", "onCommand:powershell.showWinFormDesigner", "onCommand:powershell.generateWinForm", @@ -145,6 +146,11 @@ "title": "Refresh", "icon": "$(refresh)" }, + { + "command": "newsView.refresh", + "title": "Refresh", + "icon": "$(refresh)" + }, { "command": "providerView.refresh", "title": "Refresh", @@ -359,6 +365,11 @@ "command": "jobView.refresh", "title": "Refresh", "icon": "$(refresh)" + }, + { + "command": "newsView.open", + "title": "Open", + "icon": "$(link-external)" } ], "configuration": { @@ -509,6 +520,11 @@ "type": "boolean", "default": true, "markdownDescription": "Whether to clear the terminal after loading PowerShell Pro Tools. Set to false to see any errors loading the module." + }, + "poshProTools.disableNewsNotification": { + "type": "boolean", + "default": false, + "markdownDescription": "Disables the notification when Ironman Software publishes news." } } }, @@ -603,6 +619,10 @@ { "id": "infoView", "name": "Help and Information" + }, + { + "id": "newsView", + "name": "What's New?" } ] }, @@ -630,6 +650,11 @@ "when": "view == moduleView", "group": "navigation" }, + { + "command": "newsView.refresh", + "when": "view == newsView", + "group": "navigation" + }, { "command": "providerView.refresh", "when": "view == providerView", @@ -840,6 +865,7 @@ "typescript": "^4.0.2" }, "dependencies": { + "axios": "^0.21.1", "cheerio": "^1.0.0-rc.2", "extract-zip": "^2.0.1", "json-rpc2": "^2.0.0", diff --git a/vscode/powershellprotools/src/commands/news.ts b/vscode/powershellprotools/src/commands/news.ts new file mode 100644 index 0000000..1b48f99 --- /dev/null +++ b/vscode/powershellprotools/src/commands/news.ts @@ -0,0 +1,42 @@ +'use strict'; +import * as vscode from 'vscode'; +import { ICommand } from './command'; +import axios from 'axios'; +import { load } from '../settings'; + +export class NewsTreeViewCommands implements ICommand { + register(context: vscode.ExtensionContext) { + context.subscriptions.push(this.Open()); + } + + Open() { + return vscode.commands.registerCommand('newsView.open', async (url) => { + vscode.env.openExternal(vscode.Uri.parse(url)); + }) + } +} + +export async function notifyAboutNews(context: vscode.ExtensionContext) { + var settings = load(); + if (settings.disableNewsNotification) { + return; + } + + var result = await axios({ url: 'https://www.ironmansoftware.com/news/api' }); + var news = result.data; + + if (news.length > 0) { + var latestNews = news[0]; + var id = context.globalState.get("PSPNewsId"); + if (id == latestNews.id) { + return; + } + + vscode.window.showInformationMessage("Ironman Software News - " + latestNews.title + " - " + latestNews.description, "View").then((result) => { + if (result == "View") { + vscode.env.openExternal(vscode.Uri.parse(latestNews.url)); + context.globalState.update("PSPNewsId", latestNews.id); + } + }); + } +} \ No newline at end of file diff --git a/vscode/powershellprotools/src/container.ts b/vscode/powershellprotools/src/container.ts index 842c1c4..e36d02a 100644 --- a/vscode/powershellprotools/src/container.ts +++ b/vscode/powershellprotools/src/container.ts @@ -21,6 +21,7 @@ import { HistoryTreeViewCommands } from './commands/history'; import { SessionCommands } from './commands/sessions'; import { JobTreeViewCommands } from './commands/jobs'; import { PerformanceService } from './services/performanceService'; +import { NewsTreeViewCommands } from './commands/news'; export class Container { static initialize(context: ExtensionContext, powershellService: PowerShellService) { @@ -40,6 +41,7 @@ export class Container { this._commands.push(new HistoryTreeViewCommands()); this._commands.push(new SessionCommands()); this._commands.push(new JobTreeViewCommands()); + this._commands.push(new NewsTreeViewCommands()); this.RegisterCommands(); //this._codeLensProvider = new PowerShellCodeLensProvider(); diff --git a/vscode/powershellprotools/src/extension.ts b/vscode/powershellprotools/src/extension.ts index 442e329..9ce9f48 100644 --- a/vscode/powershellprotools/src/extension.ts +++ b/vscode/powershellprotools/src/extension.ts @@ -26,6 +26,8 @@ import { SessionTreeViewProvider } from './treeView/sessionTreeView'; import { JobTreeViewProvider } from './treeView/jobTreeView'; import { PowerShellRenameProvider } from './services/renameProvider'; import { registerWelcomeCommands } from './commands/welcomeCommand'; +import { NewsViewProvider } from './treeView/newsTreeView'; +import { notifyAboutNews } from './commands/news'; const version = "PowerShellProTools.Version"; @@ -48,6 +50,7 @@ export interface IPowerShellExtensionClient { export async function activate(context: vscode.ExtensionContext) { + notifyAboutNews(context); var service = powerShellService = new PowerShellService(context); context.subscriptions.push(showDataGrid(context)); context.subscriptions.push(packageAsExe()); @@ -125,6 +128,7 @@ async function finishActivation(context: vscode.ExtensionContext) { vscode.window.createTreeView('astView', { treeDataProvider: new AstTreeViewProvider() }); vscode.window.createTreeView('hostProcessView', { treeDataProvider: new HostProcessViewProvider() }); vscode.window.createTreeView('moduleView', { treeDataProvider: new ModuleViewProvider() }); + vscode.window.createTreeView('newsView', { treeDataProvider: new NewsViewProvider() }); vscode.window.createTreeView('providerView', { treeDataProvider: new ProviderViewProvider() }); vscode.window.createTreeView('quickScriptView', { treeDataProvider: new QuickScriptViewProvider() }); vscode.window.createTreeView('variableView', { treeDataProvider: new VariableViewProvider() }); diff --git a/vscode/powershellprotools/src/settings.ts b/vscode/powershellprotools/src/settings.ts index 8375e8d..ba24ea0 100644 --- a/vscode/powershellprotools/src/settings.ts +++ b/vscode/powershellprotools/src/settings.ts @@ -18,6 +18,7 @@ export interface ISettings { signOnSaveCertificate: string; excludeAutomaticVariables: boolean; clearScreenAfterLoad: boolean; + disableNewsNotification: boolean; } export function load(): ISettings { @@ -38,6 +39,7 @@ export function load(): ISettings { signOnSave: configuration.get("signOnSave", false), signOnSaveCertificate: configuration.get("signOnSaveCertificate", ""), excludeAutomaticVariables: configuration.get("excludeAutomaticVariables", false), - clearScreenAfterLoad: configuration.get("clearScreenAfterLoad", true) + clearScreenAfterLoad: configuration.get("clearScreenAfterLoad", true), + disableNewsNotification: configuration.get("disableNewsNotification", false) } } diff --git a/vscode/powershellprotools/src/treeView/newsTreeView.ts b/vscode/powershellprotools/src/treeView/newsTreeView.ts new file mode 100644 index 0000000..7e3b53e --- /dev/null +++ b/vscode/powershellprotools/src/treeView/newsTreeView.ts @@ -0,0 +1,31 @@ +import * as vscode from 'vscode'; +import { TreeViewProvider } from './treeViewProvider'; +import axios from 'axios'; + +export class NewsViewProvider extends TreeViewProvider { + getRefreshCommand(): string { + return "newsView.refresh"; + } + + requiresLicense(): boolean { + return false; + } + + async getNodes(): Promise { + var result = await axios({ url: 'https://www.ironmansoftware.com/news/api' }); + var news = result.data; + return news.map((news: any) => { + return { + label: news.title, + iconPath: new vscode.ThemeIcon('sparkle-filled'), + tooltip: news.description, + collapsibleState: vscode.TreeItemCollapsibleState.None, + command: { + title: 'open', + command: 'newsView.open', + arguments: [news.url] + } + }; + }); + } +} \ No newline at end of file