Skip to content

Commit

Permalink
feat: introduced cloud state in sketchbook view
Browse files Browse the repository at this point in the history
Closes #1879
Closes #1876
Closes #1899
Closes #1878

Signed-off-by: Akos Kitta <[email protected]>
  • Loading branch information
Akos Kitta authored and kittaakos committed Mar 16, 2023
1 parent b09ae48 commit 0ab2826
Show file tree
Hide file tree
Showing 53 changed files with 1,963 additions and 651 deletions.
2 changes: 1 addition & 1 deletion arduino-ide-extension/arduino-icons.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions arduino-ide-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
"@types/js-yaml": "^3.12.2",
"@types/keytar": "^4.4.0",
"@types/lodash.debounce": "^4.0.6",
"@types/ncp": "^2.0.4",
"@types/node-fetch": "^2.5.7",
"@types/p-queue": "^2.3.1",
"@types/ps-tree": "^1.1.0",
Expand All @@ -66,6 +65,7 @@
"auth0-js": "^9.14.0",
"btoa": "^1.2.1",
"classnames": "^2.3.1",
"cpy": "^8.1.2",
"cross-fetch": "^3.1.5",
"dateformat": "^3.0.3",
"deepmerge": "2.0.1",
Expand All @@ -76,14 +76,14 @@
"glob": "^7.1.6",
"google-protobuf": "^3.20.1",
"hash.js": "^1.1.7",
"is-online": "^9.0.1",
"js-yaml": "^3.13.1",
"jsonc-parser": "^2.2.0",
"just-diff": "^5.1.1",
"jwt-decode": "^3.1.2",
"keytar": "7.2.0",
"lodash.debounce": "^4.0.8",
"minimatch": "^3.1.2",
"ncp": "^2.0.0",
"node-fetch": "^2.6.1",
"open": "^8.0.6",
"p-debounce": "^2.1.0",
Expand Down Expand Up @@ -120,6 +120,7 @@
"mocha": "^7.0.0",
"mockdate": "^3.0.5",
"moment": "^2.24.0",
"ncp": "^2.0.0",
"protoc": "^1.0.4",
"shelljs": "^0.8.3",
"uuid": "^3.2.1",
Expand Down
12 changes: 10 additions & 2 deletions arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ import { EditorCommandContribution as TheiaEditorCommandContribution } from '@th
import {
FrontendConnectionStatusService,
ApplicationConnectionStatusContribution,
DaemonPort,
IsOnline,
} from './theia/core/connection-status-service';
import {
FrontendConnectionStatusService as TheiaFrontendConnectionStatusService,
Expand Down Expand Up @@ -353,6 +355,7 @@ import { CreateFeatures } from './create/create-features';
import { Account } from './contributions/account';
import { SidebarBottomMenuWidget } from './theia/core/sidebar-bottom-menu-widget';
import { SidebarBottomMenuWidget as TheiaSidebarBottomMenuWidget } from '@theia/core/lib/browser/shell/sidebar-bottom-menu-widget';
import { CreateCloudCopy } from './contributions/create-cloud-copy';

export default new ContainerModule((bind, unbind, isBound, rebind) => {
// Commands and toolbar items
Expand Down Expand Up @@ -741,6 +744,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
Contribution.configure(bind, ValidateSketch);
Contribution.configure(bind, RenameCloudSketch);
Contribution.configure(bind, Account);
Contribution.configure(bind, CloudSketchbookContribution);
Contribution.configure(bind, CreateCloudCopy);

bindContributionProvider(bind, StartupTaskProvider);
bind(StartupTaskProvider).toService(BoardsServiceProvider); // to reuse the boards config in another window
Expand Down Expand Up @@ -919,8 +924,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(CreateFsProvider).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(CreateFsProvider);
bind(FileServiceContribution).toService(CreateFsProvider);
bind(CloudSketchbookContribution).toSelf().inSingletonScope();
bind(CommandContribution).toService(CloudSketchbookContribution);
bind(LocalCacheFsProvider).toSelf().inSingletonScope();
bind(FileServiceContribution).toService(LocalCacheFsProvider);
bind(CloudSketchbookCompositeWidget).toSelf();
Expand Down Expand Up @@ -1026,4 +1029,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
rebind(TheiaSidebarBottomMenuWidget).toService(SidebarBottomMenuWidget);

bind(ArduinoComponentContextMenuRenderer).toSelf().inSingletonScope();

bind(DaemonPort).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(DaemonPort);
bind(IsOnline).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(IsOnline);
});
18 changes: 14 additions & 4 deletions arduino-ide-extension/src/browser/contributions/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { inject, injectable } from '@theia/core/shared/inversify';
import { CloudUserCommands, LEARN_MORE_URL } from '../auth/cloud-user-commands';
import { CreateFeatures } from '../create/create-features';
import { ArduinoMenus } from '../menu/arduino-menus';
import { ApplicationConnectionStatusContribution } from '../theia/core/connection-status-service';
import {
Command,
CommandRegistry,
Expand All @@ -29,6 +30,8 @@ export class Account extends Contribution {
private readonly windowService: WindowService;
@inject(CreateFeatures)
private readonly createFeatures: CreateFeatures;
@inject(ApplicationConnectionStatusContribution)
private readonly connectionStatus: ApplicationConnectionStatusContribution;

private readonly toDispose = new DisposableCollection();
private app: FrontendApplication;
Expand All @@ -50,21 +53,28 @@ export class Account extends Contribution {
override registerCommands(registry: CommandRegistry): void {
const openExternal = (url: string) =>
this.windowService.openNewWindow(url, { external: true });
const loggedIn = () => Boolean(this.createFeatures.session);
const loggedInWithInternetConnection = () =>
loggedIn() && this.connectionStatus.offlineStatus !== 'internet';
registry.registerCommand(Account.Commands.LEARN_MORE, {
execute: () => openExternal(LEARN_MORE_URL),
isEnabled: () => !Boolean(this.createFeatures.session),
isEnabled: () => !loggedIn(),
isVisible: () => !loggedIn(),
});
registry.registerCommand(Account.Commands.GO_TO_PROFILE, {
execute: () => openExternal('https://id.arduino.cc/'),
isEnabled: () => Boolean(this.createFeatures.session),
isEnabled: () => loggedInWithInternetConnection(),
isVisible: () => loggedIn(),
});
registry.registerCommand(Account.Commands.GO_TO_CLOUD_EDITOR, {
execute: () => openExternal('https://create.arduino.cc/editor'),
isEnabled: () => Boolean(this.createFeatures.session),
isEnabled: () => loggedInWithInternetConnection(),
isVisible: () => loggedIn(),
});
registry.registerCommand(Account.Commands.GO_TO_IOT_CLOUD, {
execute: () => openExternal('https://create.arduino.cc/iot/'),
isEnabled: () => Boolean(this.createFeatures.session),
isEnabled: () => loggedInWithInternetConnection(),
isVisible: () => loggedIn(),
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export abstract class CloudSketchContribution extends SketchContribution {
);
}
try {
await treeModel.sketchbookTree().pull({ node });
await treeModel.sketchbookTree().pull({ node }, true);
return node;
} catch (err) {
if (isNotFound(err)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
import { MessageService } from '@theia/core/lib/common/message-service';
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
import { open, OpenerService } from '@theia/core/lib/browser/opener-service';

import {
MenuModelRegistry,
MenuContribution,
Expand Down Expand Up @@ -58,7 +57,7 @@ import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
import { ExecuteWithProgress } from '../../common/protocol/progressible';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import { BoardsDataStore } from '../boards/boards-data-store';
import { NotificationManager } from '../theia/messages/notifications-manager';
import { NotificationManager } from '@theia/messages/lib/browser/notifications-manager';
import { MessageType } from '@theia/core/lib/common/message-service-protocol';
import { WorkspaceService } from '../theia/workspace/workspace-service';
import { MainMenuManager } from '../../common/main-menu-manager';
Expand Down Expand Up @@ -295,7 +294,7 @@ export abstract class CoreServiceContribution extends SketchContribution {
}

private notificationId(message: string, ...actions: string[]): string {
return this.notificationManager.getMessageId({
return this.notificationManager['getMessageId']({
text: message,
actions,
type: MessageType.Error,
Expand Down
118 changes: 118 additions & 0 deletions arduino-ide-extension/src/browser/contributions/create-cloud-copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
import { ApplicationShell } from '@theia/core/lib/browser/shell';
import type { Command, CommandRegistry } from '@theia/core/lib/common/command';
import { Progress } from '@theia/core/lib/common/message-service-protocol';
import { nls } from '@theia/core/lib/common/nls';
import { inject, injectable } from '@theia/core/shared/inversify';
import { Create } from '../create/typings';
import { ApplicationConnectionStatusContribution } from '../theia/core/connection-status-service';
import { CloudSketchbookTree } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree';
import { SketchbookTree } from '../widgets/sketchbook/sketchbook-tree';
import { SketchbookTreeModel } from '../widgets/sketchbook/sketchbook-tree-model';
import { CloudSketchContribution, pushingSketch } from './cloud-contribution';
import {
CreateNewCloudSketchCallback,
NewCloudSketch,
NewCloudSketchParams,
} from './new-cloud-sketch';
import { saveOntoCopiedSketch } from './save-as-sketch';

interface CreateCloudCopyParams {
readonly model: SketchbookTreeModel;
readonly node: SketchbookTree.SketchDirNode;
}
function isCreateCloudCopyParams(arg: unknown): arg is CreateCloudCopyParams {
return (
typeof arg === 'object' &&
(<CreateCloudCopyParams>arg).model !== undefined &&
(<CreateCloudCopyParams>arg).model instanceof SketchbookTreeModel &&
(<CreateCloudCopyParams>arg).node !== undefined &&
SketchbookTree.SketchDirNode.is((<CreateCloudCopyParams>arg).node)
);
}

@injectable()
export class CreateCloudCopy extends CloudSketchContribution {
@inject(ApplicationConnectionStatusContribution)
private readonly connectionStatus: ApplicationConnectionStatusContribution;

private shell: ApplicationShell;

override onStart(app: FrontendApplication): void {
this.shell = app.shell;
}

override registerCommands(registry: CommandRegistry): void {
registry.registerCommand(CreateCloudCopy.Commands.CREATE_CLOUD_COPY, {
execute: (args: CreateCloudCopyParams) => this.createCloudCopy(args),
isEnabled: (args: unknown) =>
Boolean(this.createFeatures.session) && isCreateCloudCopyParams(args),
isVisible: (args: unknown) =>
Boolean(this.createFeatures.enabled) &&
Boolean(this.createFeatures.session) &&
this.connectionStatus.offlineStatus !== 'internet' &&
isCreateCloudCopyParams(args),
});
}

/**
* - creates new cloud sketch with the name of the params sketch,
* - pulls the cloud sketch,
* - copies files from params sketch to pulled cloud sketch in the cache folder,
* - pushes the cloud sketch, and
* - opens in new window.
*/
private async createCloudCopy(params: CreateCloudCopyParams): Promise<void> {
const sketch = await this.sketchesService.loadSketch(
params.node.fileStat.resource.toString()
);
const callback: CreateNewCloudSketchCallback = async (
newSketch: Create.Sketch,
newNode: CloudSketchbookTree.CloudSketchDirNode,
progress: Progress
) => {
const treeModel = await this.treeModel();
if (!treeModel) {
throw new Error('Could not retrieve the cloud sketchbook tree model.');
}

progress.report({
message: nls.localize(
'arduino/createCloudCopy/copyingSketchFilesMessage',
'Copying local sketch files...'
),
});
const localCacheFolderUri = newNode.uri.toString();
await this.sketchesService.copy(sketch, {
destinationUri: localCacheFolderUri,
onlySketchFiles: true,
});
await saveOntoCopiedSketch(
sketch,
localCacheFolderUri,
this.shell,
this.editorManager
);

progress.report({ message: pushingSketch(newSketch.name) });
await treeModel.sketchbookTree().push(newNode, true, true);
};
return this.commandService.executeCommand(
NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
<NewCloudSketchParams>{
initialValue: params.node.fileStat.name,
callback,
skipShowErrorMessageOnOpen: false,
}
);
}
}

export namespace CreateCloudCopy {
export namespace Commands {
export const CREATE_CLOUD_COPY: Command = {
id: 'arduino-create-cloud-copy',
iconClass: 'fa fa-arduino-cloud-upload',
};
}
}
Loading

0 comments on commit 0ab2826

Please sign in to comment.