ATL-663: Indicate alpha status. Updated the About dialog.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2020-11-03 16:08:19 +01:00 committed by Akos Kitta
parent 7b364ebe60
commit 874c3efa2c
13 changed files with 114 additions and 49 deletions

View File

@ -57,8 +57,6 @@ import { TabBarDecoratorService } from './theia/core/tab-bar-decorator';
import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser';
import { ProblemManager } from './theia/markers/problem-manager';
import { BoardsAutoInstaller } from './boards/boards-auto-installer';
import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog';
import { AboutDialog } from './theia/core/about-dialog';
import { ShellLayoutRestorer } from './theia/core/shell-layout-restorer';
import { EditorMode } from './editor-mode';
import { ListItemRenderer } from './widgets/component-list/list-item-renderer';
@ -121,11 +119,12 @@ import { OutputServiceImpl } from './output-service-impl';
import { OutputServicePath, OutputService } from '../common/protocol/output-service';
import { NotificationCenter } from './notification-center';
import { NotificationServicePath, NotificationServiceServer } from '../common/protocol';
import { About } from './contributions/about';
const ElementQueries = require('css-element-queries/src/ElementQueries');
MonacoThemingService.register({
id: 'arduinoTheme',
id: 'arduino-theme',
label: 'Light (Arduino)',
uiTheme: 'vs',
json: require('../../src/browser/data/arduino.color-theme.json')
@ -289,10 +288,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ProblemManager).toSelf().inSingletonScope();
rebind(TheiaProblemManager).toService(ProblemManager);
// About dialog to show the CLI version
bind(AboutDialog).toSelf().inSingletonScope();
rebind(TheiaAboutDialog).toService(AboutDialog);
// Customized layout restorer that can restore the state in async way: https://github.com/eclipse-theia/theia/issues/6579
bind(ShellLayoutRestorer).toSelf().inSingletonScope();
rebind(TheiaShellLayoutRestorer).toService(ShellLayoutRestorer);
@ -324,6 +319,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
Contribution.configure(bind, BuiltInExamples);
Contribution.configure(bind, LibraryExamples);
Contribution.configure(bind, IncludeLibrary);
Contribution.configure(bind, About);
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
WebSocketConnectionProvider.createProxy(container, OutputServicePath, outputService);

View File

@ -0,0 +1,74 @@
import { inject, injectable } from 'inversify';
import { remote } from 'electron';
import { isOSX, isWindows } from '@theia/core/lib/common/os';
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
import { Contribution, Command, MenuModelRegistry, CommandRegistry } from './contribution';
import { ArduinoMenus } from '../menu/arduino-menus';
import { ConfigService } from '../../common/protocol';
@injectable()
export class About extends Contribution {
@inject(ClipboardService)
protected readonly clipboardService: ClipboardService;
@inject(ConfigService)
protected readonly configService: ConfigService;
registerCommands(registry: CommandRegistry): void {
registry.registerCommand(About.Commands.ABOUT_APP, {
execute: () => this.showAbout()
});
}
registerMenus(registry: MenuModelRegistry): void {
// On macOS we will get the `Quit ${YOUR_APP_NAME}` menu item natively, no need to duplicate it.
registry.registerMenuAction(ArduinoMenus.HELP__ABOUT_GROUP, {
commandId: About.Commands.ABOUT_APP.id,
label: `About${isOSX ? ` ${this.applicationName}` : ''}`,
order: '0'
});
}
async showAbout(): Promise<void> {
const ideStatus = FrontendApplicationConfigProvider.get()['status'];
const { version, commit, status: cliStatus } = await this.configService.getVersion();
const detail = `
Version: ${remote.app.getVersion()}
CLI Version: ${version}${cliStatus ? ` ${cliStatus}` : ''} [${commit}]
Copyright © ${new Date().getFullYear()} Arduino SA
`;
const ok = 'OK';
const copy = 'Copy';
const buttons = !isWindows && !isOSX ? [copy, ok] : [ok, copy];
const { response } = await remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: `${this.applicationName}${ideStatus ? ` ${ideStatus}` : ''}`,
title: `${this.applicationName}${ideStatus ? ` ${ideStatus}` : ''}`,
type: 'info',
detail,
buttons,
noLink: true,
defaultId: buttons.indexOf(ok),
cancelId: buttons.indexOf(ok)
});
if (buttons[response] === copy) {
await this.clipboardService.writeText(detail);
}
}
protected get applicationName(): string {
return FrontendApplicationConfigProvider.get().applicationName;
}
}
export namespace About {
export namespace Commands {
export const ABOUT_APP: Command = {
id: 'arduino-about'
};
}
}

