Skip to content

Commit 19a57e9

Browse files
author
Akos Kitta
committed
Link resolved for lib/boards manager.
Closes #1442 Signed-off-by: Akos Kitta <[email protected]>
1 parent 42f6f43 commit 19a57e9

File tree

6 files changed

+168
-26
lines changed

6 files changed

+168
-26
lines changed

Diff for: arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+3
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ import { OutputEditorFactory } from './theia/output/output-editor-factory';
338338
import { StartupTaskProvider } from '../electron-common/startup-task';
339339
import { DeleteSketch } from './contributions/delete-sketch';
340340
import { UserFields } from './contributions/user-fields';
341+
import { OpenHandler } from '@theia/core/lib/browser/opener-service';
341342

342343
const registerArduinoThemes = () => {
343344
const themes: MonacoThemeJson[] = [
@@ -402,6 +403,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
402403
bind(FrontendApplicationContribution).toService(
403404
LibraryListWidgetFrontendContribution
404405
);
406+
bind(OpenHandler).toService(LibraryListWidgetFrontendContribution);
405407

406408
// Sketch list service
407409
bind(SketchesService)
@@ -468,6 +470,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
468470
bind(FrontendApplicationContribution).toService(
469471
BoardsListWidgetFrontendContribution
470472
);
473+
bind(OpenHandler).toService(BoardsListWidgetFrontendContribution);
471474

472475
// Board select dialog
473476
bind(BoardsConfigDialogWidget).toSelf().inSingletonScope();

Diff for: arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { injectable } from '@theia/core/shared/inversify';
22
import { BoardsListWidget } from './boards-list-widget';
3-
import type {
3+
import {
44
BoardSearch,
55
BoardsPackage,
66
} from '../../common/protocol/boards-service';
@@ -11,6 +11,8 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont
1111
BoardsPackage,
1212
BoardSearch
1313
> {
14+
protected readonly openerAuthority = 'boardsmanager';
15+
1416
constructor() {
1517
super({
1618
widgetId: BoardsListWidget.WIDGET_ID,
@@ -24,7 +26,22 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont
2426
});
2527
}
2628

27-
override async initializeLayout(): Promise<void> {
28-
this.openView();
29+
protected parsePath(path: string): Omit<BoardSearch, 'query'> | undefined {
30+
const segments = this.normalizedSegmentsOf(path);
31+
if (segments.length !== 1) {
32+
return undefined;
33+
}
34+
const [type] = segments;
35+
if (!type) {
36+
return {
37+
type: 'All',
38+
};
39+
}
40+
if (BoardSearch.Type.is(type)) {
41+
return {
42+
type,
43+
};
44+
}
45+
return undefined;
2946
}
3047
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
import { nls } from '@theia/core/lib/common';
2+
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
13
import { injectable } from '@theia/core/shared/inversify';
2-
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
3-
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
4-
import { MenuModelRegistry } from '@theia/core';
5-
import { LibraryListWidget } from './library-list-widget';
4+
import { LibraryPackage, LibrarySearch } from '../../common/protocol';
65
import { ArduinoMenus } from '../menu/arduino-menus';
7-
import { nls } from '@theia/core/lib/common';
6+
import { ListWidgetFrontendContribution } from '../widgets/component-list/list-widget-frontend-contribution';
7+
import { LibraryListWidget } from './library-list-widget';
88

99
@injectable()
10-
export class LibraryListWidgetFrontendContribution
11-
extends AbstractViewContribution<LibraryListWidget>
12-
implements FrontendApplicationContribution
13-
{
10+
export class LibraryListWidgetFrontendContribution extends ListWidgetFrontendContribution<
11+
LibraryPackage,
12+
LibrarySearch
13+
> {
14+
protected readonly openerAuthority = 'librarymanager';
15+
1416
constructor() {
1517
super({
1618
widgetId: LibraryListWidget.WIDGET_ID,
@@ -24,10 +26,6 @@ export class LibraryListWidgetFrontendContribution
2426
});
2527
}
2628

27-
async initializeLayout(): Promise<void> {
28-
this.openView();
29-
}
30-
3129
override registerMenus(menus: MenuModelRegistry): void {
3230
if (this.toggleCommand) {
3331
menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, {
@@ -40,4 +38,46 @@ export class LibraryListWidgetFrontendContribution
4038
});
4139
}
4240
}
41+
42+
protected parsePath(path: string): Omit<LibrarySearch, 'query'> | undefined {
43+
const segments = this.normalizedSegmentsOf(path);
44+
// Special magic handling for `Signal Input/Output`.
45+
// TODO: IDE2 deserves better lib/boards URL spec
46+
// https://github.com/arduino/arduino-ide/issues/1442#issuecomment-1252136377
47+
if (segments.length === 3) {
48+
const [type, topicHead, topicTail] = segments;
49+
const maybeTopic = `${topicHead}/${topicTail}`;
50+
if (
51+
LibrarySearch.Topic.is(maybeTopic) &&
52+
maybeTopic === 'Signal Input/Output' &&
53+
LibrarySearch.Type.is(type)
54+
) {
55+
return {
56+
type,
57+
topic: maybeTopic,
58+
};
59+
}
60+
}
61+
const [type, topic] = segments;
62+
if (!type && !topic) {
63+
return {
64+
type: 'All',
65+
topic: 'All',
66+
};
67+
}
68+
if (LibrarySearch.Type.is(type)) {
69+
if (!topic) {
70+
return {
71+
type,
72+
};
73+
}
74+
if (LibrarySearch.Topic.is(topic)) {
75+
return {
76+
type,
77+
topic,
78+
};
79+
}
80+
}
81+
return undefined;
82+
}
4383
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,85 @@
1-
import { injectable } from '@theia/core/shared/inversify';
21
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
2+
import {
3+
OpenerOptions,
4+
OpenHandler,
5+
} from '@theia/core/lib/browser/opener-service';
36
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
7+
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
8+
import { URI } from '@theia/core/lib/common/uri';
9+
import { injectable } from '@theia/core/shared/inversify';
10+
import { Searchable } from '../../../common/protocol';
411
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
512
import { ListWidget } from './list-widget';
6-
import { Searchable } from '../../../common/protocol';
713

814
@injectable()
915
export abstract class ListWidgetFrontendContribution<
1016
T extends ArduinoComponent,
1117
S extends Searchable.Options
1218
>
1319
extends AbstractViewContribution<ListWidget<T, S>>
14-
implements FrontendApplicationContribution
20+
implements FrontendApplicationContribution, OpenHandler
1521
{
22+
protected abstract readonly openerAuthority: string;
23+
readonly id: string = `http-opener-${this.viewId}`;
24+
1625
async initializeLayout(): Promise<void> {
17-
// TS requires at least one method from `FrontendApplicationContribution`.
18-
// Expected to be empty.
26+
this.openView();
1927
}
2028

21-
override registerMenus(): void {
29+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
30+
override registerMenus(_: MenuModelRegistry): void {
2231
// NOOP
2332
}
33+
34+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
35+
canHandle(uri: URI, _?: OpenerOptions): number {
36+
// `500` is the default HTTP opener in Theia. IDE2 has higher priority.
37+
// https://github.com/eclipse-theia/theia/blob/b75b6144b0ffea06a549294903c374fa642135e4/packages/core/src/browser/http-open-handler.ts#L39
38+
return uri.scheme === 'http' && uri.authority === this.openerAuthority
39+
? 501
40+
: 0;
41+
}
42+
43+
async open(
44+
uri: URI,
45+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
46+
_?: OpenerOptions | undefined
47+
): Promise<void> {
48+
const searchOptions = this.parse(uri);
49+
if (!searchOptions) {
50+
console.warn(
51+
`Failed to parse URI into a search options. URI: ${uri.toString()}`
52+
);
53+
return;
54+
}
55+
56+
const widget = await this.openView({
57+
activate: true,
58+
reveal: true,
59+
});
60+
if (!widget) {
61+
console.warn(`Failed to open view for URI: ${uri.toString()}`);
62+
return;
63+
}
64+
65+
widget.refresh(searchOptions);
66+
}
67+
68+
protected parse(uri: URI): S | undefined {
69+
const refinements = this.parsePath(new URL(uri.toString()).pathname);
70+
if (!refinements) {
71+
return undefined;
72+
}
73+
return { ...refinements, query: uri.fragment } as S;
74+
}
75+
76+
protected normalizedSegmentsOf(path: string): string[] {
77+
// /
78+
// /All
79+
// /All/Device%20Control
80+
// /All/Display
81+
return path.split('/').slice(1).map(decodeURIComponent);
82+
}
83+
84+
protected abstract parsePath(path: string): Omit<S, 'query'> | undefined;
2485
}

Diff for: arduino-ide-extension/src/common/protocol/boards-service.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { Searchable } from './searchable';
33
import { Installable } from './installable';
44
import { ArduinoComponent } from './arduino-component';
55
import { nls } from '@theia/core/lib/common/nls';
6-
import { All, Contributed, Partner, Type, Updatable } from '../nls';
6+
import {
7+
All,
8+
Contributed,
9+
Partner,
10+
Type as TypeLabel,
11+
Updatable,
12+
} from '../nls';
713

814
export type AvailablePorts = Record<string, [Port, Array<Board>]>;
915
export namespace AvailablePorts {
@@ -161,6 +167,11 @@ export namespace BoardSearch {
161167
'Arduino@Heart',
162168
] as const;
163169
export type Type = typeof TypeLiterals[number];
170+
export namespace Type {
171+
export function is(arg: unknown): arg is Type {
172+
return typeof arg === 'string' && TypeLiterals.includes(arg as Type);
173+
}
174+
}
164175
export const TypeLabels: Record<Type, string> = {
165176
All: All,
166177
Updatable: Updatable,
@@ -177,7 +188,7 @@ export namespace BoardSearch {
177188
keyof Omit<BoardSearch, 'query'>,
178189
string
179190
> = {
180-
type: Type,
191+
type: TypeLabel,
181192
};
182193
}
183194

Diff for: arduino-ide-extension/src/common/protocol/library-service.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
Partner,
99
Recommended,
1010
Retired,
11-
Type,
11+
Type as TypeLabel,
1212
Updatable,
1313
} from '../nls';
1414

@@ -66,6 +66,11 @@ export namespace LibrarySearch {
6666
'Retired',
6767
] as const;
6868
export type Type = typeof TypeLiterals[number];
69+
export namespace Type {
70+
export function is(arg: unknown): arg is Type {
71+
return typeof arg === 'string' && TypeLiterals.includes(arg as Type);
72+
}
73+
}
6974
export const TypeLabels: Record<Type, string> = {
7075
All: All,
7176
Updatable: Updatable,
@@ -90,6 +95,11 @@ export namespace LibrarySearch {
9095
'Uncategorized',
9196
] as const;
9297
export type Topic = typeof TopicLiterals[number];
98+
export namespace Topic {
99+
export function is(arg: unknown): arg is Topic {
100+
return typeof arg === 'string' && TopicLiterals.includes(arg as Topic);
101+
}
102+
}
93103
export const TopicLabels: Record<Topic, string> = {
94104
All: All,
95105
Communication: nls.localize(
@@ -126,7 +136,7 @@ export namespace LibrarySearch {
126136
string
127137
> = {
128138
topic: nls.localize('arduino/librarySearchProperty/topic', 'Topic'),
129-
type: Type,
139+
type: TypeLabel,
130140
};
131141
}
132142

0 commit comments

Comments
 (0)