|
1 |
| -import { injectable } from '@theia/core/shared/inversify'; |
2 | 1 | import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
| 2 | +import { |
| 3 | + OpenerOptions, |
| 4 | + OpenHandler, |
| 5 | +} from '@theia/core/lib/browser/opener-service'; |
3 | 6 | 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'; |
4 | 11 | import { ArduinoComponent } from '../../../common/protocol/arduino-component';
|
5 | 12 | import { ListWidget } from './list-widget';
|
6 |
| -import { Searchable } from '../../../common/protocol'; |
7 | 13 |
|
8 | 14 | @injectable()
|
9 | 15 | export abstract class ListWidgetFrontendContribution<
|
10 | 16 | T extends ArduinoComponent,
|
11 | 17 | S extends Searchable.Options
|
12 | 18 | >
|
13 | 19 | extends AbstractViewContribution<ListWidget<T, S>>
|
14 |
| - implements FrontendApplicationContribution |
| 20 | + implements FrontendApplicationContribution, OpenHandler |
15 | 21 | {
|
| 22 | + protected abstract readonly openerAuthority: string; |
| 23 | + readonly id: string = `http-opener-${this.viewId}`; |
| 24 | + |
16 | 25 | async initializeLayout(): Promise<void> {
|
17 |
| - // TS requires at least one method from `FrontendApplicationContribution`. |
18 |
| - // Expected to be empty. |
| 26 | + this.openView(); |
19 | 27 | }
|
20 | 28 |
|
21 |
| - override registerMenus(): void { |
| 29 | + // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| 30 | + override registerMenus(_: MenuModelRegistry): void { |
22 | 31 | // NOOP
|
23 | 32 | }
|
| 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; |
24 | 85 | }
|
0 commit comments