View File

@ -1,6 +1,6 @@
import { MAIN_MENU_BAR } from '@theia/core/lib/common/menu';
import { isOSX } from '@theia/core/lib/common/os';
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
import { isOSX } from '@theia/core';
import { MAIN_MENU_BAR } from '@theia/core/lib/common/menu';
export namespace ArduinoMenus {
@ -40,7 +40,14 @@ export namespace ArduinoMenus {
// Core settings, such as `Processor` and `Programmers` for the board and `Burn Bootloader`
export const TOOLS__BOARD_SETTINGS_GROUP = [...TOOLS, '1_board_settings'];
// Context menu
// -- Help
// `About` group
// XXX: on macOS, the about group is not under `Help`
export const HELP__ABOUT_GROUP = [...(isOSX ? MAIN_MENU_BAR : CommonMenus.HELP), '999_about'];
// ------------
// Context menus
// -- Open
export const OPEN_SKETCH__CONTEXT = ['arduino-open-sketch--context'];
export const OPEN_SKETCH__CONTEXT__OPEN_GROUP = [...OPEN_SKETCH__CONTEXT, '0_open'];

View File

@ -1,25 +0,0 @@
import { injectable, inject, postConstruct } from 'inversify';
import { AboutDialog as TheiaAboutDialog, ABOUT_CONTENT_CLASS } from '@theia/core/lib/browser/about-dialog';
import { ConfigService } from '../../../common/protocol/config-service';
@injectable()
export class AboutDialog extends TheiaAboutDialog {
@inject(ConfigService)
protected readonly configService: ConfigService;
@postConstruct()
protected async init(): Promise<void> {
const [, version] = await Promise.all([super.init(), this.configService.getVersion()]);
if (version) {
const { firstChild } = this.contentNode;
if (firstChild instanceof HTMLElement && firstChild.classList.contains(ABOUT_CONTENT_CLASS)) {
const cliVersion = document.createElement('div');
cliVersion.textContent = version;
firstChild.appendChild(cliVersion);
// TODO: anchor to the commit in the `arduino-cli` repository.
}
}
}
}

View File

@ -19,7 +19,8 @@ export class CommonFrontendContribution extends TheiaCommonFrontendContribution
CommonCommands.AUTO_SAVE,
CommonCommands.OPEN_PREFERENCES,
CommonCommands.SELECT_ICON_THEME,
CommonCommands.SELECT_COLOR_THEME
CommonCommands.SELECT_COLOR_THEME,
CommonCommands.ABOUT_COMMAND
]) {
registry.unregisterMenuAction(command);
}

View File

@ -7,6 +7,7 @@ import { ApplicationServer } from '@theia/core/lib/common/application-protocol';
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
import { FocusTracker, Widget } from '@theia/core/lib/browser';
import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
import { ConfigService } from '../../../common/protocol/config-service';
import { SketchesService } from '../../../common/protocol/sketches-service';
import { ArduinoWorkspaceRootResolver } from '../../arduino-workspace-resolver';
@ -97,8 +98,9 @@ export class WorkspaceService extends TheiaWorkspaceService {
}
protected formatTitle(title?: string): string {
const status = FrontendApplicationConfigProvider.get()['status'];
const version = this.version ? ` ${this.version}` : '';
const name = `${this.applicationName} ${version}`;
const name = `${this.applicationName}${status ? ` ${status}` : ''} ${version}`;
return title ? `${title} | ${name}` : name;
}

