Skip to content

Commit d386d3c

Browse files
feat: introduce VersionWelcomeDialog
1 parent 6a0efbe commit d386d3c

File tree

7 files changed

+170
-2
lines changed

7 files changed

+170
-2
lines changed

arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+9
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ import {
387387
import { TreeViewDecoratorService } from '@theia/plugin-ext/lib/main/browser/view/tree-view-decorator-service';
388388
import { PLUGIN_VIEW_DATA_FACTORY_ID } from '@theia/plugin-ext/lib/main/browser/view/plugin-view-registry';
389389
import { TreeViewWidget } from './theia/plugin-ext/tree-view-widget';
390+
import {
391+
VersionWelcomeDialog,
392+
VersionWelcomeDialogProps,
393+
} from './dialogs/version-welcome-dialog';
390394

391395
// Hack to fix copy/cut/paste issue after electron version update in Theia.
392396
// https://github.com/eclipse-theia/theia/issues/12487
@@ -1014,6 +1018,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
10141018
title: 'IDEUpdater',
10151019
});
10161020

1021+
bind(VersionWelcomeDialog).toSelf().inSingletonScope();
1022+
bind(VersionWelcomeDialogProps).toConstantValue({
1023+
title: 'VersionWelcomeDialog',
1024+
});
1025+
10171026
bind(UserFieldsDialog).toSelf().inSingletonScope();
10181027
bind(UserFieldsDialogProps).toConstantValue({
10191028
title: 'UserFields',

arduino-ide-extension/src/browser/contributions/check-for-ide-updates.ts

+43-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ import { LocalStorageService } from '@theia/core/lib/browser/storage-service';
33
import { inject, injectable } from '@theia/core/shared/inversify';
44
import {
55
IDEUpdater,
6+
LAST_USED_IDE_VERSION,
67
SKIP_IDE_VERSION,
78
} from '../../common/protocol/ide-updater';
89
import { IDEUpdaterDialog } from '../dialogs/ide-updater/ide-updater-dialog';
910
import { Contribution } from './contribution';
11+
import { VersionWelcomeDialog } from '../dialogs/version-welcome-dialog';
12+
import { AppService } from '../app-service';
13+
import { SemVer, valid as validSemVer } from 'semver';
1014

1115
@injectable()
1216
export class CheckForIDEUpdates extends Contribution {
@@ -16,9 +20,15 @@ export class CheckForIDEUpdates extends Contribution {
1620
@inject(IDEUpdaterDialog)
1721
private readonly updaterDialog: IDEUpdaterDialog;
1822

23+
@inject(VersionWelcomeDialog)
24+
private readonly versionWelcomeDialog: VersionWelcomeDialog;
25+
1926
@inject(LocalStorageService)
2027
private readonly localStorage: LocalStorageService;
2128

29+
@inject(AppService)
30+
private readonly appService: AppService;
31+
2232
override onStart(): void {
2333
this.preferences.onPreferenceChanged(
2434
({ preferenceName, newValue, oldValue }) => {
@@ -36,7 +46,9 @@ export class CheckForIDEUpdates extends Contribution {
3646
);
3747
}
3848

39-
override onReady(): void {
49+
override async onReady(): Promise<void> {
50+
await this.setLastUsedIDEVersion();
51+
4052
this.updater
4153
.init(
4254
this.preferences.get('arduino.ide.updateChannel'),
@@ -49,7 +61,14 @@ export class CheckForIDEUpdates extends Contribution {
4961
return this.updater.checkForUpdates(true);
5062
})
5163
.then(async (updateInfo) => {
52-
if (!updateInfo) return;
64+
if (!updateInfo) {
65+
const isNewVersion = await this.isRunningNewIDEVersion();
66+
if (isNewVersion) {
67+
this.setLastUsedIDEVersion(true);
68+
this.versionWelcomeDialog.open();
69+
}
70+
return;
71+
}
5372
const versionToSkip = await this.localStorage.getData<string>(
5473
SKIP_IDE_VERSION
5574
);
@@ -66,4 +85,26 @@ export class CheckForIDEUpdates extends Contribution {
6685
);
6786
});
6887
}
88+
89+
private async setLastUsedIDEVersion(force = false): Promise<void> {
90+
const { appVersion } = await this.appService.info();
91+
const lastUsedIDEVersion = await this.localStorage.getData<string>(
92+
LAST_USED_IDE_VERSION
93+
);
94+
if (validSemVer(appVersion) && (!lastUsedIDEVersion || force)) {
95+
this.localStorage.setData(LAST_USED_IDE_VERSION, appVersion);
96+
}
97+
}
98+
99+
private async isRunningNewIDEVersion(): Promise<boolean> {
100+
const { appVersion } = await this.appService.info();
101+
const prevVersion = await this.localStorage.getData<string>(
102+
LAST_USED_IDE_VERSION
103+
);
104+
try {
105+
return !!prevVersion && new SemVer(appVersion).compare(prevVersion) === 1;
106+
} catch (e) {
107+
return false;
108+
}
109+
}
69110
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React from '@theia/core/shared/react';
2+
import { inject, injectable } from '@theia/core/shared/inversify';
3+
import { Message } from '@theia/core/shared/@phosphor/messaging';
4+
import { ReactDialog } from '../theia/dialogs/dialogs';
5+
import { nls } from '@theia/core';
6+
import { DialogProps } from '@theia/core/lib/browser';
7+
import { WindowService } from '@theia/core/lib/browser/window/window-service';
8+
import { AppService } from '../app-service';
9+
10+
@injectable()
11+
export class VersionWelcomeDialogProps extends DialogProps {}
12+
13+
@injectable()
14+
export class VersionWelcomeDialog extends ReactDialog<void> {
15+
// @inject(LocalStorageService)
16+
// private readonly localStorageService: LocalStorageService;
17+
18+
@inject(AppService)
19+
private readonly appService: AppService;
20+
21+
@inject(WindowService)
22+
private readonly windowService: WindowService;
23+
24+
constructor(
25+
@inject(VersionWelcomeDialogProps)
26+
protected override readonly props: VersionWelcomeDialogProps
27+
) {
28+
super({
29+
title: nls.localize(
30+
'arduino/versionWelcome/versionWelcomeDialog',
31+
'Welcome to the new Arduino IDE!'
32+
),
33+
});
34+
35+
this.node.id = 'version-welcome-dialog-container';
36+
this.contentNode.classList.add('version-welcome-dialog');
37+
}
38+
39+
protected render(): React.ReactNode {
40+
return (
41+
<div>
42+
<p>
43+
{nls.localize(
44+
'arduino/versionWelcome/donateMessage',
45+
'Arduino is committed to keeping software free and open-source for everyone. Your donation helps us develop new features, improve libraries, and support millions of users worldwide.'
46+
)}
47+
</p>
48+
<p className="bold">
49+
{nls.localize(
50+
'arduino/versionWelcome/donateMessage2',
51+
'Please consider supporting our efforts to keep Arduino IDE free.'
52+
)}
53+
</p>
54+
</div>
55+
);
56+
}
57+
58+
override get value(): void {
59+
return;
60+
}
61+
62+
private appendButtons(): void {
63+
const cancelButton = this.createButton(
64+
nls.localize('arduino/versionWelcome/cancelButton', 'Maybe later')
65+
);
66+
cancelButton.classList.add('secondary');
67+
cancelButton.classList.add('cancel-button');
68+
this.addAction(cancelButton, this.close.bind(this), 'click');
69+
this.controlPanel.appendChild(cancelButton);
70+
71+
const donateButton = this.createButton(
72+
nls.localize('arduino/versionWelcome/donateButton', 'Donate now')
73+
);
74+
this.addAction(donateButton, this.openDonationPage.bind(this), 'click');
75+
this.controlPanel.appendChild(donateButton);
76+
donateButton.focus();
77+
}
78+
79+
private readonly openDonationPage = () => {
80+
const url = 'https://www.arduino.cc/en/donate';
81+
this.windowService.openNewWindow(url, { external: true });
82+
};
83+
84+
// FIXME: AppInfo is not available in the browser?
85+
private async updateTitleVersion(): Promise<void> {
86+
const appInfo = await this.appService.info();
87+
const { appVersion } = appInfo;
88+
const title = nls.localize(
89+
'arduino/versionWelcome/versionWelcomeDialog',
90+
`Welcome to the new Arduino IDE ${appVersion}!`,
91+
appVersion
92+
);
93+
this.titleNode.innerHTML = title;
94+
}
95+
96+
protected override onAfterAttach(msg: Message): void {
97+
this.update();
98+
this.appendButtons();
99+
this.updateTitleVersion();
100+
super.onAfterAttach(msg);
101+
}
102+
}

arduino-ide-extension/src/browser/style/index.css

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
@import "./settings-dialog.css";
1111
@import "./firmware-uploader-dialog.css";
1212
@import "./ide-updater-dialog.css";
13+
@import "./version-welcome-dialog.css";
1314
@import "./certificate-uploader-dialog.css";
1415
@import "./user-fields-dialog.css";
1516
@import "./debug.css";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#version-welcome-dialog-container > .dialogBlock {
2+
width: 546px;
3+
4+
.bold {
5+
font-weight: bold;
6+
}
7+
}

arduino-ide-extension/src/common/protocol/ide-updater.ts

+1
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,4 @@ export interface IDEUpdaterClient {
7171
}
7272

7373
export const SKIP_IDE_VERSION = 'skipIDEVersion';
74+
export const LAST_USED_IDE_VERSION = 'lastUsedIDEVersion';

i18n/en.json

+7
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,13 @@
528528
"renameSketchFolderMessage": "The sketch '{0}' cannot be used. {1} To get rid of this message, rename the sketch. Do you want to rename the sketch now?",
529529
"renameSketchFolderTitle": "Invalid sketch name"
530530
},
531+
"versionWelcome": {
532+
"cancelButton": "Maybe later",
533+
"donateButton": "Donate now",
534+
"donateMessage": "Arduino is committed to keeping software free and open-source for everyone. Your donation helps us develop new features, improve libraries, and support millions of users worldwide.",
535+
"donateMessage2": "Please consider supporting our efforts to keep Arduino IDE free.",
536+
"versionWelcomeDialog": "Welcome to Arduino IDE '{0}'!."
537+
},
531538
"workspace": {
532539
"alreadyExists": "'{0}' already exists."
533540
}

0 commit comments

Comments
 (0)