UNPKG

5.34 kBTypeScriptView Raw
1// *****************************************************************************
2// Copyright (C) 2018 Ericsson and others.
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License v. 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0.
7//
8// This Source Code may also be made available under the following Secondary
9// Licenses when the conditions for such availability set forth in the Eclipse
10// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11// with the GNU Classpath Exception which is available at
12// https://www.gnu.org/software/classpath/license.html.
13//
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15// *****************************************************************************
16
17import * as React from 'react';
18import { inject, injectable, postConstruct } from 'inversify';
19import { Dialog, DialogProps } from './dialogs';
20import { ReactDialog } from './dialogs/react-dialog';
21import { ApplicationServer, ApplicationInfo, ExtensionInfo } from '../common/application-protocol';
22import { Message } from './widgets/widget';
23import { FrontendApplicationConfigProvider } from './frontend-application-config-provider';
24import { DEFAULT_SUPPORTED_API_VERSION } from '@theia/application-package/lib/api';
25import { WindowService } from './window/window-service';
26import { Key, KeyCode } from './keys';
27import { nls } from '../common/nls';
28
29export const ABOUT_CONTENT_CLASS = 'theia-aboutDialog';
30export const ABOUT_EXTENSIONS_CLASS = 'theia-aboutExtensions';
31
32@injectable()
33export class AboutDialogProps extends DialogProps {
34}
35
36@injectable()
37export class AboutDialog extends ReactDialog<void> {
38 protected applicationInfo: ApplicationInfo | undefined;
39 protected extensionsInfos: ExtensionInfo[] = [];
40 protected readonly okButton: HTMLButtonElement;
41
42 @inject(ApplicationServer)
43 protected readonly appServer: ApplicationServer;
44
45 @inject(WindowService)
46 protected readonly windowService: WindowService;
47
48 constructor(
49 @inject(AboutDialogProps) protected override readonly props: AboutDialogProps
50 ) {
51 super({
52 title: FrontendApplicationConfigProvider.get().applicationName,
53 });
54 this.appendAcceptButton(Dialog.OK);
55 }
56
57 @postConstruct()
58 protected async init(): Promise<void> {
59 this.applicationInfo = await this.appServer.getApplicationInfo();
60 this.extensionsInfos = await this.appServer.getExtensionsInfos();
61 this.update();
62 }
63
64 protected renderHeader(): React.ReactNode {
65 const applicationInfo = this.applicationInfo;
66 const compatibilityUrl = 'https://eclipse-theia.github.io/vscode-theia-comparator/status.html';
67
68 const detailsLabel = nls.localizeByDefault('Details');
69 const versionLabel = nls.localize('theia/core/about/version', 'Version');
70 const defaultApiLabel = nls.localize('theia/core/about/defaultApi', 'Default {0} API', 'VS Code');
71 const compatibilityLabel = nls.localize('theia/core/about/compatibility', '{0} Compatibility', 'VS Code');
72
73 return <>
74 <h3>{detailsLabel}</h3>
75 <div className='about-details'>
76 {applicationInfo && <p>{`${versionLabel}: ${applicationInfo.version}`}</p>}
77 <p>{`${defaultApiLabel}: ${DEFAULT_SUPPORTED_API_VERSION}`}</p>
78 <p>
79 <a
80 role={'button'}
81 tabIndex={0}
82 onClick={() => this.doOpenExternalLink(compatibilityUrl)}
83 onKeyDown={(e: React.KeyboardEvent) => this.doOpenExternalLinkEnter(e, compatibilityUrl)}>
84 {compatibilityLabel}
85 </a>
86 </p>
87 </div>
88 </>;
89 }
90
91 protected renderExtensions(): React.ReactNode {
92 const extensionsInfos = this.extensionsInfos;
93 return <>
94 <h3>List of extensions</h3>
95 <ul className={ABOUT_EXTENSIONS_CLASS}>
96 {
97 extensionsInfos
98 .sort((a: ExtensionInfo, b: ExtensionInfo) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
99 .map((extension: ExtensionInfo) => <li key={extension.name}>{extension.name} {extension.version}</li>)
100 }
101 </ul>
102 </>;
103 }
104
105 protected render(): React.ReactNode {
106 return <div className={ABOUT_CONTENT_CLASS}>
107 {this.renderHeader()}
108 {this.renderExtensions()}
109 </div>;
110 }
111
112 protected override onAfterAttach(msg: Message): void {
113 super.onAfterAttach(msg);
114 this.update();
115 }
116
117 /**
118 * Open a link in an external window.
119 * @param url the link.
120 */
121 protected doOpenExternalLink = (url: string) => this.windowService.openNewWindow(url, { external: true });
122 protected doOpenExternalLinkEnter = (e: React.KeyboardEvent, url: string) => {
123 if (this.isEnterKey(e)) {
124 this.doOpenExternalLink(url);
125 }
126 };
127
128 protected isEnterKey(e: React.KeyboardEvent): boolean {
129 return Key.ENTER.keyCode === KeyCode.createKeyCode(e.nativeEvent).key?.keyCode;
130 }
131
132 get value(): undefined { return undefined; }
133}