Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0c49709

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommitted
Link resolved for lib/boards manager.
Closes #1442 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 019b2d5 commit 0c49709

File tree

8 files changed

+359
-27
lines changed

8 files changed

+359
-27
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ import { DeleteSketch } from './contributions/delete-sketch';
334334
import { UserFields } from './contributions/user-fields';
335335
import { UpdateIndexes } from './contributions/update-indexes';
336336
import { InterfaceScale } from './contributions/interface-scale';
337+
import { OpenHandler } from '@theia/core/lib/browser/opener-service';
337338

338339
const registerArduinoThemes = () => {
339340
const themes: MonacoThemeJson[] = [
@@ -398,6 +399,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
398399
bind(FrontendApplicationContribution).toService(
399400
LibraryListWidgetFrontendContribution
400401
);
402+
bind(OpenHandler).toService(LibraryListWidgetFrontendContribution);
401403

402404
// Sketch list service
403405
bind(SketchesService)
@@ -464,6 +466,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
464466
bind(FrontendApplicationContribution).toService(
465467
BoardsListWidgetFrontendContribution
466468
);
469+
bind(OpenHandler).toService(BoardsListWidgetFrontendContribution);
467470

468471
// Board select dialog
469472
bind(BoardsConfigDialogWidget).toSelf().inSingletonScope();

‎arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { injectable } from '@theia/core/shared/inversify';
2-
import { BoardsListWidget } from './boards-list-widget';
3-
import type {
2+
import {
43
BoardSearch,
54
BoardsPackage,
65
} from '../../common/protocol/boards-service';
6+
import { URI } from '../contributions/contribution';
77
import { ListWidgetFrontendContribution } from '../widgets/component-list/list-widget-frontend-contribution';
8+
import { BoardsListWidget } from './boards-list-widget';
89

910
@injectable()
1011
export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution<
@@ -24,7 +25,16 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont
2425
});
2526
}
2627

27-
override async initializeLayout(): Promise<void> {
28-
this.openView();
28+
protected canParse(uri: URI): boolean {
29+
try {
30+
BoardSearch.UriParser.parse(uri);
31+
return true;
32+
} catch {
33+
return false;
34+
}
35+
}
36+
37+
protected parse(uri: URI): BoardSearch | undefined {
38+
return BoardSearch.UriParser.parse(uri);
2939
}
3040
}
Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
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';
5+
import { URI } from '../contributions/contribution';
66
import { ArduinoMenus } from '../menu/arduino-menus';
7-
import { nls } from '@theia/core/lib/common';
7+
import { ListWidgetFrontendContribution } from '../widgets/component-list/list-widget-frontend-contribution';
8+
import { LibraryListWidget } from './library-list-widget';
89

910
@injectable()
10-
export class LibraryListWidgetFrontendContribution
11-
extendsAbstractViewContribution<LibraryListWidget>
12-
implementsFrontendApplicationContribution
13-
{
11+
export class LibraryListWidgetFrontendContributionextendsListWidgetFrontendContribution<
12+
LibraryPackage,
13+
LibrarySearch
14+
>{
1415
constructor() {
1516
super({
1617
widgetId: LibraryListWidget.WIDGET_ID,
@@ -24,10 +25,6 @@ export class LibraryListWidgetFrontendContribution
2425
});
2526
}
2627

27-
async initializeLayout(): Promise<void> {
28-
this.openView();
29-
}
30-
3128
override registerMenus(menus: MenuModelRegistry): void {
3229
if (this.toggleCommand) {
3330
menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, {
@@ -40,4 +37,17 @@ export class LibraryListWidgetFrontendContribution
4037
});
4138
}
4239
}
40+
41+
protected canParse(uri: URI): boolean {
42+
try {
43+
LibrarySearch.UriParser.parse(uri);
44+
return true;
45+
} catch {
46+
return false;
47+
}
48+
}
49+
50+
protected parse(uri: URI): LibrarySearch | undefined {
51+
return LibrarySearch.UriParser.parse(uri);
52+
}
4353
}
Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,65 @@
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+
readonly id: string = `http-opener-${this.viewId}`;
23+
1624
async initializeLayout(): Promise<void> {
17-
// TS requires at least one method from `FrontendApplicationContribution`.
18-
// Expected to be empty.
25+
this.openView();
1926
}
2027

