Skip to content

Commit 25665d8

Browse files
author
Akos Kitta
committed
feat: introduced cloud state in sketchbook view
Closes #1879 Closes #1876 Closes #1899 Closes #1878 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 24dc0bb commit 25665d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1948
-647
lines changed

arduino-ide-extension/arduino-icons.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

arduino-ide-extension/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
"@types/js-yaml": "^3.12.2",
5454
"@types/keytar": "^4.4.0",
5555
"@types/lodash.debounce": "^4.0.6",
56-
"@types/ncp": "^2.0.4",
5756
"@types/node-fetch": "^2.5.7",
5857
"@types/p-queue": "^2.3.1",
5958
"@types/ps-tree": "^1.1.0",
@@ -67,6 +66,7 @@
6766
"auth0-js": "^9.14.0",
6867
"btoa": "^1.2.1",
6968
"classnames": "^2.3.1",
69+
"cpy": "^8.1.2",
7070
"cross-fetch": "^3.1.5",
7171
"dateformat": "^3.0.3",
7272
"deepmerge": "2.0.1",
@@ -77,13 +77,13 @@
7777
"glob": "^7.1.6",
7878
"google-protobuf": "^3.20.1",
7979
"hash.js": "^1.1.7",
80+
"is-online": "^9.0.1",
8081
"js-yaml": "^3.13.1",
8182
"just-diff": "^5.1.1",
8283
"jwt-decode": "^3.1.2",
8384
"keytar": "7.2.0",
8485
"lodash.debounce": "^4.0.8",
8586
"minimatch": "^3.1.2",
86-
"ncp": "^2.0.0",
8787
"node-fetch": "^2.6.1",
8888
"open": "^8.0.6",
8989
"p-debounce": "^2.1.0",
@@ -121,6 +121,7 @@
121121
"mocha": "^7.0.0",
122122
"mockdate": "^3.0.5",
123123
"moment": "^2.24.0",
124+
"ncp": "^2.0.0",
124125
"protoc": "^1.0.4",
125126
"shelljs": "^0.8.3",
126127
"uuid": "^3.2.1",

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ import { EditorCommandContribution as TheiaEditorCommandContribution } from '@th
9090
import {
9191
FrontendConnectionStatusService,
9292
ApplicationConnectionStatusContribution,
93+
DaemonPort,
94+
IsOnline,
9395
} from './theia/core/connection-status-service';
9496
import {
9597
FrontendConnectionStatusService as TheiaFrontendConnectionStatusService,
@@ -350,6 +352,7 @@ import { CreateFeatures } from './create/create-features';
350352
import { Account } from './contributions/account';
351353
import { SidebarBottomMenuWidget } from './theia/core/sidebar-bottom-menu-widget';
352354
import { SidebarBottomMenuWidget as TheiaSidebarBottomMenuWidget } from '@theia/core/lib/browser/shell/sidebar-bottom-menu-widget';
355+
import { CreateCloudCopy } from './contributions/create-cloud-copy';
353356

354357
export default new ContainerModule((bind, unbind, isBound, rebind) => {
355358
// Commands and toolbar items
@@ -738,6 +741,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
738741
Contribution.configure(bind, ValidateSketch);
739742
Contribution.configure(bind, RenameCloudSketch);
740743
Contribution.configure(bind, Account);
744+
Contribution.configure(bind, CloudSketchbookContribution);
745+
Contribution.configure(bind, CreateCloudCopy);
741746

742747
bindContributionProvider(bind, StartupTaskProvider);
743748
bind(StartupTaskProvider).toService(BoardsServiceProvider); // to reuse the boards config in another window
@@ -916,8 +921,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
916921
bind(CreateFsProvider).toSelf().inSingletonScope();
917922
bind(FrontendApplicationContribution).toService(CreateFsProvider);
918923
bind(FileServiceContribution).toService(CreateFsProvider);
919-
bind(CloudSketchbookContribution).toSelf().inSingletonScope();
920-
bind(CommandContribution).toService(CloudSketchbookContribution);
921924
bind(LocalCacheFsProvider).toSelf().inSingletonScope();
922925
bind(FileServiceContribution).toService(LocalCacheFsProvider);
923926
bind(CloudSketchbookCompositeWidget).toSelf();
@@ -1021,4 +1024,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
10211024

10221025
bind(SidebarBottomMenuWidget).toSelf();
10231026
rebind(TheiaSidebarBottomMenuWidget).toService(SidebarBottomMenuWidget);
1027+
bind(DaemonPort).toSelf().inSingletonScope();
1028+
bind(FrontendApplicationContribution).toService(DaemonPort);
1029+
bind(IsOnline).toSelf().inSingletonScope();
1030+
bind(FrontendApplicationContribution).toService(IsOnline);
10241031
});

arduino-ide-extension/src/browser/contributions/account.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { inject, injectable } from '@theia/core/shared/inversify';
88
import { CloudUserCommands, LEARN_MORE_URL } from '../auth/cloud-user-commands';
99
import { CreateFeatures } from '../create/create-features';
1010
import { ArduinoMenus } from '../menu/arduino-menus';
11+
import { ApplicationConnectionStatusContribution } from '../theia/core/connection-status-service';
1112
import {
1213
Command,
1314
CommandRegistry,
@@ -29,6 +30,8 @@ export class Account extends Contribution {
2930
private readonly windowService: WindowService;
3031
@inject(CreateFeatures)
3132
private readonly createFeatures: CreateFeatures;
33+
@inject(ApplicationConnectionStatusContribution)
34+
private readonly connectionStatus: ApplicationConnectionStatusContribution;
3235

3336
private readonly toDispose = new DisposableCollection();
3437
private app: FrontendApplication;
@@ -50,21 +53,28 @@ export class Account extends Contribution {
5053
override registerCommands(registry: CommandRegistry): void {
5154
const openExternal = (url: string) =>
5255
this.windowService.openNewWindow(url, { external: true });
56+
const loggedIn = () => Boolean(this.createFeatures.session);
57+
const loggedInWithInternetConnection = () =>
58+
loggedIn() && this.connectionStatus.offlineStatus !== 'internet';
5359
registry.registerCommand(Account.Commands.LEARN_MORE, {
5460
execute: () => openExternal(LEARN_MORE_URL),
55-
isEnabled: () => !Boolean(this.createFeatures.session),
61+
isEnabled: () => !loggedIn(),
62+
isVisible: () => !loggedIn(),
5663
});
5764
registry.registerCommand(Account.Commands.GO_TO_PROFILE, {
5865
execute: () => openExternal('https://id.arduino.cc/'),
59-
isEnabled: () => Boolean(this.createFeatures.session),
66+
isEnabled: () => loggedInWithInternetConnection(),
67+
isVisible: () => loggedIn(),
6068
});
6169
registry.registerCommand(Account.Commands.GO_TO_CLOUD_EDITOR, {
6270
execute: () => openExternal('https://create.arduino.cc/editor'),
63-
isEnabled: () => Boolean(this.createFeatures.session),
71+
isEnabled: () => loggedInWithInternetConnection(),
72+
isVisible: () => loggedIn(),
6473
});
6574
registry.registerCommand(Account.Commands.GO_TO_IOT_CLOUD, {
6675
execute: () => openExternal('https://create.arduino.cc/iot/'),
67-
isEnabled: () => Boolean(this.createFeatures.session),
76+
isEnabled: () => loggedInWithInternetConnection(),
77+
isVisible: () => loggedIn(),
6878
});
6979
}
7080

arduino-ide-extension/src/browser/contributions/cloud-contribution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export abstract class CloudSketchContribution extends SketchContribution {
9393
);
9494
}
9595
try {
96-
await treeModel.sketchbookTree().pull({ node });
96+
await treeModel.sketchbookTree().pull({ node }, true);
9797
return node;
9898
} catch (err) {
9999
if (isNotFound(err)) {

arduino-ide-extension/src/browser/contributions/contribution.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
1414
import { MessageService } from '@theia/core/lib/common/message-service';
1515
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
1616
import { open, OpenerService } from '@theia/core/lib/browser/opener-service';
17-
1817
import {
1918
MenuModelRegistry,
2019
MenuContribution,
@@ -58,7 +57,7 @@ import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
5857
import { ExecuteWithProgress } from '../../common/protocol/progressible';
5958
import { BoardsServiceProvider } from '../boards/boards-service-provider';
6059
import { BoardsDataStore } from '../boards/boards-data-store';
61-
import { NotificationManager } from '../theia/messages/notifications-manager';
60+
import { NotificationManager } from '@theia/messages/lib/browser/notifications-manager';
6261
import { MessageType } from '@theia/core/lib/common/message-service-protocol';
6362
import { WorkspaceService } from '../theia/workspace/workspace-service';
6463
import { MainMenuManager } from '../../common/main-menu-manager';
@@ -295,7 +294,7 @@ export abstract class CoreServiceContribution extends SketchContribution {
295294
}
296295

297296
private notificationId(message: string, ...actions: string[]): string {
298-
return this.notificationManager.getMessageId({
297+
return this.notificationManager['getMessageId']({
299298
text: message,
300299
actions,
301300
type: MessageType.Error,
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
2+
import { ApplicationShell } from '@theia/core/lib/browser/shell';
3+
import type { Command, CommandRegistry } from '@theia/core/lib/common/command';
4+
import { Progress } from '@theia/core/lib/common/message-service-protocol';
5+
import { nls } from '@theia/core/lib/common/nls';
6+
import { inject, injectable } from '@theia/core/shared/inversify';
7+
import { Create } from '../create/typings';
8+
import { ApplicationConnectionStatusContribution } from '../theia/core/connection-status-service';
9+
import { CloudSketchbookTree } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree';
10+
import { SketchbookTree } from '../widgets/sketchbook/sketchbook-tree';
11+
import { SketchbookTreeModel } from '../widgets/sketchbook/sketchbook-tree-model';
12+
import { CloudSketchContribution, pushingSketch } from './cloud-contribution';
13+
import {
14+
CreateNewCloudSketchCallback,
15+
NewCloudSketch,
16+
NewCloudSketchParams,
17+
} from './new-cloud-sketch';
18+
import { saveOntoCopiedSketch } from './save-as-sketch';
19+
20+
interface CreateCloudCopyParams {
21+
readonly model: SketchbookTreeModel;
22+
readonly node: SketchbookTree.SketchDirNode;
23+
}
24+
function isCreateCloudCopyParams(arg: unknown): arg is CreateCloudCopyParams {
25+
return (
26+
typeof arg === 'object' &&
27+
(<CreateCloudCopyParams>arg).model !== undefined &&
28+
(<CreateCloudCopyParams>arg).model instanceof SketchbookTreeModel &&
29+
(<CreateCloudCopyParams>arg).node !== undefined &&
30+
SketchbookTree.SketchDirNode.is((<CreateCloudCopyParams>arg).node)
31+
);
32+
}
33+
34+
@injectable()
35+
export class CreateCloudCopy extends CloudSketchContribution {
36+
@inject(ApplicationConnectionStatusContribution)
37+
private readonly connectionStatus: ApplicationConnectionStatusContribution;
38+
39+
private shell: ApplicationShell;
40+
41+
override onStart(app: FrontendApplication): void {
42+
this.shell = app.shell;
43+
}
44+
45+
override registerCommands(registry: CommandRegistry): void {
46+
registry.registerCommand(CreateCloudCopy.Commands.CREATE_CLOUD_COPY, {
47+
execute: (args: CreateCloudCopyParams) => this.createCloudCopy(args),
48+
isEnabled: (args: unknown) =>
49+
Boolean(this.createFeatures.session) && isCreateCloudCopyParams(args),
50+
isVisible: (args: unknown) =>
51+
Boolean(this.createFeatures.enabled) &&
52+
Boolean(this.createFeatures.session) &&
53+
this.connectionStatus.offlineStatus !== 'internet' &&
54+
isCreateCloudCopyParams(args),
55+
});
56+
}
57+
58+
/**
59+
* - creates new cloud sketch with the name of the params sketch,
60+
* - pulls the cloud sketch,
61+
* - copies files from params sketch to pulled cloud sketch in the cache folder,
62+
* - pushes the cloud sketch, and
63+
* - opens in new window.
64+
*/
65+
private async createCloudCopy(params: CreateCloudCopyParams): Promise<void> {
66+
const sketch = await this.sketchesService.loadSketch(
67+
params.node.fileStat.resource.toString()
68+
);
69+
const callback: CreateNewCloudSketchCallback = async (
70+
newSketch: Create.Sketch,
71+
newNode: CloudSketchbookTree.CloudSketchDirNode,
72+
progress: Progress
73+
) => {
74+
const treeModel = await this.treeModel();
75+
if (!treeModel) {
76+
throw new Error('Could not retrieve the cloud sketchbook tree model.');
77+
}
78+
79+
progress.report({
80+
message: nls.localize(
81+
'arduino/createCloudCopy/copyingSketchFilesMessage',
82+
'Copying local sketch files...'
83+
),
84+
});
85+
const localCacheFolderUri = newNode.uri.toString();
86+
await this.sketchesService.copy(sketch, {
87+
destinationUri: localCacheFolderUri,
88+
onlySketchFiles: true,
89+
});
90+
await saveOntoCopiedSketch(
91+
sketch,
92+
localCacheFolderUri,
93+
this.shell,
94+
this.editorManager
95+
);
96+
97+
progress.report({ message: pushingSketch(newSketch.name) });
98+
await treeModel.sketchbookTree().push(newNode, true);
99+
};
100+
return this.commandService.executeCommand(
101+
NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
102+
<NewCloudSketchParams>{
103+
initialValue: params.node.fileStat.name,
104+
callback,
105+
skipShowErrorMessageOnOpen: false,
106+
}
107+
);
108+
}
109+
}
110+
111+
export namespace CreateCloudCopy {
112+
export namespace Commands {
113+
export const CREATE_CLOUD_COPY: Command = {
114+
id: 'arduino-create-cloud-copy',
115+
iconClass: 'fa fa-arduino-cloud-upload',
116+
};
117+
}
118+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy