mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-06-13 15:46:34 +00:00
feat: introduce VersionWelcomeDialog
Show donate dialog after the first time a first IDE version is loaded
This commit is contained in:
parent
71b11ed829
commit
4788bfbc3f
@ -387,6 +387,10 @@ import {
|
|||||||
import { TreeViewDecoratorService } from '@theia/plugin-ext/lib/main/browser/view/tree-view-decorator-service';
|
import { TreeViewDecoratorService } from '@theia/plugin-ext/lib/main/browser/view/tree-view-decorator-service';
|
||||||
import { PLUGIN_VIEW_DATA_FACTORY_ID } from '@theia/plugin-ext/lib/main/browser/view/plugin-view-registry';
|
import { PLUGIN_VIEW_DATA_FACTORY_ID } from '@theia/plugin-ext/lib/main/browser/view/plugin-view-registry';
|
||||||
import { TreeViewWidget } from './theia/plugin-ext/tree-view-widget';
|
import { TreeViewWidget } from './theia/plugin-ext/tree-view-widget';
|
||||||
|
import {
|
||||||
|
VersionWelcomeDialog,
|
||||||
|
VersionWelcomeDialogProps,
|
||||||
|
} from './dialogs/version-welcome-dialog';
|
||||||
|
|
||||||
// Hack to fix copy/cut/paste issue after electron version update in Theia.
|
// Hack to fix copy/cut/paste issue after electron version update in Theia.
|
||||||
// https://github.com/eclipse-theia/theia/issues/12487
|
// https://github.com/eclipse-theia/theia/issues/12487
|
||||||
@ -1014,6 +1018,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|||||||
title: 'IDEUpdater',
|
title: 'IDEUpdater',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bind(VersionWelcomeDialog).toSelf().inSingletonScope();
|
||||||
|
bind(VersionWelcomeDialogProps).toConstantValue({
|
||||||
|
title: 'VersionWelcomeDialog',
|
||||||
|
});
|
||||||
|
|
||||||
bind(UserFieldsDialog).toSelf().inSingletonScope();
|
bind(UserFieldsDialog).toSelf().inSingletonScope();
|
||||||
bind(UserFieldsDialogProps).toConstantValue({
|
bind(UserFieldsDialogProps).toConstantValue({
|
||||||
title: 'UserFields',
|
title: 'UserFields',
|
||||||
|
@ -3,10 +3,14 @@ import { LocalStorageService } from '@theia/core/lib/browser/storage-service';
|
|||||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||||
import {
|
import {
|
||||||
IDEUpdater,
|
IDEUpdater,
|
||||||
|
LAST_USED_IDE_VERSION,
|
||||||
SKIP_IDE_VERSION,
|
SKIP_IDE_VERSION,
|
||||||
} from '../../common/protocol/ide-updater';
|
} from '../../common/protocol/ide-updater';
|
||||||
import { IDEUpdaterDialog } from '../dialogs/ide-updater/ide-updater-dialog';
|
import { IDEUpdaterDialog } from '../dialogs/ide-updater/ide-updater-dialog';
|
||||||
import { Contribution } from './contribution';
|
import { Contribution } from './contribution';
|
||||||
|
import { VersionWelcomeDialog } from '../dialogs/version-welcome-dialog';
|
||||||
|
import { AppService } from '../app-service';
|
||||||
|
import { SemVer } from 'semver';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class CheckForIDEUpdates extends Contribution {
|
export class CheckForIDEUpdates extends Contribution {
|
||||||
@ -16,9 +20,15 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
@inject(IDEUpdaterDialog)
|
@inject(IDEUpdaterDialog)
|
||||||
private readonly updaterDialog: IDEUpdaterDialog;
|
private readonly updaterDialog: IDEUpdaterDialog;
|
||||||
|
|
||||||
|
@inject(VersionWelcomeDialog)
|
||||||
|
private readonly versionWelcomeDialog: VersionWelcomeDialog;
|
||||||
|
|
||||||
@inject(LocalStorageService)
|
@inject(LocalStorageService)
|
||||||
private readonly localStorage: LocalStorageService;
|
private readonly localStorage: LocalStorageService;
|
||||||
|
|
||||||
|
@inject(AppService)
|
||||||
|
private readonly appService: AppService;
|
||||||
|
|
||||||
override onStart(): void {
|
override onStart(): void {
|
||||||
this.preferences.onPreferenceChanged(
|
this.preferences.onPreferenceChanged(
|
||||||
({ preferenceName, newValue, oldValue }) => {
|
({ preferenceName, newValue, oldValue }) => {
|
||||||
@ -36,7 +46,7 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
override onReady(): void {
|
override async onReady(): Promise<void> {
|
||||||
this.updater
|
this.updater
|
||||||
.init(
|
.init(
|
||||||
this.preferences.get('arduino.ide.updateChannel'),
|
this.preferences.get('arduino.ide.updateChannel'),
|
||||||
@ -49,7 +59,13 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
return this.updater.checkForUpdates(true);
|
return this.updater.checkForUpdates(true);
|
||||||
})
|
})
|
||||||
.then(async (updateInfo) => {
|
.then(async (updateInfo) => {
|
||||||
if (!updateInfo) return;
|
if (!updateInfo) {
|
||||||
|
const isNewVersion = await this.isNewStableVersion();
|
||||||
|
if (isNewVersion) {
|
||||||
|
this.versionWelcomeDialog.open();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
const versionToSkip = await this.localStorage.getData<string>(
|
const versionToSkip = await this.localStorage.getData<string>(
|
||||||
SKIP_IDE_VERSION
|
SKIP_IDE_VERSION
|
||||||
);
|
);
|
||||||
@ -64,6 +80,44 @@ export class CheckForIDEUpdates extends Contribution {
|
|||||||
e.message
|
e.message
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.setCurrentIDEVersion();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async setCurrentIDEVersion(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const { appVersion } = await this.appService.info();
|
||||||
|
const currSemVer = new SemVer(appVersion ?? '');
|
||||||
|
this.localStorage.setData(LAST_USED_IDE_VERSION, currSemVer.format());
|
||||||
|
} catch {
|
||||||
|
// ignore invalid versions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user is running a new IDE version for the first time.
|
||||||
|
* @returns true if the current IDE version is greater than the last used version
|
||||||
|
* and both are non-prerelease versions.
|
||||||
|
*/
|
||||||
|
private async isNewStableVersion(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const { appVersion } = await this.appService.info();
|
||||||
|
const prevVersion = await this.localStorage.getData<string>(
|
||||||
|
LAST_USED_IDE_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
const prevSemVer = new SemVer(prevVersion ?? '');
|
||||||
|
const currSemVer = new SemVer(appVersion ?? '');
|
||||||
|
|
||||||
|
if (prevSemVer.prerelease.length || currSemVer.prerelease.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currSemVer.compare(prevSemVer) === 1;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
import React from '@theia/core/shared/react';
|
||||||
|
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||||
|
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||||
|
import { ReactDialog } from '../theia/dialogs/dialogs';
|
||||||
|
import { nls } from '@theia/core';
|
||||||
|
import { DialogProps } from '@theia/core/lib/browser';
|
||||||
|
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||||
|
import { AppService } from '../app-service';
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class VersionWelcomeDialogProps extends DialogProps {}
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class VersionWelcomeDialog extends ReactDialog<void> {
|
||||||
|
@inject(AppService)
|
||||||
|
private readonly appService: AppService;
|
||||||
|
|
||||||
|
@inject(WindowService)
|
||||||
|
private readonly windowService: WindowService;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@inject(VersionWelcomeDialogProps)
|
||||||
|
protected override readonly props: VersionWelcomeDialogProps
|
||||||
|
) {
|
||||||
|
super({
|
||||||
|
title: nls.localize(
|
||||||
|
'arduino/versionWelcome/title',
|
||||||
|
'Welcome to a new version of the Arduino IDE!'
|
||||||
|
),
|
||||||
|
});
|
||||||
|
this.node.id = 'version-welcome-dialog-container';
|
||||||
|
this.contentNode.classList.add('version-welcome-dialog');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): React.ReactNode {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
{nls.localize(
|
||||||
|
'arduino/versionWelcome/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.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p className="bold">
|
||||||
|
{nls.localize(
|
||||||
|
'arduino/versionWelcome/donateMessage2',
|
||||||
|
'Please consider supporting our work on the free open source Arduino IDE.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
override get value(): void {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private appendButtons(): void {
|
||||||
|
const cancelButton = this.createButton(
|
||||||
|
nls.localize('arduino/versionWelcome/cancelButton', 'Maybe later')
|
||||||
|
);
|
||||||
|
cancelButton.classList.add('secondary');
|
||||||
|
cancelButton.classList.add('cancel-button');
|
||||||
|
this.addAction(cancelButton, this.close.bind(this), 'click');
|
||||||
|
this.controlPanel.appendChild(cancelButton);
|
||||||
|
|
||||||
|
const donateButton = this.createButton(
|
||||||
|
nls.localize('arduino/versionWelcome/donateButton', 'Donate now')
|
||||||
|
);
|
||||||
|
this.addAction(donateButton, this.onDonateButtonClick.bind(this), 'click');
|
||||||
|
this.controlPanel.appendChild(donateButton);
|
||||||
|
donateButton.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onDonateButtonClick(): void {
|
||||||
|
this.openDonationPage();
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly openDonationPage = () => {
|
||||||
|
const url = 'https://www.arduino.cc/en/donate';
|
||||||
|
this.windowService.openNewWindow(url, { external: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
private async updateTitleVersion(): Promise<void> {
|
||||||
|
const appInfo = await this.appService.info();
|
||||||
|
const { appVersion } = appInfo;
|
||||||
|
|
||||||
|
if (appVersion) {
|
||||||
|
this.titleNode.innerHTML = nls.localize(
|
||||||
|
'arduino/versionWelcome/titleWithVersion',
|
||||||
|
'Welcome to the new Arduino IDE {0}!',
|
||||||
|
appVersion
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override onAfterAttach(msg: Message): void {
|
||||||
|
this.update();
|
||||||
|
this.appendButtons();
|
||||||
|
this.updateTitleVersion();
|
||||||
|
super.onAfterAttach(msg);
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
@import "./settings-dialog.css";
|
@import "./settings-dialog.css";
|
||||||
@import "./firmware-uploader-dialog.css";
|
@import "./firmware-uploader-dialog.css";
|
||||||
@import "./ide-updater-dialog.css";
|
@import "./ide-updater-dialog.css";
|
||||||
|
@import "./version-welcome-dialog.css";
|
||||||
@import "./certificate-uploader-dialog.css";
|
@import "./certificate-uploader-dialog.css";
|
||||||
@import "./user-fields-dialog.css";
|
@import "./user-fields-dialog.css";
|
||||||
@import "./debug.css";
|
@import "./debug.css";
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
#version-welcome-dialog-container > .dialogBlock {
|
||||||
|
width: 546px;
|
||||||
|
|
||||||
|
.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
@ -71,3 +71,4 @@ export interface IDEUpdaterClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const SKIP_IDE_VERSION = 'skipIDEVersion';
|
export const SKIP_IDE_VERSION = 'skipIDEVersion';
|
||||||
|
export const LAST_USED_IDE_VERSION = 'lastUsedIDEVersion';
|
||||||
|
@ -528,6 +528,14 @@
|
|||||||
"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?",
|
"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?",
|
||||||
"renameSketchFolderTitle": "Invalid sketch name"
|
"renameSketchFolderTitle": "Invalid sketch name"
|
||||||
},
|
},
|
||||||
|
"versionWelcome": {
|
||||||
|
"cancelButton": "Maybe later",
|
||||||
|
"donateButton": "Donate now",
|
||||||
|
"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.",
|
||||||
|
"donateMessage2": "Please consider supporting our work on the free open source Arduino IDE.",
|
||||||
|
"title": "Welcome to a new version of the Arduino IDE!",
|
||||||
|
"titleWithVersion": "Welcome to the new Arduino IDE {0}!"
|
||||||
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"alreadyExists": "'{0}' already exists."
|
"alreadyExists": "'{0}' already exists."
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user