ATL-1064: Support for nested sketchbook structure

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta
2021-03-10 17:30:58 +01:00
committed by Akos Kitta
parent ac502053d7
commit c64ac48fe3
9 changed files with 188 additions and 116 deletions

View File

@@ -1,14 +1,10 @@
import { Sketch } from './sketches-service';
import { SketchContainer } from './sketches-service';
export const ExamplesServicePath = '/services/example-service';
export const ExamplesService = Symbol('ExamplesService');
export interface ExamplesService {
builtIns(): Promise<ExampleContainer[]>;
installed(options: { fqbn: string }): Promise<{ user: ExampleContainer[], current: ExampleContainer[], any: ExampleContainer[] }>;
builtIns(): Promise<SketchContainer[]>;
installed(options: { fqbn: string }): Promise<{ user: SketchContainer[], current: SketchContainer[], any: SketchContainer[] }>;
}
export interface ExampleContainer {
readonly label: string;
readonly children: ExampleContainer[];
readonly sketches: Sketch[];
}

View File

@@ -9,6 +9,7 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser';
import { ConfigService } from './config-service';
import { DisposableCollection, Emitter } from '@theia/core';
import { FileChangeType } from '@theia/filesystem/lib/browser';
import { SketchContainer } from './sketches-service';
@injectable()
export class SketchesServiceClientImpl implements FrontendApplicationContribution {
@@ -35,9 +36,9 @@ export class SketchesServiceClientImpl implements FrontendApplicationContributio
onStart(): void {
this.configService.getConfiguration().then(({ sketchDirUri }) => {
this.sketchService.getSketches(sketchDirUri).then(sketches => {
this.sketchService.getSketches({ uri: sketchDirUri }).then(container => {
const sketchbookUri = new URI(sketchDirUri);
for (const sketch of sketches) {
for (const sketch of SketchContainer.toArray(container)) {
this.sketches.set(sketch.uri, sketch);
}
this.toDispose.push(this.fileService.watch(new URI(sketchDirUri), { recursive: true, excludes: [] }));

View File

@@ -5,10 +5,11 @@ export const SketchesService = Symbol('SketchesService');
export interface SketchesService {
/**
* Returns with the direct sketch folders from the location of the `fileStat`.
* The sketches returns with inverse-chronological order, the first item is the most recent one.
* Resolves to a sketch container representing the hierarchical structure of the sketches.
* If `uri` is not given, `directories.user` will be user instead. Specify `exclude` global patterns to filter folders from the sketch container.
* If `exclude` is not set `['**\/libraries\/**', '**\/hardware\/**']` will be used instead.
*/
getSketches(uri?: string): Promise<Sketch[]>;
getSketches({ uri, exclude }: { uri?: string, exclude?: string[] }): Promise<SketchContainer>;
/**
* This is the TS implementation of `SketchLoad` from the CLI and should be replaced with a gRPC call eventually.
@@ -100,3 +101,51 @@ export namespace Sketch {
return Extensions.MAIN.some(ext => arg.endsWith(ext));
}
}
export interface SketchContainer {
readonly label: string;
readonly children: SketchContainer[];
readonly sketches: Sketch[];
}
export namespace SketchContainer {
export function is(arg: any): arg is SketchContainer {
return !!arg
&& 'label' in arg && typeof arg.label === 'string'
&& 'children' in arg && Array.isArray(arg.children)
&& 'sketches' in arg && Array.isArray(arg.sketches);
}
/**
* `false` if the `container` recursively contains at least one sketch. Otherwise, `true`.
*/
export function isEmpty(container: SketchContainer): boolean {
const hasSketch = (parent: SketchContainer) => {
if (parent.sketches.length || parent.children.some(child => hasSketch(child))) {
return true;
}
return false;
}
return !hasSketch(container);
}
export function prune<T extends SketchContainer>(container: T): T {
for (let i = container.children.length - 1; i >= 0; i--) {
if (isEmpty(container.children[i])) {
container.children.splice(i, 1);
}
}
return container;
}
export function toArray(container: SketchContainer): Sketch[] {
const visit = (parent: SketchContainer, toPushSketch: Sketch[]) => {
toPushSketch.push(...parent.sketches);
parent.children.map(child => visit(child, toPushSketch));
}
const sketches: Sketch[] = [];
visit(container, sketches);
return sketches;
}
}