21-
override registerMenus(): void {
28+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
29+
override registerMenus(_: MenuModelRegistry): void {
2230
// NOOP
2331
}
32+
33+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
34+
canHandle(uri: URI, _?: OpenerOptions): number {
35+
// `500` is the default HTTP opener in Theia. IDE2 has higher priority.
36+
// https://github.com/eclipse-theia/theia/blob/b75b6144b0ffea06a549294903c374fa642135e4/packages/core/src/browser/http-open-handler.ts#L39
37+
return this.canParse(uri) ? 501 : 0;
38+
}
39+
40+
async open(
41+
uri: URI,
42+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
43+
_?: OpenerOptions | undefined
44+
): Promise<void> {
45+
const searchOptions = this.parse(uri);
46+
if (!searchOptions) {
47+
console.warn(
48+
`Failed to parse URI into a search options. URI: ${uri.toString()}`
49+
);
50+
return;
51+
}
52+
const widget = await this.openView({
53+
activate: true,
54+
reveal: true,
55+
});
56+
if (!widget) {
57+
console.warn(`Failed to open view for URI: ${uri.toString()}`);
58+
return;
59+
}
60+
widget.refresh(searchOptions);
61+
}
62+
63+
protected abstract canParse(uri: URI): boolean;
64+
protected abstract parse(uri: URI): S | undefined;
2465
}

‎arduino-ide-extension/src/common/protocol/boards-service.ts‎

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@ 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';
13+
import URI from '@theia/core/lib/common/uri';
714