View File

@ -1,7 +1,7 @@
export const ConfigServicePath = '/services/config-service';
export const ConfigService = Symbol('ConfigService');
export interface ConfigService {
getVersion(): Promise<string>;
getVersion(): Promise<Readonly<{ version: string, commit: string, status?: string }>>;
getConfiguration(): Promise<Config>;
getCliConfigFileUri(): Promise<string>;
getConfigurationFileSchemaUri(): Promise<string>;

View File

@ -20,13 +20,13 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
const { submenu } = super.createOSXMenu();
const label = 'Arduino Pro IDE';
if (!!submenu && !(submenu instanceof remote.Menu)) {
const [about, , ...rest] = submenu;
const menuModel = this.menuProvider.getMenu(ArduinoMenus.FILE__SETTINGS_GROUP);
const settings = this.fillMenuTemplate([], menuModel);
const [/* about */, /* settings */, ...rest] = submenu;
const about = this.fillMenuTemplate([], this.menuProvider.getMenu(ArduinoMenus.HELP__ABOUT_GROUP));
const settings = this.fillMenuTemplate([], this.menuProvider.getMenu(ArduinoMenus.FILE__SETTINGS_GROUP));
return {
label,
submenu: [
about, // TODO: we have two about dialogs! one from electron the other from Theia.
...about,
{ type: 'separator' },
...settings,
{ type: 'separator' },

View File

@ -105,9 +105,20 @@ export class ArduinoDaemonImpl implements ArduinoDaemon, BackendApplicationContr
return this._execPath;
}
async getVersion(): Promise<string> {
async getVersion(): Promise<Readonly<{ version: string, commit: string, status?: string }>> {
const execPath = await this.getExecPath();
return spawnCommand(`"${execPath}"`, ['version'], this.onError.bind(this));
const raw = await spawnCommand(`"${execPath}"`, ['version', '--format', 'json'], this.onError.bind(this));
try {
// The CLI `Info` object: https://github.com/arduino/arduino-cli/blob/17d24eb901b1fdaa5a4ec7da3417e9e460f84007/version/version.go#L31-L34
const { VersionString, Commit, Status } = JSON.parse(raw);
return {
version: VersionString,
commit: Commit,
status: Status
};
} catch {
return { version: raw, commit: raw };
}
}
protected async getSpawnArgs(): Promise<string[]> {

View File

@ -84,7 +84,7 @@ export class ConfigServiceImpl implements BackendApplicationContribution, Config
return this.configChangeEmitter.event;
}
async getVersion(): Promise<string> {
async getVersion(): Promise<Readonly<{ version: string, commit: string, status?: string }>> {
return this.daemon.getVersion();
}

View File

@ -34,6 +34,7 @@
"config": {
"applicationName": "Arduino Pro IDE",
"defaultTheme": "arduino-theme",
"status": "Alpha",
"preferences": {
"editor.autoSave": "on",
"editor.minimap.enabled": false,

View File

@ -37,6 +37,7 @@
"config": {
"applicationName": "Arduino Pro IDE",
"defaultTheme": "arduino-theme",
"status": "Alpha",
"preferences": {
"editor.autoSave": "on",
"editor.minimap.enabled": false,

View File

@ -38,20 +38,17 @@
"target": "electron",
"frontend": {
"config": {
"applicationName": "Arduino Pro IDE",
"disallowReloadKeybinding": true
}
},
"backend": {
"config": {
"singleInstance": true,
"configDirName": ".arduinoProIDE"
"singleInstance": true
}
}
},
"build": {
"productName": "Arduino Pro IDE",
"appId": "arduino.ProIDE",
"asar": false,
"directories": {
"buildResources": "resources"