Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4deaf4f

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommitted
feat: moved login entry point to the side-bar
Closes #1877 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent d68bc4a commit 4deaf4f

13 files changed

+278
-114
lines changed

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

Lines changed: 2 additions & 7 deletions
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‎

Lines changed: 7 additions & 0 deletions
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‎

Lines changed: 4 additions & 0 deletions
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‎

Lines changed: 3 additions & 5 deletions
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
}
Lines changed: 145 additions & 0 deletions
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‎

Lines changed: 19 additions & 0 deletions
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‎

Lines changed: 2 additions & 2 deletions
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
}
Lines changed: 83 additions & 0 deletions
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‎

Lines changed: 2 additions & 2 deletions
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
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /