Skip to content

Commit 4deaf4f

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommittedFeb 20, 2023
feat: moved login entry point to the side-bar
Closes #1877 Signed-off-by: Akos Kitta <[email protected]>
1 parent d68bc4a commit 4deaf4f

13 files changed

+278
-114
lines changed
 

‎arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx

+2-7
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ import {
1010
MenuContribution,
1111
MenuModelRegistry,
1212
} from '@theia/core';
13-
import {
14-
FrontendApplication,
15-
FrontendApplicationContribution,
16-
} from '@theia/core/lib/browser';
13+
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
1714
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
1815
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
1916
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
@@ -77,7 +74,7 @@ export class ArduinoFrontendContribution
7774
}
7875
}
7976

80-
onStart(app: FrontendApplication): void {
77+
onStart(): void {
8178
this.electronWindowPreferences.onPreferenceChanged((event) => {
8279
if (event.newValue !== event.oldValue) {
8380
switch (event.preferenceName) {
@@ -98,8 +95,6 @@ export class ArduinoFrontendContribution
9895
webContents.setZoomLevel(zoomLevel);
9996
})
10097
);
101-
// Removes the _Settings_ (cog) icon from the left sidebar
102-
app.shell.leftPanelHandler.removeBottomMenu('settings-menu');
10398
}
10499

105100
registerToolbarItems(registry: TabBarToolbarRegistry): void {

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

+7
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ import { ConfigServiceClient } from './config/config-service-client';
347347
import { ValidateSketch } from './contributions/validate-sketch';
348348
import { RenameCloudSketch } from './contributions/rename-cloud-sketch';
349349
import { CreateFeatures } from './create/create-features';
350+
import { Account } from './contributions/account';
351+
import { SidebarBottomMenuWidget } from './theia/core/sidebar-bottom-menu-widget';
352+
import { SidebarBottomMenuWidget as TheiaSidebarBottomMenuWidget } from '@theia/core/lib/browser/shell/sidebar-bottom-menu-widget';
350353

351354
export default new ContainerModule((bind, unbind, isBound, rebind) => {
352355
// Commands and toolbar items
@@ -734,6 +737,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
734737
Contribution.configure(bind, NewCloudSketch);
735738
Contribution.configure(bind, ValidateSketch);
736739
Contribution.configure(bind, RenameCloudSketch);
740+
Contribution.configure(bind, Account);
737741

738742
bindContributionProvider(bind, StartupTaskProvider);
739743
bind(StartupTaskProvider).toService(BoardsServiceProvider); // to reuse the boards config in another window
@@ -1014,4 +1018,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
10141018
},
10151019
}))
10161020
.inSingletonScope();
1021+
1022+
bind(SidebarBottomMenuWidget).toSelf();
1023+
rebind(TheiaSidebarBottomMenuWidget).toService(SidebarBottomMenuWidget);
10171024
});

‎arduino-ide-extension/src/browser/auth/authentication-client-service.ts

+4
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,13 @@ export class AuthenticationClientService
8383
registerCommands(registry: CommandRegistry): void {
8484
registry.registerCommand(CloudUserCommands.LOGIN, {
8585
execute: () => this.service.login(),
86+
isEnabled: () => !this._session,
87+
isVisible: () => !this._session,
8688
});
8789
registry.registerCommand(CloudUserCommands.LOGOUT, {
8890
execute: () => this.service.logout(),
91+
isEnabled: () => !!this._session,
92+
isVisible: () => !!this._session,
8993
});
9094
}
9195

‎arduino-ide-extension/src/browser/auth/cloud-user-commands.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { Command } from '@theia/core/lib/common/command';
22

