Skip to content

Commit

Permalink
fix: editor toolbar enablement
Browse files Browse the repository at this point in the history
Signed-off-by: Akos Kitta <[email protected]>
  • Loading branch information
Akos Kitta committed Feb 24, 2023
1 parent 93e2082 commit 124f0c4
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 47 deletions.
59 changes: 56 additions & 3 deletions arduino-ide-extension/src/browser/create/create-features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { AuthenticationSession } from '../../node/auth/types';
import { ArduinoPreferences } from '../arduino-preferences';
import { AuthenticationClientService } from '../auth/authentication-client-service';
import { LocalCacheFsProvider } from '../local-cache/local-cache-fs-provider';
import { CreateUri } from './create-uri';

export type CloudSketchState = 'push' | 'pull';

@injectable()
export class CreateFeatures implements FrontendApplicationContribution {
Expand All @@ -18,13 +21,22 @@ export class CreateFeatures implements FrontendApplicationContribution {
@inject(LocalCacheFsProvider)
private readonly localCacheFsProvider: LocalCacheFsProvider;

/**
* The keys are the Create URI of the sketches.
*/
private readonly _cloudSketchStates = new Map<string, CloudSketchState>();
private readonly onDidChangeSessionEmitter = new Emitter<
AuthenticationSession | undefined
>();
private readonly onDidChangeEnabledEmitter = new Emitter<boolean>();
private readonly onDidChangeCloudSketchStateEmitter = new Emitter<{
uri: URI;
state: CloudSketchState | undefined;
}>();
private readonly toDispose = new DisposableCollection(
this.onDidChangeSessionEmitter,
this.onDidChangeEnabledEmitter
this.onDidChangeEnabledEmitter,
this.onDidChangeCloudSketchStateEmitter
);
private _enabled: boolean;
private _session: AuthenticationSession | undefined;
Expand Down Expand Up @@ -64,14 +76,55 @@ export class CreateFeatures implements FrontendApplicationContribution {
return this.onDidChangeEnabledEmitter.event;
}

get enabled(): boolean {
return this._enabled;
get onDidChangeCloudSketchState(): Event<{
uri: URI;
state: CloudSketchState | undefined;
}> {
return this.onDidChangeCloudSketchStateEmitter.event;
}

get session(): AuthenticationSession | undefined {
return this._session;
}

get enabled(): boolean {
return this._enabled;
}

get cloudSketchStates(): {
uri: URI;
state: CloudSketchState | undefined;
}[] {
return Array.from(this._cloudSketchStates.entries()).map(
([uri, state]) => ({ uri: new URI(uri), state })
);
}

cloudSketchState(uri: URI): CloudSketchState | undefined {
return this._cloudSketchStates.get(uri.toString());
}

setCloudSketchState(uri: URI, state: CloudSketchState | undefined): void {
if (uri.scheme !== CreateUri.scheme) {
throw new Error(
`Expected a URI with '${uri.scheme}' scheme. Got: ${uri.toString()}`
);
}
const key = uri.toString();
if (!state) {
if (!this._cloudSketchStates.delete(key)) {
console.warn(
`Could not reset the cloud sketch state of ${key}. No state existed for the the cloud sketch.`
);
} else {
this.onDidChangeCloudSketchStateEmitter.fire({ uri, state: undefined });
}
} else {
this._cloudSketchStates.set(key, state);
this.onDidChangeCloudSketchStateEmitter.fire({ uri, state });
}
}

/**
* `true` if the sketch is under `directories.data/RemoteSketchbook`. Otherwise, `false`.
* Returns with `undefined` if `dataDirUri` is `undefined`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
import {
ContextMenuRenderer,
RenderContextMenuOptions,
Expand Down Expand Up @@ -34,6 +33,7 @@ import { ApplicationConnectionStatusContribution } from '../../theia/core/connec
import { SketchbookCommands } from '../sketchbook/sketchbook-commands';
import { CloudSketchbookCommands } from './cloud-sketchbook-commands';
import { CloudSketchbookTree } from './cloud-sketchbook-tree';
import { CreateUri } from '../../create/create-uri';

const SKETCHBOOKSYNC__CONTEXT = ['arduino-sketchbook-sync--context'];

Expand Down Expand Up @@ -61,8 +61,6 @@ export class CloudSketchbookContribution extends CloudSketchContribution {
private readonly configServiceClient: ConfigServiceClient;
@inject(ApplicationConnectionStatusContribution)
private readonly connectionStatus: ApplicationConnectionStatusContribution;
@inject(ContextKeyService)
private readonly contextKeyService: ContextKeyService;

private readonly onDidChangeToolbarEmitter = new Emitter<void>();
private readonly toDisposeBeforeNewContextMenu = new DisposableCollection();
Expand All @@ -82,17 +80,9 @@ export class CloudSketchbookContribution extends CloudSketchContribution {
}),
this.createFeatures.onDidChangeSession(() => this.fireToolbarChange()),
this.createFeatures.onDidChangeEnabled(() => this.fireToolbarChange()),
this.contextKeyService.onDidChange((event) => {
if (
event.affects({
has(candidate: string) {
return candidate === 'cloudSketchState';
},
})
) {
this.fireToolbarChange();
}
}),
this.createFeatures.onDidChangeCloudSketchState(() =>
this.fireToolbarChange()
),
]);
}

Expand All @@ -115,15 +105,13 @@ export class CloudSketchbookContribution extends CloudSketchContribution {
tooltip: CloudSketchbookCommands.PULL_SKETCH__TOOLBAR.label,
priority: -2,
onDidChange: this.onDidChangeToolbar,
when: 'cloudSketchState != pulling && cloudSketchState != pushing',
});
registry.registerItem({
id: CloudSketchbookCommands.PUSH_SKETCH__TOOLBAR.id,
command: CloudSketchbookCommands.PUSH_SKETCH__TOOLBAR.id,
tooltip: CloudSketchbookCommands.PUSH_SKETCH__TOOLBAR.label,
priority: -1,
onDidChange: this.onDidChangeToolbar,
when: 'cloudSketchState != pulling && cloudSketchState != pushing',
});
}

Expand Down Expand Up @@ -341,7 +329,17 @@ export class CloudSketchbookContribution extends CloudSketchContribution {
if (this.connectionStatus.offlineStatus === 'internet') {
return false;
}
return true;
// no pull/push context for the current cloud sketch
const sketch = this.currentCloudSketch;
if (sketch) {
const cloudUri = this.createFeatures.cloudUri(sketch);
if (cloudUri) {
return !this.createFeatures.cloudSketchState(
CreateUri.toUri(cloudUri.path.toString())
);
}
}
return false;
}

private isCloudSketchDirNodeCommandArg(
Expand All @@ -351,7 +349,8 @@ export class CloudSketchbookContribution extends CloudSketchContribution {
} {
return (
CloudSketchbookCommands.Arg.is(arg) &&
CloudSketchbookTree.CloudSketchDirNode.is(arg.node)
CloudSketchbookTree.CloudSketchDirNode.is(arg.node) &&
!this.createFeatures.cloudSketchState(arg.node.remoteUri)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ import {
pullingSketch,
pushingSketch,
} from '../../contributions/cloud-contribution';
import {
ContextKey,
ContextKeyService,
} from '@theia/core/lib/browser/context-key-service';
import { CloudSketchState, CreateFeatures } from '../../create/create-features';

const MESSAGE_TIMEOUT = 5 * 1000;
const deepmerge = require('deepmerge').default;
Expand All @@ -67,19 +64,13 @@ export class CloudSketchbookTree extends SketchbookTree {
@inject(ApplicationConnectionStatusContribution)
private readonly connectionStatus: ApplicationConnectionStatusContribution;

@inject(ContextKeyService)
private readonly contextKeyService: ContextKeyService;

private cloudSketchState: ContextKey<string> | undefined;
@inject(CreateFeatures)
private readonly createFeatures: CreateFeatures;

protected override init(): void {
this.toDispose.push(
this.connectionStatus.onOfflineStatusDidChange(() => this.refresh())
);
this.cloudSketchState = this.contextKeyService.createKey<string>(
'cloudSketchState',
undefined
);
super.init();
}

Expand Down Expand Up @@ -149,7 +140,7 @@ export class CloudSketchbookTree extends SketchbookTree {
}
return this.runWithState(
node,
'pulling',
'pull',
async (node) => {
const commandsCopy = node.commands;
node.commands = [];
Expand Down Expand Up @@ -217,7 +208,7 @@ export class CloudSketchbookTree extends SketchbookTree {
}
return this.runWithState(
node,
'pushing',
'push',
async (node) => {
if (!CloudSketchbookTree.CloudSketchTreeNode.isSynced(node)) {
throw new Error(
Expand Down Expand Up @@ -352,11 +343,11 @@ export class CloudSketchbookTree extends SketchbookTree {

private async runWithState<T>(
node: CloudSketchbookTree.CloudSketchDirNode & Partial<DecoratedTreeNode>,
state: CloudSketchbookTree.CloudSketchDirNode.State,
state: CloudSketchState,
task: (node: CloudSketchbookTree.CloudSketchDirNode) => MaybePromise<T>,
noProgress = false
): Promise<T> {
this.cloudSketchState?.set(state);
this.createFeatures.setCloudSketchState(node.remoteUri, state);
try {
const result = await (noProgress
? task(node)
Expand All @@ -371,18 +362,15 @@ export class CloudSketchbookTree extends SketchbookTree {
await this.refresh(node);
return result;
} finally {
this.cloudSketchState?.set(undefined);
this.createFeatures.setCloudSketchState(node.remoteUri, undefined);
}
}

private taskMessage(
state: CloudSketchbookTree.CloudSketchDirNode.State,
input: string
): string {
private taskMessage(state: CloudSketchState, input: string): string {
switch (state) {
case 'pulling':
case 'pull':
return pullingSketch(input);
case 'pushing':
case 'push':
return pushingSketch(input);
default:
assertUnreachable(state);
Expand Down Expand Up @@ -700,7 +688,7 @@ export namespace CloudSketchbookTree {
export interface CloudSketchDirNode
extends Omit<SketchbookTree.SketchDirNode, 'fileStat'>,
CloudSketchTreeNode {
state?: CloudSketchDirNode.State;
state?: CloudSketchState;
isPublic?: boolean;
sketchId?: string;
commands?: Command[];
Expand All @@ -709,7 +697,5 @@ export namespace CloudSketchbookTree {
export function is(node: TreeNode | undefined): node is CloudSketchDirNode {
return SketchbookTree.SketchDirNode.is(node);
}

export type State = 'pulling' | 'pushing';
}
}

0 comments on commit 124f0c4

Please sign in to comment.