Skip to content

[ATL-813] Notify user when IDE new version is available #422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"panel": "new",
"clear": false
}
}
},
{
"label": "Arduino IDE - Watch Browser App",
"type": "shell",
Expand Down
5 changes: 3 additions & 2 deletions arduino-ide-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"@theia/monaco": "next",
"@theia/navigator": "next",
"@theia/outline-view": "next",
"@theia/preferences": "next",
"@theia/output": "next",
"@theia/preferences": "next",
"@theia/search-in-workspace": "next",
"@theia/terminal": "next",
"@theia/workspace": "next",
Expand All @@ -48,14 +48,15 @@
"@types/which": "^1.3.1",
"ajv": "^6.5.3",
"async-mutex": "^0.3.0",
"axios": "^0.21.1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlbyIanna I love axios, but are we sure we want to add another dependency when we have something somehow similar? ("request": "^2.82.0" should be included already)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you're right. I initially decided to use axios before the API was returning 403 and using request I couldn't handle the response properly, but now the API is not returning 403 anymore so I can change this.

"css-element-queries": "^1.2.0",
"dateformat": "^3.0.3",
"deepmerge": "^4.2.2",
"fuzzy": "^0.1.3",
"glob": "^7.1.6",
"google-protobuf": "^3.11.4",
"lodash.debounce": "^4.0.8",
"js-yaml": "^3.13.1",
"lodash.debounce": "^4.0.8",
"ncp": "^2.0.0",
"p-queue": "^5.0.0",
"ps-tree": "^1.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ import { NotificationManager } from './theia/messages/notifications-manager';
import { NotificationManager as TheiaNotificationManager } from '@theia/messages/lib/browser/notifications-manager';
import { NotificationsRenderer as TheiaNotificationsRenderer } from '@theia/messages/lib/browser/notifications-renderer';
import { NotificationsRenderer } from './theia/messages/notifications-renderer';
import { NewVersionNotification } from './contributions/new-version-notification'
import { UpdatesRetriever } from './updates/updates-retriever';

const ElementQueries = require('css-element-queries/src/ElementQueries');

Expand Down Expand Up @@ -653,4 +655,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
rebind(TheiaNotificationManager).toService(NotificationManager);
bind(NotificationsRenderer).toSelf().inSingletonScope();
rebind(TheiaNotificationsRenderer).toService(NotificationsRenderer);

bind(NewVersionNotification).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(NewVersionNotification);

bind(UpdatesRetriever).toSelf().inSingletonScope();
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { BoardsDataStore } from './boards-data-store';
import { MainMenuManager } from '../../common/main-menu-manager';
import { ArduinoMenus, unregisterSubmenu } from '../menu/arduino-menus';

@injectable()
@injectable()
export class BoardsDataMenuUpdater implements FrontendApplicationContribution {
@inject(CommandRegistry)
protected readonly commandRegistry: CommandRegistry;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { injectable, inject } from 'inversify';
import { MessageService } from '@theia/core/lib/common/message-service';
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
import { UpdatesRetriever } from '../updates/updates-retriever';
import { shell } from 'electron';

const GO_TO_DOWNLOAD_PAGE = 'Go to download page...';
/**
* Listens on `BoardsConfig.Config` changes, if a board is selected which does not
* have the corresponding core installed, it proposes the user to install the core.
*/
@injectable()
export class NewVersionNotification implements FrontendApplicationContribution {
@inject(UpdatesRetriever)
private readonly updatesRetriever: UpdatesRetriever;

@inject(MessageService)
protected readonly messageService: MessageService;

async onStart(): Promise<void> {
if (await this.updatesRetriever.isUpdateAvailable()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await will block the app startup for the fetch time. It would be better to do this.updatesRetriever.isUpdateAvailable.then(available -> ). What do you think?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fstasi @AlbyIanna
please have a look at @kittaakos 's suggestion

this.messageService.info('New Arduino IDE version available.', GO_TO_DOWNLOAD_PAGE).then(async answer => {
if (answer === GO_TO_DOWNLOAD_PAGE) {
shell.openExternal('https://www.arduino.cc/en/software#experimental-software');
}
})
}
}
}
37 changes: 37 additions & 0 deletions arduino-ide-extension/src/browser/updates/updates-retriever.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import axios from 'axios';
import { injectable } from 'inversify';
import * as os from 'os';
import { compare } from 'semver';
import { remote } from 'electron';

const BASE_URL = 'https://downloads.arduino.cc';
const LATEST_LOCATION_PARTIAL_URL = `${BASE_URL}/latest-location/arduino-ide/arduino-ide_latest_`;
const LATEST_VERSION_PARTIAL_URL = `${BASE_URL}/arduino-ide/arduino-ide_`;

@injectable()
export class UpdatesRetriever {
public async isUpdateAvailable(): Promise<boolean> {
let filename;
switch (os.type()) {
case 'Linux':
filename = 'Linux_64bit.zip';
break;
case 'Darwin':
filename = 'macOS_64bit.dmg';
break;
case 'Windows_NT':
filename = 'Windows_64bit.exe';
break;
default:
return false;
}
const response = await axios.head(`${LATEST_LOCATION_PARTIAL_URL}${filename}`)
const location = (response.headers?.location as String);
if (location && location.startsWith(LATEST_VERSION_PARTIAL_URL)) {
const latestVersion = location.split('_')[1];
const version = await remote.app.getVersion();
return compare(latestVersion, version) === 1;
}
return false;
}
}