3+
export const LEARN_MORE_URL =
4+
'https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-cloud-sketch-sync';
5+
36
export namespace CloudUserCommands {
47
export const LOGIN = Command.toLocalizedCommand(
58
{
@@ -16,9 +19,4 @@ export namespace CloudUserCommands {
1619
},
1720
'arduino/cloud/signOut'
1821
);
19-
20-
export const OPEN_PROFILE_CONTEXT_MENU: Command = {
21-
id: 'arduino-cloud-sketchbook--open-profile-menu',
22-
label: 'Contextual menu',
23-
};
2422
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
2+
import { SidebarMenu } from '@theia/core/lib/browser/shell/sidebar-menu-widget';
3+
import { WindowService } from '@theia/core/lib/browser/window/window-service';
4+
import { DisposableCollection } from '@theia/core/lib/common/disposable';
5+
import { MenuPath } from '@theia/core/lib/common/menu';
6+
import { nls } from '@theia/core/lib/common/nls';
7+
import { inject, injectable } from '@theia/core/shared/inversify';
8+
import { CloudUserCommands, LEARN_MORE_URL } from '../auth/cloud-user-commands';
9+
import { CreateFeatures } from '../create/create-features';
10+
import { ArduinoMenus } from '../menu/arduino-menus';
11+
import {
12+
Command,
13+
CommandRegistry,
14+
Contribution,
15+
MenuModelRegistry,
16+
} from './contribution';
17+
18+
export const accountMenu: SidebarMenu = {
19+
id: 'arduino-accounts-menu',
20+
iconClass: 'codicon codicon-account',
21+
title: nls.localize('arduino/account/menuTitle', 'Arduino Cloud'),
22+
menuPath: ArduinoMenus.ARDUINO_ACCOUNT__CONTEXT,
23+
order: 0,
24+
};
25+
26+
@injectable()
27+
export class Account extends Contribution {
28+
@inject(WindowService)
29+
private readonly windowService: WindowService;
30+
@inject(CreateFeatures)
31+
private readonly createFeatures: CreateFeatures;
32+
33+
private readonly toDispose = new DisposableCollection();
34+
private app: FrontendApplication;
35+
36+
override onStart(app: FrontendApplication): void {
37+
this.app = app;
38+
this.updateSidebarCommand();
39+
this.toDispose.push(
40+
this.createFeatures.onDidChangeEnabled((enabled) =>
41+
this.updateSidebarCommand(enabled)
42+
)
43+
);
44+
}
45+
46+
onStop(): void {
47+
this.toDispose.dispose();
48+
}
49+
50+
override registerCommands(registry: CommandRegistry): void {
51+
const openExternal = (url: string) =>
52+
this.windowService.openNewWindow(url, { external: true });
53+
registry.registerCommand(Account.Commands.LEARN_MORE, {
54+
execute: () => openExternal(LEARN_MORE_URL),
55+
isEnabled: () => !Boolean(this.createFeatures.session),
56+
});
57+
registry.registerCommand(Account.Commands.GO_TO_PROFILE, {
58+
execute: () => openExternal('https://id.arduino.cc/'),
59+
isEnabled: () => Boolean(this.createFeatures.session),
60+
});
61+
registry.registerCommand(Account.Commands.GO_TO_CLOUD_EDITOR, {
62+
execute: () => openExternal('https://create.arduino.cc/editor'),
63+
isEnabled: () => Boolean(this.createFeatures.session),
64+
});
65+
registry.registerCommand(Account.Commands.GO_TO_IOT_CLOUD, {
66+
execute: () => openExternal('https://create.arduino.cc/iot/'),
67+
isEnabled: () => Boolean(this.createFeatures.session),
68+
});
69+
}
70+
71+
override registerMenus(registry: MenuModelRegistry): void {
72+
const register = (
73+
menuPath: MenuPath,
74+
...commands: (Command | [command: Command, menuLabel: string])[]
75+
) =>
76+
commands.forEach((command, index) => {
77+
const commandId = Array.isArray(command) ? command[0].id : command.id;
78+
const label = Array.isArray(command) ? command[1] : command.label;
79+
registry.registerMenuAction(menuPath, {
80+
label,
81+
commandId,
82+
order: String(index),
83+
});
84+
});
85+
86+
register(ArduinoMenus.ARDUINO_ACCOUNT__CONTEXT__SIGN_IN_GROUP, [
87+
CloudUserCommands.LOGIN,
88+
nls.localize('arduino/cloud/signInToCloud', 'Sign in to Arduino Cloud'),
89+
]);
90+
register(ArduinoMenus.ARDUINO_ACCOUNT__CONTEXT__LEARN_MORE_GROUP, [
91+
Account.Commands.LEARN_MORE,
92+
nls.localize('arduino/cloud/learnMore', 'Learn more'),
93+
]);
94+
register(
95+
ArduinoMenus.ARDUINO_ACCOUNT__CONTEXT__GO_TO_GROUP,
96+
[
97+
Account.Commands.GO_TO_PROFILE,
98+
nls.localize('arduino/account/goToProfile', 'Go to Profile'),
99+
],
100+
[
101+
Account.Commands.GO_TO_CLOUD_EDITOR,
102+
nls.localize('arduino/account/goToCloudEditor', 'Go to Cloud Editor'),
103+
],
104+
[
105+
Account.Commands.GO_TO_IOT_CLOUD,
106+
nls.localize('arduino/account/goToIoTCloud', 'Go to IoT Cloud'),
107+
]
108+
);
109+
register(
110+
ArduinoMenus.ARDUINO_ACCOUNT__CONTEXT__SIGN_OUT_GROUP,
111+
CloudUserCommands.LOGOUT
112+
);
113+
}
114+
115+
private updateSidebarCommand(
116+
visible: boolean = this.preferences['arduino.cloud.enabled']
117+
): void {
118+
if (!this.app) {
119+
return;
120+
}
121+
const handler = this.app.shell.leftPanelHandler;
122+
if (visible) {
123+
handler.addBottomMenu(accountMenu);
124+
} else {
125+
handler.removeBottomMenu(accountMenu.id);
126+
}
127+
}
128+
}
129+
130+
export namespace Account {
131+
export namespace Commands {
132+
export const GO_TO_PROFILE: Command = {
133+
id: 'arduino-go-to-profile',
134+
};
135+
export const GO_TO_CLOUD_EDITOR: Command = {
136+
id: 'arduino-go-to-cloud-editor',
137+
};
138+
export const GO_TO_IOT_CLOUD: Command = {
139+
id: 'arduino-go-to-iot-cloud',
140+
};
141+
export const LEARN_MORE: Command = {
142+
id: 'arduino-learn-more',
143+
};
144+
}
145+
}

‎arduino-ide-extension/src/browser/menu/arduino-menus.ts

+19
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,25 @@ export namespace ArduinoMenus {
154154
'2_resources',
155155
];
156156

157+
// -- Account
158+
export const ARDUINO_ACCOUNT__CONTEXT = ['arduino-account--context'];
159+
export const ARDUINO_ACCOUNT__CONTEXT__SIGN_IN_GROUP = [
160+
...ARDUINO_ACCOUNT__CONTEXT,
161+
'0_sign_in',
162+
];
163+
export const ARDUINO_ACCOUNT__CONTEXT__LEARN_MORE_GROUP = [
164+
...ARDUINO_ACCOUNT__CONTEXT,
165+
'1_learn_more',
166+
];
167+
export const ARDUINO_ACCOUNT__CONTEXT__GO_TO_GROUP = [
168+
...ARDUINO_ACCOUNT__CONTEXT,
169+
'2_go_to',
170+
];
171+
export const ARDUINO_ACCOUNT__CONTEXT__SIGN_OUT_GROUP = [
172+
...ARDUINO_ACCOUNT__CONTEXT,
173+
'3_sign_out',
174+
];
175+
157176
// -- ROOT SSL CERTIFICATES
158177
export const ROOT_CERTIFICATES__CONTEXT = [
159178
'arduino-root-certificates--context',

‎arduino-ide-extension/src/browser/style/cloud-sketchbook.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@
119119

120120
.account-icon {
121121
background: url("./account-icon.svg") center center no-repeat;
122-
width: var(--theia-icon-size);
123-
height: var(--theia-icon-size);
122+
width: var(--theia-private-sidebar-icon-size);
123+
height: var(--theia-private-sidebar-icon-size);
124124
border-radius: 50%;
125125
overflow: hidden;
126126
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { SidebarBottomMenuWidget as TheiaSidebarBottomMenuWidget } from '@theia/core/lib/browser/shell/sidebar-bottom-menu-widget';
2+
import type { SidebarMenu } from '@theia/core/lib/browser/shell/sidebar-menu-widget';
3+
import type { MenuPath } from '@theia/core/lib/common/menu';
4+
import { nls } from '@theia/core/lib/common/nls';
5+
import {
6+
inject,
7+
injectable,
8+
postConstruct,
9+
} from '@theia/core/shared/inversify';
10+
import * as React from '@theia/core/shared/react';
11+
import { accountMenu } from '../../contributions/account';
12+
import { CreateFeatures } from '../../create/create-features';
13+
14+
@injectable()
15+
export class SidebarBottomMenuWidget extends TheiaSidebarBottomMenuWidget {
16+
@inject(CreateFeatures)
17+
private readonly createFeatures: CreateFeatures;
18+
19+
@postConstruct()
20+
protected init(): void {
21+
this.toDispose.push(
22+
this.createFeatures.onDidChangeSession(() => this.update())
23+
);
24+
}
25+
26+
protected override onClick(
27+
e: React.MouseEvent<HTMLElement, MouseEvent>,
28+
menuPath: MenuPath
29+
): void {
30+
const button = e.currentTarget.getBoundingClientRect();
31+
this.contextMenuRenderer.render({
32+
menuPath,
33+
includeAnchorArg: false,
34+
anchor: {
35+
x: button.left + button.width,
36+
// Bogus y coordinate?
37+
// https://github.com/eclipse-theia/theia/discussions/12170
38+
y: button.top,
39+
},
40+
});
41+
}
42+
43+
protected override render(): React.ReactNode {
44+
return (
45+
<React.Fragment>
46+
{this.menus.map((menu) => this.renderMenu(menu))}
47+
</React.Fragment>
48+
);
49+
}
50+
51+
private renderMenu(menu: SidebarMenu): React.ReactNode {
52+
// Removes the _Settings_ (cog) icon from the left sidebar
53+
if (menu.id === 'settings-menu') {
54+
return undefined;
55+
}
56+
const arduinoAccount = menu.id === accountMenu.id;
57+
const picture =
58+
arduinoAccount && this.createFeatures.session?.account.picture;
59+
const className = typeof picture === 'string' ? undefined : menu.iconClass;
60+
return (
61+
<i
62+
key={menu.id}
63+
className={className}
64+
title={menu.title}
65+
onClick={(e) => this.onClick(e, menu.menuPath)}
66+
onMouseDown={this.onMouseDown}
67+
onMouseOut={this.onMouseOut}
68+
>
69+
{picture && (
70+
<div className="account-icon">
71+
<img
72+
src={picture}
73+
alt={nls.localize(
74+
'arduino/cloud/profilePicture',
75+
'Profile picture'
76+
)}
77+
/>
78+
</div>
79+
)}
80+
</i>
81+
);
82+
}
83+
}

‎arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
injectable,
66
postConstruct,
77
} from '@theia/core/shared/inversify';
8-
import { UserStatus } from './cloud-user-status';
8+
import { CloudStatus } from './cloud-user-status';
99
import { nls } from '@theia/core/lib/common/nls';
1010
import { CloudSketchbookTreeWidget } from './cloud-sketchbook-tree-widget';
1111
import { AuthenticationClientService } from '../../auth/authentication-client-service';
@@ -61,7 +61,7 @@ export class CloudSketchbookCompositeWidget extends BaseSketchbookCompositeWidge
6161
onClick={this.onDidClickCreateNew}
6262
/>
6363
)}
64-
<UserStatus
64+
<CloudStatus
6565
model={
6666
this.cloudSketchbookTreeWidget.model as CloudSketchbookTreeModel
6767
}

‎arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts

-57
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { WindowService } from '@theia/core/lib/browser/window/window-service';
1414
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
1515
import { CloudSketchbookTree } from './cloud-sketchbook-tree';
1616
import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
17-
import { CloudUserCommands } from '../../auth/cloud-user-commands';
1817
import { ShareSketchDialog } from '../../dialogs/cloud-share-sketch-dialog';
1918
import { CreateApi } from '../../create/create-api';
2019
import {
@@ -40,16 +39,6 @@ export const SKETCHBOOKSYNC__CONTEXT__MAIN_GROUP = [
4039
'0_main',
4140
];
4241

43-
export const CLOUD_USER__CONTEXT = ['arduino-cloud-user--context'];
44-
export const CLOUD_USER__CONTEXT__USERNAME = [
45-
...CLOUD_USER__CONTEXT,
46-
'0_username',
47-
];
48-
export const CLOUD_USER__CONTEXT__MAIN_GROUP = [
49-
...CLOUD_USER__CONTEXT,
50-
'1_main',
51-
];
52-
5342
export namespace CloudSketchbookCommands {
5443
export interface Arg {
5544
model: CloudSketchbookTreeModel;
@@ -328,52 +317,6 @@ export class CloudSketchbookContribution extends Contribution {
328317
}
329318
);
330319

331-
registry.registerCommand(CloudUserCommands.OPEN_PROFILE_CONTEXT_MENU, {
332-
execute: async (arg) => {
333-
this.toDisposeBeforeNewContextMenu.dispose();
334-
const container = arg.event.target;
335-
if (!container) {
336-
return;
337-
}
338-
339-
this.menuRegistry.registerMenuAction(CLOUD_USER__CONTEXT__MAIN_GROUP, {
340-
commandId: CloudUserCommands.LOGOUT.id,
341-
label: CloudUserCommands.LOGOUT.label,
342-
});
343-
this.toDisposeBeforeNewContextMenu.push(
344-
Disposable.create(() =>
345-
this.menuRegistry.unregisterMenuAction(CloudUserCommands.LOGOUT)
346-
)
347-
);
348-
349-
const placeholder = new PlaceholderMenuNode(
350-
CLOUD_USER__CONTEXT__USERNAME,
351-
arg.username
352-
);
353-
this.menuRegistry.registerMenuNode(
354-
CLOUD_USER__CONTEXT__USERNAME,
355-
placeholder
356-
);
357-
this.toDisposeBeforeNewContextMenu.push(
358-
Disposable.create(() =>
359-
this.menuRegistry.unregisterMenuNode(placeholder.id)
360-
)
361-
);
362-
363-
const options: RenderContextMenuOptions = {
364-
menuPath: CLOUD_USER__CONTEXT,
365-
anchor: {
366-
x: container.getBoundingClientRect().left,
367-
y:
368-
container.getBoundingClientRect().top -
369-
3.5 * container.offsetHeight,
370-
},
371-
args: [arg],
372-
};
373-
this.contextMenuRenderer.render(options);
374-
},
375-
});
376-
377320
this.registerMenus(this.menuRegistry);
378321
}
379322
}

‎arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
55
import { AuthenticationClientService } from '../../auth/authentication-client-service';
66
import { FileService } from '@theia/filesystem/lib/browser/file-service';
77
import { CloudSketchbookTree } from './cloud-sketchbook-tree';
8-
import { CloudUserCommands } from '../../auth/cloud-user-commands';
8+
import {
9+
CloudUserCommands,
10+
LEARN_MORE_URL,
11+
} from '../../auth/cloud-user-commands';
912
import { NodeProps } from '@theia/core/lib/browser/tree/tree-widget';
1013
import { TreeNode } from '@theia/core/lib/browser/tree';
1114
import { CompositeTreeNode } from '@theia/core/lib/browser';
1215
import { shell } from '@theia/core/electron-shared/@electron/remote';
1316
import { SketchbookTreeWidget } from '../sketchbook/sketchbook-tree-widget';
1417
import { nls } from '@theia/core/lib/common';
1518

16-
const LEARN_MORE_URL =
17-
'https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-cloud-sketch-sync';
18-
1919
@injectable()
2020
export class CloudSketchbookTreeWidget extends SketchbookTreeWidget {
2121
@inject(AuthenticationClientService)

‎arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-user-status.tsx

+1-36
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import {
55
} from '@theia/core/lib/common/disposable';
66
import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
77
import { AuthenticationClientService } from '../../auth/authentication-client-service';
8-
import { CloudUserCommands } from '../../auth/cloud-user-commands';
9-
import { AuthenticationSessionAccountInformation } from '../../../common/protocol/authentication-service';
108
import { nls } from '@theia/core/lib/common';
119

12-
export class UserStatus extends React.Component<
10+
export class CloudStatus extends React.Component<
1311
UserStatus.Props,
1412
UserStatus.State
1513
> {
@@ -19,7 +17,6 @@ export class UserStatus extends React.Component<
1917
super(props);
2018
this.state = {
2119
status: this.status,
22-
accountInfo: props.authenticationService.session?.account,
2320
refreshing: false,
2421
};
2522
}
@@ -29,9 +26,6 @@ export class UserStatus extends React.Component<
2926
window.addEventListener('online', statusListener);
3027
window.addEventListener('offline', statusListener);
3128
this.toDispose.pushAll([
32-
this.props.authenticationService.onSessionDidChange((session) =>
33-
this.setState({ accountInfo: session?.account })
34-
),
3529
Disposable.create(() =>
3630
window.removeEventListener('online', statusListener)
3731
),
@@ -73,34 +67,6 @@ export class UserStatus extends React.Component<
7367
onClick={this.onDidClickRefresh}
7468
/>
7569
</div>
76-
<div className="account item flex-line">
77-
<div
78-
title={nls.localize('arduino/cloud/account', 'Account')}
79-
className="account-icon"
80-
style={{ cursor: 'pointer' }}
81-
onClick={(event) => {
82-
event.preventDefault();
83-
event.stopPropagation();
84-
this.props.model.commandRegistry.executeCommand(
85-
CloudUserCommands.OPEN_PROFILE_CONTEXT_MENU.id,
86-
{
87-
event: event.nativeEvent,
88-
username: this.state.accountInfo?.label,
89-
}
90-
);
91-
}}
92-
>
93-
{this.state.accountInfo?.picture && (
94-
<img
95-
src={this.state.accountInfo?.picture}
96-
alt={nls.localize(
97-
'arduino/cloud/profilePicture',
98-
'Profile picture'
99-
)}
100-
/>
101-
)}
102-
</div>
103-
</div>
10470
</div>
10571
);
10672
}
@@ -128,7 +94,6 @@ export namespace UserStatus {
12894
}
12995
export interface State {
13096
status: 'connected' | 'offline';
131-
accountInfo?: AuthenticationSessionAccountInformation;
13297
refreshing?: boolean;
13398
}
13499
}

‎i18n/en.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
"detail": "Version: {0}\nDate: {1}{2}\nCLI Version: {3}\n\n{4}",
55
"label": "About {0}"
66
},
7+
"account": {
8+
"goToCloudEditor": "Go to Cloud Editor",
9+
"goToIoTCloud": "Go to IoT Cloud",
10+
"goToProfile": "Go to Profile",
11+
"menuTitle": "Arduino Cloud"
12+
},
713
"board": {
814
"board": "Board{0}",
915
"boardConfigDialogTitle": "Select Other Board and Port",
@@ -83,7 +89,6 @@
8389
"mouseError": "'Mouse' not found. Does your sketch include the line '#include <Mouse.h>'?"
8490
},
8591
"cloud": {
86-
"account": "Account",
8792
"chooseSketchVisibility": "Choose visibility of your Sketch:",
8893
"cloudSketchbook": "Cloud Sketchbook",
8994
"connected": "Connected",

0 commit comments

Comments
 (0)
Please sign in to comment.