815
export type AvailablePorts = Record<string, [Port, Array<Board>]>;
916
export namespace AvailablePorts {
@@ -151,6 +158,7 @@ export interface BoardSearch extends Searchable.Options {
151158
readonly type?: BoardSearch.Type;
152159
}
153160
export namespace BoardSearch {
161+
export const Default: BoardSearch = { type: 'All' };
154162
export const TypeLiterals = [
155163
'All',
156164
'Updatable',
@@ -161,6 +169,11 @@ export namespace BoardSearch {
161169
'Arduino@Heart',
162170
] as const;
163171
export type Type = typeof TypeLiterals[number];
172+
export namespace Type {
173+
export function is(arg: unknown): arg is Type {
174+
return typeof arg === 'string' && TypeLiterals.includes(arg as Type);
175+
}
176+
}
164177
export const TypeLabels: Record<Type, string> = {
165178
All: All,
166179
Updatable: Updatable,
@@ -177,8 +190,41 @@ export namespace BoardSearch {
177190
keyof Omit<BoardSearch, 'query'>,
178191
string
179192
> = {
180-
type: Type,
193+
type: TypeLabel,
181194
};
195+
export namespace UriParser {
196+
export const authority = 'boardsmanager';
197+
export function parse(uri: URI): BoardSearch | undefined {
198+
if (uri.scheme !== 'http') {
199+
throw new Error(
200+
`Invalid 'scheme'. Expected 'http'. URI was: ${uri.toString()}.`
201+
);
202+
}
203+
if (uri.authority !== authority) {
204+
throw new Error(
205+
`Invalid 'authority'. Expected: '${authority}'. URI was: ${uri.toString()}.`
206+
);
207+
}
208+
const segments = Searchable.UriParser.normalizedSegmentsOf(uri);
209+
if (segments.length !== 1) {
210+
return undefined;
211+
}
212+
let searchOptions: BoardSearch | undefined = undefined;
213+
const [type] = segments;
214+
if (!type) {
215+
searchOptions = BoardSearch.Default;
216+
} else if (BoardSearch.Type.is(type)) {
217+
searchOptions = { type };
218+
}
219+
if (searchOptions) {
220+
return {
221+
...searchOptions,
222+
...Searchable.UriParser.parseQuery(uri),
223+
};
224+
}
225+
return undefined;
226+
}
227+
}
182228
}
183229

184230
export interface Port {

‎arduino-ide-extension/src/common/protocol/library-service.ts‎

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import {
88
Partner,
99
Recommended,
1010
Retired,
11-
Type,
11+
TypeasTypeLabel,
1212
Updatable,
1313
} from '../nls';
14+
import URI from '@theia/core/lib/common/uri';
1415

1516
export const LibraryServicePath = '/services/library-service';
1617
export const LibraryService = Symbol('LibraryService');
@@ -55,6 +56,7 @@ export interface LibrarySearch extends Searchable.Options {
5556
readonly topic?: LibrarySearch.Topic;
5657
}
5758
export namespace LibrarySearch {
59+
export const Default: LibrarySearch = { type: 'All', topic: 'All' };
5860
export const TypeLiterals = [
5961
'All',
6062
'Updatable',
@@ -66,6 +68,11 @@ export namespace LibrarySearch {
6668
'Retired',
6769
] as const;
6870
export type Type = typeof TypeLiterals[number];
71+
export namespace Type {
72+
export function is(arg: unknown): arg is Type {
73+
return typeof arg === 'string' && TypeLiterals.includes(arg as Type);
74+
}
75+
}
6976
export const TypeLabels: Record<Type, string> = {
7077
All: All,
7178
Updatable: Updatable,
@@ -90,6 +97,11 @@ export namespace LibrarySearch {
9097
'Uncategorized',
9198
] as const;
9299
export type Topic = typeof TopicLiterals[number];
100+
export namespace Topic {
101+
export function is(arg: unknown): arg is Topic {
102+
return typeof arg === 'string' && TopicLiterals.includes(arg as Topic);
103+
}
104+
}
93105
export const TopicLabels: Record<Topic, string> = {
94106
All: All,
95107
Communication: nls.localize(
@@ -126,8 +138,60 @@ export namespace LibrarySearch {
126138
string
127139
> = {
128140
topic: nls.localize('arduino/librarySearchProperty/topic', 'Topic'),
129-
type: Type,
141+
type: TypeLabel,
130142
};
143+
export namespace UriParser {
144+
export const authority = 'librarymanager';
145+
export function parse(uri: URI): LibrarySearch | undefined {
146+
if (uri.scheme !== 'http') {
147+
throw new Error(
148+
`Invalid 'scheme'. Expected 'http'. URI was: ${uri.toString()}.`
149+
);
150+
}
151+
if (uri.authority !== authority) {
152+
throw new Error(
153+
`Invalid 'authority'. Expected: '${authority}'. URI was: ${uri.toString()}.`
154+
);
155+
}
156+
const segments = Searchable.UriParser.normalizedSegmentsOf(uri);
157+
// Special magic handling for `Signal Input/Output`.
158+
// TODO: IDE2 deserves a better lib/boards URL spec.
159+
// https://github.com/arduino/arduino-ide/issues/1442#issuecomment-1252136377
160+
if (segments.length === 3) {
161+
const [type, topicHead, topicTail] = segments;
162+
const maybeTopic = `${topicHead}/${topicTail}`;
163+
if (
164+
LibrarySearch.Topic.is(maybeTopic) &&
165+
maybeTopic === 'Signal Input/Output' &&
166+
LibrarySearch.Type.is(type)
167+
) {
168+
return {
169+
type,
170+
topic: maybeTopic,
171+
...Searchable.UriParser.parseQuery(uri),
172+
};
173+
}
174+
}
175+
let searchOptions: LibrarySearch | undefined = undefined;
176+
const [type, topic] = segments;
177+
if (!type && !topic) {
178+
searchOptions = LibrarySearch.Default;
179+
} else if (LibrarySearch.Type.is(type)) {
180+
if (!topic) {
181+
searchOptions = { ...LibrarySearch.Default, type };
182+
} else if (LibrarySearch.Topic.is(topic)) {
183+
searchOptions = { type, topic };
184+
}
185+
}
186+
if (searchOptions) {
187+
return {
188+
...searchOptions,
189+
...Searchable.UriParser.parseQuery(uri),
190+
};
191+
}
192+
return undefined;
193+
}
194+
}
131195
}
132196

133197
export namespace LibraryService {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /