mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-18 07:38:33 +00:00
feat: use theia@1.57.0
(#2654)
This commit is contained in:
@@ -24,28 +24,29 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.8.14",
|
||||
"@theia/application-package": "1.41.0",
|
||||
"@theia/core": "1.41.0",
|
||||
"@theia/debug": "1.41.0",
|
||||
"@theia/editor": "1.41.0",
|
||||
"@theia/electron": "1.41.0",
|
||||
"@theia/filesystem": "1.41.0",
|
||||
"@theia/keymaps": "1.41.0",
|
||||
"@theia/markers": "1.41.0",
|
||||
"@theia/messages": "1.41.0",
|
||||
"@theia/monaco": "1.41.0",
|
||||
"@theia/monaco-editor-core": "1.72.3",
|
||||
"@theia/navigator": "1.41.0",
|
||||
"@theia/outline-view": "1.41.0",
|
||||
"@theia/output": "1.41.0",
|
||||
"@theia/plugin-ext": "1.41.0",
|
||||
"@theia/plugin-ext-vscode": "1.41.0",
|
||||
"@theia/preferences": "1.41.0",
|
||||
"@theia/scm": "1.41.0",
|
||||
"@theia/search-in-workspace": "1.41.0",
|
||||
"@theia/terminal": "1.41.0",
|
||||
"@theia/typehierarchy": "1.41.0",
|
||||
"@theia/workspace": "1.41.0",
|
||||
"@theia/application-package": "1.57.0",
|
||||
"@theia/core": "1.57.0",
|
||||
"@theia/debug": "1.57.0",
|
||||
"@theia/editor": "1.57.0",
|
||||
"@theia/electron": "1.57.0",
|
||||
"@theia/filesystem": "1.57.0",
|
||||
"@theia/keymaps": "1.57.0",
|
||||
"@theia/markers": "1.57.0",
|
||||
"@theia/messages": "1.57.0",
|
||||
"@theia/monaco": "1.57.0",
|
||||
"@theia/monaco-editor-core": "1.83.101",
|
||||
"@theia/navigator": "1.57.0",
|
||||
"@theia/outline-view": "1.57.0",
|
||||
"@theia/output": "1.57.0",
|
||||
"@theia/plugin-ext": "1.57.0",
|
||||
"@theia/plugin-ext-vscode": "1.57.0",
|
||||
"@theia/preferences": "1.57.0",
|
||||
"@theia/scm": "1.57.0",
|
||||
"@theia/search-in-workspace": "1.57.0",
|
||||
"@theia/terminal": "1.57.0",
|
||||
"@theia/test": "1.57.0",
|
||||
"@theia/typehierarchy": "1.57.0",
|
||||
"@theia/workspace": "1.57.0",
|
||||
"@tippyjs/react": "^4.2.5",
|
||||
"@types/auth0-js": "^9.21.3",
|
||||
"@types/btoa": "^1.2.3",
|
||||
@@ -57,7 +58,6 @@
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/p-queue": "^2.3.1",
|
||||
"@types/ps-tree": "^1.1.0",
|
||||
"@types/react-tabs": "^2.3.2",
|
||||
"@types/temp": "^0.8.34",
|
||||
"arduino-serial-plotter-webapp": "0.2.0",
|
||||
"async-mutex": "^0.3.0",
|
||||
@@ -99,7 +99,7 @@
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-perfect-scrollbar": "^1.5.8",
|
||||
"react-select": "^5.6.0",
|
||||
"react-tabs": "^3.1.2",
|
||||
"react-tabs": "^6.1.0",
|
||||
"react-window": "^1.8.6",
|
||||
"semver": "^7.3.2",
|
||||
"string-natural-compare": "^2.0.3",
|
||||
@@ -126,7 +126,7 @@
|
||||
"mockdate": "^3.0.5",
|
||||
"moment": "^2.24.0",
|
||||
"ncp": "^2.0.0",
|
||||
"rimraf": "^2.6.1"
|
||||
"rimraf": "^5.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pingghost/protoc": "^1.0.2",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
||||
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
|
||||
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import {
|
||||
TabBarToolbarContribution,
|
||||
|
@@ -1,18 +1,12 @@
|
||||
import '../../src/browser/style/index.css';
|
||||
import {
|
||||
Container,
|
||||
ContainerModule,
|
||||
interfaces,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { Container, ContainerModule } from '@theia/core/shared/inversify';
|
||||
import { WidgetFactory } from '@theia/core/lib/browser/widget-manager';
|
||||
import { CommandContribution } from '@theia/core/lib/common/command';
|
||||
import { bindViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
|
||||
import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging/ws-connection-provider';
|
||||
import {
|
||||
FrontendApplicationContribution,
|
||||
FrontendApplication as TheiaFrontendApplication,
|
||||
} from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplication as TheiaFrontendApplication } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { LibraryListWidget } from './library/library-list-widget';
|
||||
import { ArduinoFrontendContribution } from './arduino-frontend-contribution';
|
||||
import {
|
||||
@@ -57,8 +51,6 @@ import {
|
||||
DockPanelRenderer as TheiaDockPanelRenderer,
|
||||
TabBarRendererFactory,
|
||||
ContextMenuRenderer,
|
||||
createTreeContainer,
|
||||
TreeWidget,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { MenuContribution } from '@theia/core/lib/common/menu';
|
||||
import {
|
||||
@@ -97,7 +89,6 @@ import {
|
||||
ArduinoDaemonPath,
|
||||
ArduinoDaemon,
|
||||
} from '../common/protocol/arduino-daemon';
|
||||
import { EditorCommandContribution as TheiaEditorCommandContribution } from '@theia/editor/lib/browser';
|
||||
import {
|
||||
FrontendConnectionStatusService,
|
||||
ApplicationConnectionStatusContribution,
|
||||
@@ -186,7 +177,6 @@ import {
|
||||
import { About } from './contributions/about';
|
||||
import { IconThemeService } from '@theia/core/lib/browser/icon-theme-service';
|
||||
import { TabBarRenderer } from './theia/core/tab-bars';
|
||||
import { EditorCommandContribution } from './theia/editor/editor-command';
|
||||
import { NavigatorTabBarDecorator as TheiaNavigatorTabBarDecorator } from '@theia/navigator/lib/browser/navigator-tab-bar-decorator';
|
||||
import { NavigatorTabBarDecorator } from './theia/navigator/navigator-tab-bar-decorator';
|
||||
import { Debug, DebugDisabledStatusMessageSource } from './contributions/debug';
|
||||
@@ -275,7 +265,7 @@ import {
|
||||
IDEUpdaterDialog,
|
||||
IDEUpdaterDialogProps,
|
||||
} from './dialogs/ide-updater/ide-updater-dialog';
|
||||
import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-provider';
|
||||
import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-source';
|
||||
import { MonitorModel } from './monitor-model';
|
||||
import { MonitorManagerProxyClientImpl } from './monitor-manager-proxy-client-impl';
|
||||
import { EditorManager as TheiaEditorManager } from '@theia/editor/lib/browser/editor-manager';
|
||||
@@ -295,10 +285,6 @@ import { PreferenceTreeGenerator } from './theia/preferences/preference-tree-gen
|
||||
import { PreferenceTreeGenerator as TheiaPreferenceTreeGenerator } from '@theia/preferences/lib/browser/util/preference-tree-generator';
|
||||
import { AboutDialog } from './theia/core/about-dialog';
|
||||
import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog';
|
||||
import {
|
||||
SurveyNotificationService,
|
||||
SurveyNotificationServicePath,
|
||||
} from '../common/protocol/survey-service';
|
||||
import { WindowContribution } from './theia/core/window-contribution';
|
||||
import { WindowContribution as TheiaWindowContribution } from '@theia/core/lib/browser/window-contribution';
|
||||
import { CoreErrorHandler } from './contributions/core-error-handler';
|
||||
@@ -381,19 +367,13 @@ import { DebugSessionWidget } from '@theia/debug/lib/browser/view/debug-session-
|
||||
import { DebugConfigurationWidget } from './theia/debug/debug-configuration-widget';
|
||||
import { DebugConfigurationWidget as TheiaDebugConfigurationWidget } from '@theia/debug/lib/browser/view/debug-configuration-widget';
|
||||
import { DebugToolBar } from '@theia/debug/lib/browser/view/debug-toolbar-widget';
|
||||
import {
|
||||
PluginTree,
|
||||
PluginTreeModel,
|
||||
TreeViewWidgetOptions,
|
||||
VIEW_ITEM_CONTEXT_MENU,
|
||||
} from '@theia/plugin-ext/lib/main/browser/view/tree-view-widget';
|
||||
import { TreeViewDecoratorService } from '@theia/plugin-ext/lib/main/browser/view/tree-view-decorator-service';
|
||||
import { PLUGIN_VIEW_DATA_FACTORY_ID } from '@theia/plugin-ext/lib/main/browser/view/plugin-view-registry';
|
||||
import { TreeViewWidget } from './theia/plugin-ext/tree-view-widget';
|
||||
|
||||
import {
|
||||
VersionWelcomeDialog,
|
||||
VersionWelcomeDialogProps,
|
||||
} from './dialogs/version-welcome-dialog';
|
||||
import { TestViewContribution as TheiaTestViewContribution } from '@theia/test/lib/browser/view/test-view-contribution';
|
||||
import { TestViewContribution } from './theia/test/test-view-contribution';
|
||||
|
||||
// Hack to fix copy/cut/paste issue after electron version update in Theia.
|
||||
// https://github.com/eclipse-theia/theia/issues/12487
|
||||
@@ -574,15 +554,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
WorkspaceVariableContribution
|
||||
);
|
||||
|
||||
bind(SurveyNotificationService)
|
||||
.toDynamicValue((context) => {
|
||||
return ElectronIpcConnectionProvider.createProxy(
|
||||
context.container,
|
||||
SurveyNotificationServicePath
|
||||
);
|
||||
})
|
||||
.inSingletonScope();
|
||||
|
||||
// Layout and shell customizations.
|
||||
rebind(TheiaOutlineViewContribution)
|
||||
.to(OutlineViewContribution)
|
||||
@@ -856,13 +827,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
);
|
||||
});
|
||||
|
||||
// Workaround for https://github.com/eclipse-theia/theia/issues/8722
|
||||
// Do not trigger a save on IDE startup if `"editor.autoSave": "on"` was set as a preference.
|
||||
// Note: `"editor.autoSave" was renamed to `"files.autoSave" and `"on"` was replaced with three
|
||||
// different cases, but we treat `!== 'off'` as auto save enabled. (https://github.com/eclipse-theia/theia/issues/10812)
|
||||
bind(EditorCommandContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaEditorCommandContribution).toService(EditorCommandContribution);
|
||||
|
||||
// Silent the badge decoration in the Explorer view.
|
||||
bind(NavigatorTabBarDecorator).toSelf().inSingletonScope();
|
||||
rebind(TheiaNavigatorTabBarDecorator).toService(NavigatorTabBarDecorator);
|
||||
@@ -1112,42 +1076,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
TerminalFrontendContribution
|
||||
);
|
||||
|
||||
bindViewsWelcome_TheiaGH14309({ bind, widget: TreeViewWidget });
|
||||
// Hides the Test Explorer from the side-bar
|
||||
bind(TestViewContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaTestViewContribution).toService(TestViewContribution);
|
||||
});
|
||||
|
||||
// Align the viewsWelcome rendering with VS Code (https://github.com/eclipse-theia/theia/issues/14309)
|
||||
// Copied from Theia code but with customized TreeViewWidget with the customized viewsWelcome rendering
|
||||
// https://github.com/eclipse-theia/theia/blob/0c5f69455d9ee355b1a7ca510ffa63d2b20f0c77/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts#L159-L181
|
||||
function bindViewsWelcome_TheiaGH14309({
|
||||
bind,
|
||||
widget,
|
||||
}: {
|
||||
bind: interfaces.Bind;
|
||||
widget: interfaces.Newable<TreeWidget>;
|
||||
}) {
|
||||
bind(WidgetFactory)
|
||||
.toDynamicValue(({ container }) => ({
|
||||
id: PLUGIN_VIEW_DATA_FACTORY_ID,
|
||||
createWidget: (options: TreeViewWidgetOptions) => {
|
||||
const props = {
|
||||
contextMenuPath: VIEW_ITEM_CONTEXT_MENU,
|
||||
expandOnlyOnExpansionToggleClick: true,
|
||||
expansionTogglePadding: 22,
|
||||
globalSelection: true,
|
||||
leftPadding: 8,
|
||||
search: true,
|
||||
multiSelect: options.multiSelect,
|
||||
};
|
||||
const child = createTreeContainer(container, {
|
||||
props,
|
||||
tree: PluginTree,
|
||||
model: PluginTreeModel,
|
||||
widget,
|
||||
decoratorService: TreeViewDecoratorService,
|
||||
});
|
||||
child.bind(TreeViewWidgetOptions).toConstantValue(options);
|
||||
return child.get(TreeWidget);
|
||||
},
|
||||
}))
|
||||
.inSingletonScope();
|
||||
}
|
||||
|
@@ -280,14 +280,6 @@ const properties: ArduinoPreferenceSchemaProperties = {
|
||||
),
|
||||
default: 'https://auth.arduino.cc/login#/register',
|
||||
},
|
||||
'arduino.survey.notification': {
|
||||
type: 'boolean',
|
||||
description: nls.localize(
|
||||
'arduino/preferences/survey.notification',
|
||||
'True if users should be notified if a survey is available. True by default.'
|
||||
),
|
||||
default: true,
|
||||
},
|
||||
'arduino.cli.daemon.debug': {
|
||||
type: 'boolean',
|
||||
description: nls.localize(
|
||||
@@ -355,7 +347,6 @@ export interface ArduinoConfiguration {
|
||||
'arduino.auth.domain': string;
|
||||
'arduino.auth.audience': string;
|
||||
'arduino.auth.registerUri': string;
|
||||
'arduino.survey.notification': boolean;
|
||||
'arduino.cli.daemon.debug': boolean;
|
||||
'arduino.sketch.inoBlueprint': string;
|
||||
'arduino.checkForUpdates': boolean;
|
||||
|
@@ -3,7 +3,7 @@ import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { JsonRpcProxy } from '@theia/core/lib/common/messaging/proxy-factory';
|
||||
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import {
|
||||
CommandRegistry,
|
||||
CommandContribution,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { MessageType } from '@theia/core/lib/common/message-service-protocol';
|
||||
|
@@ -98,6 +98,7 @@ export class BoardsConfigDialog extends ReactDialog<BoardsConfigDialogState> {
|
||||
}
|
||||
|
||||
override async open(
|
||||
disposeOnResolve = true,
|
||||
params?: EditBoardsConfigActionParams
|
||||
): Promise<BoardsConfig | undefined> {
|
||||
this._searchSet = undefined;
|
||||
@@ -119,7 +120,7 @@ export class BoardsConfigDialog extends ReactDialog<BoardsConfigDialogState> {
|
||||
this._searchSet = params.searchSet.slice();
|
||||
}
|
||||
}
|
||||
return super.open();
|
||||
return super.open(disposeOnResolve);
|
||||
}
|
||||
|
||||
protected override onAfterAttach(msg: Message): void {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { StorageService } from '@theia/core/lib/browser/storage-service';
|
||||
import type {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { StorageService } from '@theia/core/lib/browser/storage-service';
|
||||
import {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { Emitter, Event } from '@theia/core/lib/common/event';
|
||||
|
@@ -70,7 +70,7 @@ export class CheckForIDEUpdates extends Contribution {
|
||||
SKIP_IDE_VERSION
|
||||
);
|
||||
if (versionToSkip === updateInfo.version) return;
|
||||
this.updaterDialog.open(updateInfo);
|
||||
this.updaterDialog.open(true, updateInfo);
|
||||
})
|
||||
.catch((e) => {
|
||||
this.messageService.error(
|
||||
|
@@ -1,8 +1,6 @@
|
||||
import { Dialog } from '@theia/core/lib/browser/dialogs';
|
||||
import type {
|
||||
FrontendApplication,
|
||||
OnWillStopAction,
|
||||
} from '@theia/core/lib/browser/frontend-application';
|
||||
import type { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
|
||||
import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import type { MaybePromise } from '@theia/core/lib/common/types';
|
||||
|
@@ -779,7 +779,7 @@ export class CompilerErrors
|
||||
return undefined;
|
||||
} else {
|
||||
return this.editorManager
|
||||
.getByUri(new URI(uriOrWidget))
|
||||
.getByUri(new URI(uriOrWidget.toString()))
|
||||
.then((editor) => {
|
||||
if (editor) {
|
||||
return this.monacoEditor(editor);
|
||||
|
@@ -1,8 +1,6 @@
|
||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
||||
import {
|
||||
FrontendApplication,
|
||||
FrontendApplicationContribution,
|
||||
} from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import {
|
||||
KeybindingContribution,
|
||||
|
@@ -1,7 +1,11 @@
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
||||
import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service';
|
||||
import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
|
||||
import { ICodeEditorService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/codeEditorService';
|
||||
import type { ICodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser';
|
||||
import type { StandaloneCodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor';
|
||||
import {
|
||||
Contribution,
|
||||
Command,
|
||||
@@ -10,17 +14,11 @@ import {
|
||||
CommandRegistry,
|
||||
} from './contribution';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import type { ICodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser';
|
||||
import type { StandaloneCodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor';
|
||||
|
||||
// TODO: [macOS]: to remove `Start Dictation...` and `Emoji & Symbol` see this thread: https://github.com/electron/electron/issues/8283#issuecomment-269522072
|
||||
// Depends on https://github.com/eclipse-theia/theia/pull/7964
|
||||
@injectable()
|
||||
export class EditContributions extends Contribution {
|
||||
@inject(MonacoEditorService)
|
||||
private readonly codeEditorService: MonacoEditorService;
|
||||
|
||||
@inject(ClipboardService)
|
||||
private readonly clipboardService: ClipboardService;
|
||||
|
||||
@@ -208,9 +206,10 @@ ${value}
|
||||
protected async current(): Promise<
|
||||
ICodeEditor | StandaloneCodeEditor | undefined
|
||||
> {
|
||||
const codeEditorService = StandaloneServices.get(ICodeEditorService);
|
||||
return (
|
||||
this.codeEditorService.getFocusedCodeEditor() ||
|
||||
this.codeEditorService.getActiveCodeEditor() ||
|
||||
codeEditorService.getFocusedCodeEditor() ||
|
||||
codeEditorService.getActiveCodeEditor() ||
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ export class OpenBoardsConfig extends Contribution {
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(OpenBoardsConfig.Commands.OPEN_DIALOG, {
|
||||
execute: async (params?: EditBoardsConfigActionParams) =>
|
||||
this.boardsConfigDialog.open(params),
|
||||
this.boardsConfigDialog.open(true, params),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,78 +0,0 @@
|
||||
import { MessageService } from '@theia/core';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { LocalStorageService } from '@theia/core/lib/browser';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||
import { ArduinoPreferences } from '../arduino-preferences';
|
||||
import { SurveyNotificationService } from '../../common/protocol/survey-service';
|
||||
|
||||
const SURVEY_MESSAGE = nls.localize(
|
||||
'arduino/survey/surveyMessage',
|
||||
'Please help us improve by answering this super short survey. We value our community and would like to get to know our supporters a little better.'
|
||||
);
|
||||
const DO_NOT_SHOW_AGAIN = nls.localize(
|
||||
'arduino/survey/dismissSurvey',
|
||||
"Don't show again"
|
||||
);
|
||||
const GO_TO_SURVEY = nls.localize(
|
||||
'arduino/survey/answerSurvey',
|
||||
'Answer survey'
|
||||
);
|
||||
|
||||
const SURVEY_BASE_URL = 'https://surveys.hotjar.com/';
|
||||
const surveyId = '17887b40-e1f0-4bd6-b9f0-a37f229ccd8b';
|
||||
|
||||
@injectable()
|
||||
export class SurveyNotification implements FrontendApplicationContribution {
|
||||
@inject(MessageService)
|
||||
private readonly messageService: MessageService;
|
||||
|
||||
@inject(LocalStorageService)
|
||||
private readonly localStorageService: LocalStorageService;
|
||||
|
||||
@inject(WindowService)
|
||||
private readonly windowService: WindowService;
|
||||
|
||||
@inject(ArduinoPreferences)
|
||||
private readonly arduinoPreferences: ArduinoPreferences;
|
||||
|
||||
@inject(SurveyNotificationService)
|
||||
private readonly surveyNotificationService: SurveyNotificationService;
|
||||
|
||||
onStart(): void {
|
||||
this.arduinoPreferences.ready.then(async () => {
|
||||
if (
|
||||
(await this.surveyNotificationService.isFirstInstance()) &&
|
||||
this.arduinoPreferences.get('arduino.survey.notification')
|
||||
) {
|
||||
const surveyAnswered = await this.localStorageService.getData(
|
||||
this.surveyKey(surveyId)
|
||||
);
|
||||
if (surveyAnswered !== undefined) {
|
||||
return;
|
||||
}
|
||||
const answer = await this.messageService.info(
|
||||
SURVEY_MESSAGE,
|
||||
DO_NOT_SHOW_AGAIN,
|
||||
GO_TO_SURVEY
|
||||
);
|
||||
switch (answer) {
|
||||
case GO_TO_SURVEY:
|
||||
this.windowService.openNewWindow(SURVEY_BASE_URL + surveyId, {
|
||||
external: true,
|
||||
});
|
||||
this.localStorageService.setData(this.surveyKey(surveyId), true);
|
||||
break;
|
||||
case DO_NOT_SHOW_AGAIN:
|
||||
this.localStorageService.setData(this.surveyKey(surveyId), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private surveyKey(id: string): string {
|
||||
return `answered_survey:${id}`;
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { Emitter, Event } from '@theia/core/lib/common/event';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
|
@@ -5,7 +5,7 @@ import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import {
|
||||
Stat,
|
||||
FileType,
|
||||
|
@@ -261,6 +261,7 @@ export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> {
|
||||
}
|
||||
|
||||
override async open(
|
||||
disposeOnResolve = true,
|
||||
data: UpdateInfo | undefined = undefined
|
||||
): Promise<UpdateInfo | undefined> {
|
||||
if (data && data.version) {
|
||||
@@ -271,7 +272,7 @@ export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> {
|
||||
error: undefined,
|
||||
});
|
||||
this.updateInfo = data;
|
||||
return super.open();
|
||||
return super.open(disposeOnResolve);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ export class IDEUpdaterCommands implements CommandContribution {
|
||||
try {
|
||||
const updateInfo = await this.updater.checkForUpdates(initialCheck);
|
||||
if (!!updateInfo) {
|
||||
this.updaterDialog.open(updateInfo);
|
||||
this.updaterDialog.open(true, updateInfo);
|
||||
} else {
|
||||
this.messageService.info(
|
||||
nls.localize(
|
||||
|
@@ -6,7 +6,7 @@ import {
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { JsonRpcProxy } from '@theia/core/lib/common/messaging/proxy-factory';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import {
|
||||
IndexUpdateDidCompleteParams,
|
||||
IndexUpdateDidFailParams,
|
||||
|
@@ -9,7 +9,7 @@ import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { Sketch, SketchesService } from '../common/protocol';
|
||||
import { ConfigServiceClient } from './config/config-service-client';
|
||||
import {
|
||||
@@ -74,6 +74,7 @@ export class SketchesServiceClientImpl
|
||||
const sketchDirUri = this.configService.tryGetSketchDirUri();
|
||||
this.watchSketchbookDir(sketchDirUri);
|
||||
const refreshCurrentSketch = async () => {
|
||||
await this.workspaceService.ready;
|
||||
const currentSketch = await this.loadCurrentSketch();
|
||||
const ideTempFolderUri = await this.getIdeTempFolderUriForSketch(
|
||||
currentSketch
|
||||
@@ -287,7 +288,7 @@ export class SketchesServiceClientImpl
|
||||
* `true` if the `uri` is not contained in any of the opened workspaces. Otherwise, `false`.
|
||||
*/
|
||||
isReadOnly(uri: URI | monaco.Uri | string): boolean {
|
||||
const toCheck = uri instanceof URI ? uri : new URI(uri);
|
||||
const toCheck = uri instanceof URI ? uri : new URI(uri.toString());
|
||||
if (toCheck.scheme === 'user-storage') {
|
||||
return false;
|
||||
}
|
||||
|
@@ -98,16 +98,12 @@
|
||||
color: var(--theia-textLink-foreground);
|
||||
}
|
||||
|
||||
.account-icon {
|
||||
img.arduino-account-picture {
|
||||
width: var(--theia-private-sidebar-icon-size);
|
||||
height: var(--theia-private-sidebar-icon-size);
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.account-icon > img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.connected-status-icon {
|
||||
|
@@ -2,7 +2,7 @@ import {
|
||||
CommonCommands,
|
||||
CommonFrontendContribution as TheiaCommonFrontendContribution,
|
||||
} from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application';
|
||||
import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import type { KeybindingRegistry } from '@theia/core/lib/browser/keybinding';
|
||||
import type { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import type { MenuModelRegistry } from '@theia/core/lib/common/menu';
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
ApplicationConnectionStatusContribution as TheiaApplicationConnectionStatusContribution,
|
||||
ConnectionStatus,
|
||||
ApplicationConnectionStatusContribution as TheiaApplicationConnectionStatusContribution,
|
||||
FrontendConnectionStatusService as TheiaFrontendConnectionStatusService,
|
||||
} from '@theia/core/lib/browser/connection-status-service';
|
||||
import type { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { WebSocketConnectionProvider } from '@theia/core/lib/browser/index';
|
||||
import type { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { WebSocketConnectionSource } from '@theia/core/lib/browser/messaging/ws-connection-source';
|
||||
import { StatusBarAlignment } from '@theia/core/lib/browser/status-bar/status-bar';
|
||||
import { Disposable } from '@theia/core/lib/common/disposable';
|
||||
import { Emitter, Event } from '@theia/core/lib/common/event';
|
||||
@@ -114,8 +114,8 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat
|
||||
private readonly daemonPort: DaemonPort;
|
||||
@inject(IsOnline)
|
||||
private readonly isOnline: IsOnline;
|
||||
@inject(WebSocketConnectionProvider)
|
||||
private readonly connectionProvider: WebSocketConnectionProvider;
|
||||
@inject(WebSocketConnectionSource)
|
||||
private readonly connectionSource: WebSocketConnectionSource;
|
||||
|
||||
@postConstruct()
|
||||
protected override init(): void {
|
||||
@@ -128,7 +128,7 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat
|
||||
}
|
||||
|
||||
protected override async performPingRequest(): Promise<void> {
|
||||
if (!this.connectionProvider['socket'].connected) {
|
||||
if (!this.connectionSource['socket'].connected) {
|
||||
this.updateStatus(false);
|
||||
return;
|
||||
}
|
||||
@@ -171,8 +171,8 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon
|
||||
private readonly notificationManager: NotificationManager;
|
||||
@inject(CreateFeatures)
|
||||
private readonly createFeatures: CreateFeatures;
|
||||
@inject(WebSocketConnectionProvider)
|
||||
private readonly connectionProvider: WebSocketConnectionProvider;
|
||||
@inject(WebSocketConnectionSource)
|
||||
private readonly connectionSource: WebSocketConnectionSource;
|
||||
|
||||
private readonly offlineStatusDidChangeEmitter = new Emitter<
|
||||
OfflineConnectionStatus | undefined
|
||||
@@ -202,7 +202,7 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon
|
||||
const params = <OfflineMessageParams>{
|
||||
port: this.daemonPort.port,
|
||||
online: this.isOnline.online,
|
||||
backendConnected: this.connectionProvider['socket'].connected, // https://github.com/arduino/arduino-ide/issues/2081
|
||||
backendConnected: this.connectionSource['socket'].connected, // https://github.com/arduino/arduino-ide/issues/2081
|
||||
};
|
||||
this._offlineStatus = offlineConnectionStatusType(params);
|
||||
const { text, tooltip } = offlineMessage(params);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { SidebarBottomMenuWidget as TheiaSidebarBottomMenuWidget } from '@theia/core/lib/browser/shell/sidebar-bottom-menu-widget';
|
||||
import type { SidebarMenu } from '@theia/core/lib/browser/shell/sidebar-menu-widget';
|
||||
import type { SidebarMenuItem } from '@theia/core/lib/browser/shell/sidebar-menu-widget';
|
||||
import type { MenuPath } from '@theia/core/lib/common/menu';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import {
|
||||
@@ -46,46 +46,45 @@ export class SidebarBottomMenuWidget extends TheiaSidebarBottomMenuWidget {
|
||||
this.contextMenuRenderer.render(options);
|
||||
}
|
||||
|
||||
protected override render(): React.ReactNode {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.menus.map((menu) => this.renderMenu(menu))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
private renderMenu(menu: SidebarMenu): React.ReactNode {
|
||||
override renderItem(item: SidebarMenuItem): React.ReactNode {
|
||||
// Removes the _Settings_ (cog) icon from the left sidebar
|
||||
if (menu.id === 'settings-menu') {
|
||||
if (item.menu.id === 'settings-menu') {
|
||||
return undefined;
|
||||
}
|
||||
const arduinoAccount = menu.id === accountMenu.id;
|
||||
const picture =
|
||||
const arduinoAccount = item.menu.id === accountMenu.id;
|
||||
const arduinoAccountPicture =
|
||||
arduinoAccount &&
|
||||
this.connectionStatue.offlineStatus !== 'internet' &&
|
||||
this.createFeatures.session?.account.picture;
|
||||
const className = typeof picture === 'string' ? undefined : menu.iconClass;
|
||||
|
||||
return (
|
||||
<i
|
||||
key={menu.id}
|
||||
className={className}
|
||||
title={menu.title}
|
||||
onClick={(e) => this.onClick(e, menu.menuPath)}
|
||||
<div
|
||||
key={item.menu.id}
|
||||
className="theia-sidebar-menu-item"
|
||||
title={item.menu.title}
|
||||
onClick={(e) => this.onClick(e, item.menu.menuPath)}
|
||||
onMouseDown={this.onMouseDown}
|
||||
onMouseEnter={(e) => this.onMouseEnter(e, item.menu.title)}
|
||||
onMouseOut={this.onMouseOut}
|
||||
>
|
||||
{picture && (
|
||||
<div className="account-icon">
|
||||
{arduinoAccountPicture ? (
|
||||
<i>
|
||||
<img
|
||||
src={picture}
|
||||
className="arduino-account-picture"
|
||||
src={arduinoAccountPicture}
|
||||
alt={nls.localize(
|
||||
'arduino/cloud/profilePicture',
|
||||
'Profile picture'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</i>
|
||||
) : (
|
||||
<i className={item.menu.iconClass} />
|
||||
)}
|
||||
</i>
|
||||
{item.badge && (
|
||||
<div className="theia-badge-decorator-sidebar">{item.badge}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { DebugSessionConnection } from '@theia/debug/lib/browser/debug-session-connection';
|
||||
import { DefaultDebugSessionFactory as TheiaDefaultDebugSessionFactory } from '@theia/debug/lib/browser/debug-session-contribution';
|
||||
import { DebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
|
||||
import { DebugConfigurationSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
|
||||
import {
|
||||
DebugAdapterPath,
|
||||
@@ -12,6 +13,7 @@ import { DebugSession } from './debug-session';
|
||||
@injectable()
|
||||
export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory {
|
||||
override get(
|
||||
manager: DebugSessionManager,
|
||||
sessionId: string,
|
||||
options: DebugConfigurationSessionOptions,
|
||||
parentSession?: DebugSession
|
||||
@@ -20,12 +22,12 @@ export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory
|
||||
sessionId,
|
||||
() =>
|
||||
new Promise<DebugChannel>((resolve) =>
|
||||
this.connectionProvider.openChannel(
|
||||
this.connectionProvider.listen(
|
||||
`${DebugAdapterPath}/${sessionId}`,
|
||||
(wsChannel) => {
|
||||
(_, wsChannel) => {
|
||||
resolve(new ForwardingDebugChannel(wsChannel));
|
||||
},
|
||||
{ reconnecting: false }
|
||||
false
|
||||
)
|
||||
),
|
||||
this.getTraceOutputChannel()
|
||||
@@ -35,6 +37,9 @@ export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory
|
||||
sessionId,
|
||||
options,
|
||||
parentSession,
|
||||
this.testService,
|
||||
options.testRun,
|
||||
manager,
|
||||
connection,
|
||||
this.terminalService,
|
||||
this.editorManager,
|
||||
|
@@ -1,21 +0,0 @@
|
||||
import { injectable, postConstruct } from '@theia/core/shared/inversify';
|
||||
import { EditorCommandContribution as TheiaEditorCommandContribution } from '@theia/editor/lib/browser/editor-command';
|
||||
|
||||
@injectable()
|
||||
export class EditorCommandContribution extends TheiaEditorCommandContribution {
|
||||
@postConstruct()
|
||||
protected override init(): void {
|
||||
// Workaround for https://github.com/eclipse-theia/theia/issues/8722.
|
||||
this.editorPreferences.onPreferenceChanged(
|
||||
({ preferenceName, newValue, oldValue }) => {
|
||||
if (preferenceName === 'files.autoSave') {
|
||||
const autoSaveWasOnBeforeChange = !oldValue || oldValue !== 'off';
|
||||
const autoSaveIsOnAfterChange = !newValue || newValue !== 'off';
|
||||
if (!autoSaveWasOnBeforeChange && autoSaveIsOnAfterChange) {
|
||||
this.shell.saveAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,19 +1,18 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { TextEditor } from '@theia/editor/lib/browser';
|
||||
import { EditorContribution as TheiaEditorContribution } from '@theia/editor/lib/browser/editor-contribution';
|
||||
|
||||
@injectable()
|
||||
export class EditorContribution extends TheiaEditorContribution {
|
||||
protected override updateLanguageStatus(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
|
||||
editor: TextEditor | undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
..._: Parameters<TheiaEditorContribution['updateLanguageStatus']>
|
||||
): void {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
protected override updateEncodingStatus(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
|
||||
editor: TextEditor | undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
..._: Parameters<TheiaEditorContribution['updateEncodingStatus']>
|
||||
): void {
|
||||
// https://github.com/arduino/arduino-ide/issues/1393
|
||||
// NOOP
|
||||
|
@@ -36,7 +36,7 @@ export class FileResourceResolver extends TheiaFileResourceResolver {
|
||||
);
|
||||
}
|
||||
return new WriteQueuedFileResource(uri, this.fileService, {
|
||||
isReadonly: stat?.isReadonly ?? false,
|
||||
readOnly: stat?.isReadonly ?? false,
|
||||
shouldOverwrite: () => this.shouldOverwrite(uri),
|
||||
shouldOpenAsText: (error) => this.shouldOpenAsText(uri, error),
|
||||
});
|
||||
|
@@ -117,7 +117,7 @@ export function maybeUpdateReadOnlyState(
|
||||
const model = editor.document;
|
||||
const oldReadOnly = model.readOnly;
|
||||
const resource = model['resource'];
|
||||
const newReadOnly = Boolean(resource.isReadonly) || isReadOnly(resource.uri);
|
||||
const newReadOnly = Boolean(resource.readOnly) || isReadOnly(resource.uri);
|
||||
if (oldReadOnly !== newReadOnly) {
|
||||
editor.getControl().updateOptions({ readOnly: newReadOnly });
|
||||
if (newReadOnly) {
|
||||
|
@@ -20,7 +20,7 @@ export class MonacoTextModelService extends TheiaMonacoTextModelService {
|
||||
.getContributions()
|
||||
.find(({ scheme }) => resource.uri.scheme === scheme);
|
||||
const readOnly =
|
||||
Boolean(resource.isReadonly) ||
|
||||
Boolean(resource.readOnly) ||
|
||||
this.sketchesServiceClient.isReadOnly(resource.uri);
|
||||
return factory
|
||||
? factory.createModel(resource)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { ThemeService } from '@theia/core/lib/browser/theming';
|
||||
import {
|
||||
Disposable,
|
||||
|
@@ -1,11 +1,9 @@
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import type { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { Emitter, Event } from '@theia/core/lib/common/event';
|
||||
import { injectable, interfaces } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
PluginContributions,
|
||||
HostedPluginSupport as TheiaHostedPluginSupport,
|
||||
} from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
|
||||
import { HostedPluginSupport } from '../../hosted/hosted-plugin-support';
|
||||
import { HostedPluginSupport as TheiaHostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
|
||||
import type { PluginContributions } from '@theia/plugin-ext/lib/hosted/common/hosted-plugin';
|
||||
import type { HostedPluginSupport } from '../../hosted/hosted-plugin-support';
|
||||
|
||||
@injectable()
|
||||
export class HostedPluginSupportImpl
|
||||
|
@@ -1,241 +0,0 @@
|
||||
import { LabelIcon } from '@theia/core/lib/browser/label-parser';
|
||||
import { OpenerService, open } from '@theia/core/lib/browser/opener-service';
|
||||
import { codicon } from '@theia/core/lib/browser/widgets/widget';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { URI } from '@theia/core/lib/common/uri';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { URI as CodeUri } from '@theia/core/shared/vscode-uri';
|
||||
import { TreeViewWidget as TheiaTreeViewWidget } from '@theia/plugin-ext/lib/main/browser/view/tree-view-widget';
|
||||
|
||||
// Copied back from https://github.com/eclipse-theia/theia/pull/14391
|
||||
// Remove the patching when Arduino uses Eclipse Theia >1.55.0
|
||||
// https://github.com/eclipse-theia/theia/blob/8d3c5a11af65448b6700bedd096f8d68f0675541/packages/core/src/browser/tree/tree-view-welcome-widget.tsx#L37-L54
|
||||
// https://github.com/eclipse-theia/theia/blob/8d3c5a11af65448b6700bedd096f8d68f0675541/packages/core/src/browser/tree/tree-view-welcome-widget.tsx#L146-L298
|
||||
|
||||
interface ViewWelcome {
|
||||
readonly view: string;
|
||||
readonly content: string;
|
||||
readonly when?: string;
|
||||
readonly enablement?: string;
|
||||
readonly order: number;
|
||||
}
|
||||
|
||||
export interface IItem {
|
||||
readonly welcomeInfo: ViewWelcome;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export interface ILink {
|
||||
readonly label: string;
|
||||
readonly href: string;
|
||||
readonly title?: string;
|
||||
}
|
||||
|
||||
type LinkedTextItem = string | ILink;
|
||||
|
||||
@injectable()
|
||||
export class TreeViewWidget extends TheiaTreeViewWidget {
|
||||
@inject(OpenerService)
|
||||
private readonly openerService: OpenerService;
|
||||
|
||||
private readonly toDisposeBeforeUpdateViewWelcomeNodes =
|
||||
new DisposableCollection();
|
||||
|
||||
protected override updateViewWelcomeNodes(): void {
|
||||
this.viewWelcomeNodes = [];
|
||||
this.toDisposeBeforeUpdateViewWelcomeNodes.dispose();
|
||||
const items = this.visibleItems.sort((a, b) => a.order - b.order);
|
||||
|
||||
const enablementKeys: Set<string>[] = [];
|
||||
// the plugin-view-registry will push the changes when there is a change in the `when` prop which controls the visibility
|
||||
// this listener is to update the enablement of the components in the view welcome
|
||||
this.toDisposeBeforeUpdateViewWelcomeNodes.push(
|
||||
this.contextService.onDidChange((event) => {
|
||||
if (enablementKeys.some((keys) => event.affects(keys))) {
|
||||
this.updateViewWelcomeNodes();
|
||||
this.update();
|
||||
}
|
||||
})
|
||||
);
|
||||
// Note: VS Code does not support the `renderSecondaryButtons` prop in welcome content either.
|
||||
for (const item of items) {
|
||||
const { content } = item;
|
||||
const enablement = isEnablementAware(item) ? item.enablement : undefined;
|
||||
const itemEnablementKeys = enablement
|
||||
? this.contextService.parseKeys(enablement)
|
||||
: undefined;
|
||||
if (itemEnablementKeys) {
|
||||
enablementKeys.push(itemEnablementKeys);
|
||||
}
|
||||
const lines = content.split('\n');
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.trim();
|
||||
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const linkedTextItems = this.parseLinkedText_patch14309(line);
|
||||
|
||||
if (
|
||||
linkedTextItems.length === 1 &&
|
||||
typeof linkedTextItems[0] !== 'string'
|
||||
) {
|
||||
const node = linkedTextItems[0];
|
||||
this.viewWelcomeNodes.push(
|
||||
this.renderButtonNode_patch14309(
|
||||
node,
|
||||
this.viewWelcomeNodes.length,
|
||||
enablement
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const renderNode = (item: LinkedTextItem, index: number) =>
|
||||
typeof item == 'string'
|
||||
? this.renderTextNode_patch14309(item, index)
|
||||
: this.renderLinkNode_patch14309(item, index, enablement);
|
||||
|
||||
this.viewWelcomeNodes.push(
|
||||
<p key={`p-${this.viewWelcomeNodes.length}`}>
|
||||
{...linkedTextItems.flatMap(renderNode)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private renderButtonNode_patch14309(
|
||||
node: ILink,
|
||||
lineKey: string | number,
|
||||
enablement: string | undefined
|
||||
): React.ReactNode {
|
||||
return (
|
||||
<div key={`line-${lineKey}`} className="theia-WelcomeViewButtonWrapper">
|
||||
<button
|
||||
title={node.title}
|
||||
className="theia-button theia-WelcomeViewButton"
|
||||
disabled={!this.isEnabledClick_patch14309(enablement)}
|
||||
onClick={(e) => this.openLinkOrCommand_patch14309(e, node.href)}
|
||||
>
|
||||
{node.label}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderTextNode_patch14309(
|
||||
node: string,
|
||||
textKey: string | number
|
||||
): React.ReactNode {
|
||||
return (
|
||||
<span key={`text-${textKey}`}>
|
||||
{this.labelParser
|
||||
.parse(node)
|
||||
.map((segment, index) =>
|
||||
LabelIcon.is(segment) ? (
|
||||
<span key={index} className={codicon(segment.name)} />
|
||||
) : (
|
||||
<span key={index}>{segment}</span>
|
||||
)
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
private renderLinkNode_patch14309(
|
||||
node: ILink,
|
||||
linkKey: string | number,
|
||||
enablement: string | undefined
|
||||
): React.ReactNode {
|
||||
return (
|
||||
<a
|
||||
key={`link-${linkKey}`}
|
||||
className={this.getLinkClassName_patch14309(node.href, enablement)}
|
||||
title={node.title || ''}
|
||||
onClick={(e) => this.openLinkOrCommand_patch14309(e, node.href)}
|
||||
>
|
||||
{node.label}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
private getLinkClassName_patch14309(
|
||||
href: string,
|
||||
enablement: string | undefined
|
||||
): string {
|
||||
const classNames = ['theia-WelcomeViewCommandLink'];
|
||||
// Only command-backed links can be disabled. All other, https:, file: remain enabled
|
||||
if (
|
||||
href.startsWith('command:') &&
|
||||
!this.isEnabledClick_patch14309(enablement)
|
||||
) {
|
||||
classNames.push('disabled');
|
||||
}
|
||||
return classNames.join(' ');
|
||||
}
|
||||
|
||||
private isEnabledClick_patch14309(enablement: string | undefined): boolean {
|
||||
return typeof enablement === 'string'
|
||||
? this.contextService.match(enablement)
|
||||
: true;
|
||||
}
|
||||
|
||||
private openLinkOrCommand_patch14309 = (
|
||||
event: React.MouseEvent,
|
||||
value: string
|
||||
): void => {
|
||||
event.stopPropagation();
|
||||
|
||||
if (value.startsWith('command:')) {
|
||||
const command = value.replace('command:', '');
|
||||
this.commands.executeCommand(command);
|
||||
} else if (value.startsWith('file:')) {
|
||||
const uri = value.replace('file:', '');
|
||||
open(this.openerService, new URI(CodeUri.file(uri).toString()));
|
||||
} else {
|
||||
this.windowService.openNewWindow(value, { external: true });
|
||||
}
|
||||
};
|
||||
|
||||
private parseLinkedText_patch14309(text: string): LinkedTextItem[] {
|
||||
const result: LinkedTextItem[] = [];
|
||||
|
||||
const linkRegex =
|
||||
/\[([^\]]+)\]\(((?:https?:\/\/|command:|file:)[^\)\s]+)(?: (["'])(.+?)(\3))?\)/gi;
|
||||
let index = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
while ((match = linkRegex.exec(text))) {
|
||||
if (match.index - index > 0) {
|
||||
result.push(text.substring(index, match.index));
|
||||
}
|
||||
|
||||
const [, label, href, , title] = match;
|
||||
|
||||
if (title) {
|
||||
result.push({ label, href, title });
|
||||
} else {
|
||||
result.push({ label, href });
|
||||
}
|
||||
|
||||
index = match.index + match[0].length;
|
||||
}
|
||||
|
||||
if (index < text.length) {
|
||||
result.push(text.substring(index));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
interface EnablementAware {
|
||||
readonly enablement: string | undefined;
|
||||
}
|
||||
|
||||
function isEnablementAware(arg: unknown): arg is EnablementAware {
|
||||
return !!arg && typeof arg === 'object' && 'enablement' in arg;
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
import { TestViewContribution as TheiaTestViewContribution } from '@theia/test/lib/browser/view/test-view-contribution';
|
||||
import { injectable } from 'inversify';
|
||||
|
||||
@injectable()
|
||||
export class TestViewContribution extends TheiaTestViewContribution {
|
||||
override async initializeLayout(): Promise<void> {
|
||||
// NOOP
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ import {
|
||||
TabBarToolbarRegistry,
|
||||
TabBarToolbarItem,
|
||||
ReactTabBarToolbarItem,
|
||||
RenderedToolbarItem,
|
||||
} from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { ReactWidget } from '@theia/core/lib/browser';
|
||||
@@ -14,7 +15,7 @@ export const ARDUINO_TOOLBAR_ITEM_CLASS = 'arduino-tool-item';
|
||||
export namespace ArduinoToolbarComponent {
|
||||
export interface Props {
|
||||
side: 'left' | 'right';
|
||||
items: (TabBarToolbarItem | ReactTabBarToolbarItem)[];
|
||||
items: TabBarToolbarItem[];
|
||||
commands: CommandRegistry;
|
||||
labelParser: LabelParser;
|
||||
commandIsEnabled: (id: string) => boolean;
|
||||
@@ -34,7 +35,7 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
this.state = { tooltip: '' };
|
||||
}
|
||||
|
||||
protected renderItem = (item: TabBarToolbarItem) => {
|
||||
protected renderItem = (item: RenderedToolbarItem) => {
|
||||
let innerText = '';
|
||||
let className = `arduino-tool-icon ${item.id}-icon`;
|
||||
if (item.text) {
|
||||
@@ -46,7 +47,8 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
}
|
||||
}
|
||||
}
|
||||
const command = this.props.commands.getCommand(item.command);
|
||||
const command =
|
||||
item.command && this.props.commands.getCommand(item.command);
|
||||
const cls = `${ARDUINO_TOOLBAR_ITEM_CLASS} ${
|
||||
TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM
|
||||
} ${command && this.props.commandIsEnabled(command.id) ? 'enabled' : ''} ${
|
||||
@@ -80,7 +82,9 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
const items = [
|
||||
<React.Fragment key={this.props.side + '-arduino-toolbar-tooltip'}>
|
||||
{[...this.props.items].map((item) =>
|
||||
TabBarToolbarItem.is(item) ? this.renderItem(item) : item.render()
|
||||
ReactTabBarToolbarItem.is(item)
|
||||
? item.render()
|
||||
: this.renderItem(item)
|
||||
)}
|
||||
</React.Fragment>,
|
||||
];
|
||||
@@ -94,10 +98,7 @@ export class ArduinoToolbarComponent extends React.Component<
|
||||
}
|
||||
|
||||
export class ArduinoToolbar extends ReactWidget {
|
||||
protected items = new Map<
|
||||
string,
|
||||
TabBarToolbarItem | ReactTabBarToolbarItem
|
||||
>();
|
||||
protected items = new Map<string, TabBarToolbarItem>();
|
||||
|
||||
constructor(
|
||||
protected readonly tabBarToolbarRegistry: TabBarToolbarRegistry,
|
||||
@@ -112,9 +113,7 @@ export class ArduinoToolbar extends ReactWidget {
|
||||
this.tabBarToolbarRegistry.onDidChange(() => this.updateToolbar());
|
||||
}
|
||||
|
||||
protected updateItems(
|
||||
items: Array<TabBarToolbarItem | ReactTabBarToolbarItem>
|
||||
): void {
|
||||
protected updateItems(items: Array<TabBarToolbarItem>): void {
|
||||
this.items.clear();
|
||||
const revItems = items
|
||||
.sort(TabBarToolbarItem.PRIORITY_COMPARATOR)
|
||||
@@ -163,7 +162,7 @@ export class ArduinoToolbar extends ReactWidget {
|
||||
|
||||
protected executeCommand = (e: React.MouseEvent<HTMLElement>) => {
|
||||
const item = this.items.get(e.currentTarget.id);
|
||||
if (TabBarToolbarItem.is(item)) {
|
||||
if (item && item.command) {
|
||||
this.commands.executeCommand(item.command, this, e.target);
|
||||
}
|
||||
};
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import {
|
||||
OpenerOptions,
|
||||
OpenHandler,
|
||||
|
@@ -3,7 +3,7 @@ import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
|
||||
import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service';
|
||||
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
||||
import { MainMenuManager } from '../../../common/main-menu-manager';
|
||||
import { ArduinoPreferences } from '../../arduino-preferences';
|
||||
import { SketchbookWidget } from './sketchbook-widget';
|
||||
|
@@ -1,7 +0,0 @@
|
||||
export const SurveyNotificationServicePath =
|
||||
'/services/survey-notification-service';
|
||||
export const SurveyNotificationService = Symbol('SurveyNotificationService');
|
||||
|
||||
export interface SurveyNotificationService {
|
||||
isFirstInstance(): Promise<boolean>;
|
||||
}
|
@@ -38,33 +38,33 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
this.preferencesService.onPreferenceChanged(
|
||||
debounce((e) => {
|
||||
if (e.preferenceName === 'window.menuBarVisibility') {
|
||||
this.setMenuBar();
|
||||
this.doSetMenuBar();
|
||||
}
|
||||
if (this._menu) {
|
||||
for (const cmd of this._toggledCommands) {
|
||||
const menuItem = this.findMenuById(this._menu, cmd);
|
||||
if (this.menu) {
|
||||
for (const cmd of this.toggledCommands) {
|
||||
const menuItem = this.findMenuById(this.menu, cmd);
|
||||
if (menuItem) {
|
||||
menuItem.checked = this.commandRegistry.isToggled(cmd);
|
||||
}
|
||||
}
|
||||
window.electronArduino.setMenu(this._menu); // calls the IDE2-specific implementation
|
||||
window.electronArduino.setMenu(this.menu); // calls the IDE2-specific implementation
|
||||
}
|
||||
}, 10)
|
||||
);
|
||||
this.keybindingRegistry.onKeybindingsChanged(() => {
|
||||
this.setMenuBar();
|
||||
this.doSetMenuBar();
|
||||
});
|
||||
// #endregion Theia `postConstruct`
|
||||
this.appStateService.reachedState('ready').then(() => {
|
||||
this.appReady = true;
|
||||
if (this.updateWhenReady) {
|
||||
this.setMenuBar();
|
||||
this.doSetMenuBar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
override createElectronMenuBar(): MenuDto[] {
|
||||
this._toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977
|
||||
this.toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977
|
||||
const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR);
|
||||
const menu = this.fillMenuTemplate([], menuModel, [], {
|
||||
rootMenuPath: MAIN_MENU_BAR,
|
||||
@@ -73,11 +73,11 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
menu.unshift(this.createOSXMenu());
|
||||
}
|
||||
const escapedMenu = this.escapeAmpersand(menu);
|
||||
this._menu = escapedMenu;
|
||||
this.menu = escapedMenu;
|
||||
return escapedMenu;
|
||||
}
|
||||
|
||||
override async setMenuBar(): Promise<void> {
|
||||
override async doSetMenuBar(): Promise<void> {
|
||||
// Avoid updating menu items when the app is not ready.
|
||||
// Getting the current electron window is not free and synchronous.
|
||||
// Here, we defer all menu update requests, and fire one when the app is ready.
|
||||
@@ -124,17 +124,17 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
...args
|
||||
);
|
||||
if (
|
||||
this._menu &&
|
||||
this.menu &&
|
||||
this.menuCommandExecutor.isVisible(menuPath, commandId, ...args)
|
||||
) {
|
||||
const item = this.findMenuById(this._menu, commandId);
|
||||
const item = this.findMenuById(this.menu, commandId);
|
||||
if (item) {
|
||||
item.checked = this.menuCommandExecutor.isToggled(
|
||||
menuPath,
|
||||
commandId,
|
||||
...args
|
||||
);
|
||||
window.electronArduino.setMenu(this._menu); // overridden to call the IDE2-specific implementation.
|
||||
window.electronArduino.setMenu(this.menu); // overridden to call the IDE2-specific implementation.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
parentItems.push(menuItem);
|
||||
|
||||
if (this.commandRegistry.getToggledHandler(commandId, ...args)) {
|
||||
this._toggledCommands.add(commandId);
|
||||
this.toggledCommands.add(commandId);
|
||||
}
|
||||
}
|
||||
return parentItems;
|
||||
|
@@ -7,6 +7,7 @@ import {
|
||||
hasStartupTasks,
|
||||
StartupTasks,
|
||||
} from '../../../electron-common/startup-task';
|
||||
import { WindowReloadOptions } from '@theia/core/lib/browser/window/window-service';
|
||||
|
||||
@injectable()
|
||||
export class ElectronWindowService
|
||||
@@ -17,8 +18,12 @@ export class ElectronWindowService
|
||||
|
||||
@postConstruct()
|
||||
protected override init(): void {
|
||||
// NOOP
|
||||
// Overridden to avoid calling the zoom level listener in super.
|
||||
// IDE2 listens on the zoom level changes in `ArduinoFrontendContribution#onStart`
|
||||
|
||||
window.electronTheiaCore.onAboutToClose(() => {
|
||||
this.connectionCloseService.markForClose(this.frontendIdProvider.getId());
|
||||
});
|
||||
}
|
||||
|
||||
async isFirstWindow(): Promise<boolean> {
|
||||
@@ -38,11 +43,11 @@ export class ElectronWindowService
|
||||
}
|
||||
|
||||
// Overridden to support optional task owner params and make `tsc` happy.
|
||||
override reload(options?: StartupTasks): void {
|
||||
override reload(options?: StartupTasks | WindowReloadOptions): void {
|
||||
if (hasStartupTasks(options)) {
|
||||
window.electronArduino.requestReload(options);
|
||||
} else {
|
||||
window.electronTheiaCore.requestReload();
|
||||
super.reload(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { ConnectionHandler } from '@theia/core/lib/common/messaging/handler';
|
||||
import { JsonRpcConnectionHandler } from '@theia/core/lib/common/messaging/proxy-factory';
|
||||
import { ElectronMainWindowService } from '@theia/core/lib/electron-common/electron-main-window-service';
|
||||
import { ElectronConnectionHandler } from '@theia/core/lib/electron-common/messaging/electron-connection-handler';
|
||||
import { TheiaMainApi } from '@theia/core/lib/electron-main/electron-api-main';
|
||||
import {
|
||||
ElectronMainApplication as TheiaElectronMainApplication,
|
||||
ElectronMainApplicationContribution,
|
||||
ElectronMainApplication as TheiaElectronMainApplication,
|
||||
} from '@theia/core/lib/electron-main/electron-main-application';
|
||||
import { TheiaElectronWindow as DefaultTheiaElectronWindow } from '@theia/core/lib/electron-main/theia-electron-window';
|
||||
import { ContainerModule } from '@theia/core/shared/inversify';
|
||||
@@ -33,7 +33,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(IDEUpdaterImpl).toSelf().inSingletonScope();
|
||||
bind(IDEUpdater).toService(IDEUpdaterImpl);
|
||||
bind(ElectronMainApplicationContribution).toService(IDEUpdater);
|
||||
bind(ElectronConnectionHandler)
|
||||
bind(ConnectionHandler)
|
||||
.toDynamicValue(
|
||||
(context) =>
|
||||
new JsonRpcConnectionHandler<IDEUpdaterClient>(
|
||||
|
@@ -11,16 +11,16 @@ import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { isOSX } from '@theia/core/lib/common/os';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { isObject, MaybePromise, Mutable } from '@theia/core/lib/common/types';
|
||||
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
|
||||
import {
|
||||
ElectronMainExecutionParams,
|
||||
ElectronMainCommandOptions,
|
||||
ElectronMainApplication as TheiaElectronMainApplication,
|
||||
} from '@theia/core/lib/electron-main/electron-main-application';
|
||||
import type { TheiaBrowserWindowOptions } from '@theia/core/lib/electron-main/theia-electron-window';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { URI } from '@theia/core/shared/vscode-uri';
|
||||
import { log as logToFile, setup as setupFileLog } from 'node-log-rotate';
|
||||
@@ -28,6 +28,7 @@ import { fork } from 'node:child_process';
|
||||
import { promises as fs, readFileSync, rm, rmSync } from 'node:fs';
|
||||
import type { AddressInfo } from 'node:net';
|
||||
import { isAbsolute, join, resolve } from 'node:path';
|
||||
import type { Argv } from 'yargs';
|
||||
import { Sketch } from '../../common/protocol';
|
||||
import {
|
||||
AppInfo,
|
||||
@@ -129,6 +130,11 @@ const APP_STARTED_WITH_CONTENT_TRACE =
|
||||
typeof process !== 'undefined' &&
|
||||
process.argv.indexOf('--content-trace') !== -1;
|
||||
|
||||
const createYargs: (
|
||||
argv?: string[],
|
||||
cwd?: string
|
||||
) => Argv = require('yargs/yargs');
|
||||
|
||||
@injectable()
|
||||
export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
@inject(IsTempSketch)
|
||||
@@ -171,29 +177,59 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
private readonly scheduledDeletions: Disposable[] = [];
|
||||
|
||||
override async start(config: FrontendApplicationConfig): Promise<void> {
|
||||
// Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit")
|
||||
// See: https://github.com/electron-userland/electron-builder/issues/2468
|
||||
// Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701
|
||||
console.log(`${config.applicationName} ${app.getVersion()}`);
|
||||
app.on('ready', () => app.setName(config.applicationName));
|
||||
const cwd = process.cwd();
|
||||
this.attachFileAssociations(cwd);
|
||||
this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native';
|
||||
this._config = await updateFrontendApplicationConfigFromPackageJson(config);
|
||||
this._appInfo = updateAppInfo(this._appInfo, this._config);
|
||||
this.hookApplicationEvents();
|
||||
const [port] = await Promise.all([this.startBackend(), app.whenReady()]);
|
||||
this.startContentTracing();
|
||||
this._backendPort.resolve(port);
|
||||
await Promise.all([
|
||||
this.attachElectronSecurityToken(port),
|
||||
this.startContributions(),
|
||||
]);
|
||||
return this.launch({
|
||||
secondInstance: false,
|
||||
argv: this.processArgv.getProcessArgvWithoutBin(process.argv),
|
||||
cwd,
|
||||
});
|
||||
createYargs(this.argv, process.cwd())
|
||||
.command(
|
||||
'$0 [file]',
|
||||
false,
|
||||
(cmd) =>
|
||||
cmd
|
||||
.option('electronUserData', {
|
||||
type: 'string',
|
||||
describe:
|
||||
'The area where the electron main process puts its data',
|
||||
})
|
||||
.positional('file', { type: 'string' }),
|
||||
async (args) => {
|
||||
if (args.electronUserData) {
|
||||
console.info(
|
||||
`using electron user data area : '${args.electronUserData}'`
|
||||
);
|
||||
await fs.mkdir(args.electronUserData, { recursive: true });
|
||||
app.setPath('userData', args.electronUserData);
|
||||
}
|
||||
// Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit")
|
||||
// See: https://github.com/electron-userland/electron-builder/issues/2468
|
||||
// Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701
|
||||
console.log(`${config.applicationName} ${app.getVersion()}`);
|
||||
app.on('ready', () => app.setName(config.applicationName));
|
||||
const cwd = process.cwd();
|
||||
this.attachFileAssociations(cwd);
|
||||
this.useNativeWindowFrame =
|
||||
this.getTitleBarStyle(config) === 'native';
|
||||
this._config = await updateFrontendApplicationConfigFromPackageJson(
|
||||
config
|
||||
);
|
||||
this._appInfo = updateAppInfo(this._appInfo, this._config);
|
||||
this.hookApplicationEvents();
|
||||
this.showInitialWindow(undefined);
|
||||
const [port] = await Promise.all([
|
||||
this.startBackend(),
|
||||
app.whenReady(),
|
||||
]);
|
||||
this.startContentTracing();
|
||||
this._backendPort.resolve(port);
|
||||
await Promise.all([
|
||||
this.attachElectronSecurityToken(port),
|
||||
this.startContributions(),
|
||||
]);
|
||||
this.handleMainCommand({
|
||||
file: args.file,
|
||||
cwd,
|
||||
secondInstance: false,
|
||||
});
|
||||
}
|
||||
)
|
||||
.parse();
|
||||
}
|
||||
|
||||
private startContentTracing(): void {
|
||||
@@ -284,8 +320,8 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
}
|
||||
}
|
||||
|
||||
protected override async launch(
|
||||
params: ElectronMainExecutionParams
|
||||
protected override async handleMainCommand(
|
||||
options: ElectronMainCommandOptions
|
||||
): Promise<void> {
|
||||
try {
|
||||
// When running on MacOS, we either have to wait until
|
||||
@@ -300,7 +336,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (await this.launchFromArgs(params)) {
|
||||
if (await this.launchFromArgs(options)) {
|
||||
// Application has received a file in its arguments and will skip the default application launch
|
||||
return;
|
||||
}
|
||||
@@ -314,7 +350,10 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
`Restoring workspace roots: ${workspaces.map(({ file }) => file)}`
|
||||
);
|
||||
for (const workspace of workspaces) {
|
||||
const resolvedPath = await this.resolvePath(workspace.file, params.cwd);
|
||||
const resolvedPath = await this.resolvePath(
|
||||
workspace.file,
|
||||
options.cwd
|
||||
);
|
||||
if (!resolvedPath) {
|
||||
continue;
|
||||
}
|
||||
@@ -337,15 +376,19 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
}
|
||||
this.startup = false;
|
||||
if (useDefault) {
|
||||
super.launch(params);
|
||||
super.handleMainCommand(options);
|
||||
}
|
||||
}
|
||||
|
||||
private get argv(): string[] {
|
||||
return this.processArgv.getProcessArgvWithoutBin(process.argv).slice();
|
||||
}
|
||||
|
||||
private async launchFromArgs(
|
||||
params: ElectronMainExecutionParams
|
||||
params: ElectronMainCommandOptions
|
||||
): Promise<boolean> {
|
||||
// Copy to prevent manipulation of original array
|
||||
const argCopy = [...params.argv];
|
||||
const argCopy = [...this.argv];
|
||||
let path: string | undefined;
|
||||
for (const maybePath of argCopy) {
|
||||
const resolvedPath = await this.resolvePath(maybePath, params.cwd);
|
||||
@@ -383,7 +426,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
}
|
||||
const [uri, electronWindow] = await Promise.all([
|
||||
this.createWindowUri(),
|
||||
this.createWindow(options),
|
||||
this.reuseOrCreateWindow(options),
|
||||
]);
|
||||
electronWindow.loadURL(uri.withFragment(encodeURI(file)).toString(true));
|
||||
return electronWindow;
|
||||
@@ -483,7 +526,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
argv: string[],
|
||||
cwd: string
|
||||
): Promise<void> {
|
||||
if (await this.launchFromArgs({ cwd, argv, secondInstance: true })) {
|
||||
if (await this.launchFromArgs({ cwd, secondInstance: true })) {
|
||||
// Application has received a file in its arguments
|
||||
return;
|
||||
}
|
||||
@@ -779,7 +822,7 @@ class InterruptWorkspaceRestoreError extends Error {
|
||||
// but it's the `package.json` inside the `resources/app/` folder if it's the final bundled app.
|
||||
// See https://github.com/arduino/arduino-ide/pull/2144#pullrequestreview-1556343430.
|
||||
async function updateFrontendApplicationConfigFromPackageJson(
|
||||
config: FrontendApplicationConfig
|
||||
config: Mutable<FrontendApplicationConfig>
|
||||
): Promise<FrontendApplicationConfig> {
|
||||
if (!isProductionMode) {
|
||||
console.debug(
|
||||
@@ -846,7 +889,8 @@ const fallbackFrontendAppConfig: FrontendApplicationConfig = {
|
||||
defaultIconTheme: 'none',
|
||||
validatePreferencesSchema: false,
|
||||
defaultLocale: '',
|
||||
electron: {},
|
||||
electron: { showWindowEarly: true, uriScheme: 'custom://arduino-ide' },
|
||||
reloadOnReconnect: true,
|
||||
};
|
||||
|
||||
// When the package.json must go from `./lib/backend/electron-main.js` to `./package.json` when the app is webpacked.
|
||||
|
@@ -8,7 +8,7 @@ import { ElectronArduinoRenderer } from '../electron-arduino';
|
||||
@injectable()
|
||||
export class TheiaElectronWindow extends DefaultTheiaElectronWindow {
|
||||
protected override reload(args?: unknown): void {
|
||||
this.handleStopRequest(() => {
|
||||
this.handleStopRequest(async () => {
|
||||
this.applicationState = 'init';
|
||||
if (hasStartupTasks(args)) {
|
||||
const { webContents } = this._window;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { join } from 'node:path';
|
||||
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
||||
import { spawn, ChildProcess } from 'node:child_process';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { Deferred, retry } from '@theia/core/lib/common/promise-util';
|
||||
import {
|
||||
|
@@ -105,14 +105,8 @@ import { ClangFormatter } from './clang-formatter';
|
||||
import { FormatterPath } from '../common/protocol/formatter';
|
||||
import { HostedPluginLocalizationService } from './theia/plugin-ext/hosted-plugin-localization-service';
|
||||
import { HostedPluginLocalizationService as TheiaHostedPluginLocalizationService } from '@theia/plugin-ext/lib/hosted/node/hosted-plugin-localization-service';
|
||||
import { SurveyNotificationServiceImpl } from './survey-service-impl';
|
||||
import {
|
||||
SurveyNotificationService,
|
||||
SurveyNotificationServicePath,
|
||||
} from '../common/protocol/survey-service';
|
||||
import { IsTempSketch } from './is-temp-sketch';
|
||||
import { rebindNsfwFileSystemWatcher } from './theia/filesystem/nsfw-bindings';
|
||||
import { MessagingContribution } from './theia/core/messaging-contribution';
|
||||
import { WebsocketEndpoint } from './theia/core/websocket-endpoint';
|
||||
import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service';
|
||||
import { HostedPluginReader } from './theia/plugin-ext/plugin-reader';
|
||||
import { HostedPluginReader as TheiaHostedPluginReader } from '@theia/plugin-ext/lib/hosted/node/plugin-reader';
|
||||
@@ -126,6 +120,7 @@ import {
|
||||
} from './theia/plugin-ext/plugin-deployer';
|
||||
import { SettingsReader } from './settings-reader';
|
||||
import { VsCodePluginScanner } from './theia/plugin-ext-vscode/scanner-vscode';
|
||||
import { rebindParcelFileSystemWatcher } from './theia/filesystem/parcel-bindings';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(BackendApplication).toSelf().inSingletonScope();
|
||||
@@ -305,7 +300,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
)
|
||||
)
|
||||
.inSingletonScope();
|
||||
rebindNsfwFileSystemWatcher(rebind);
|
||||
rebindParcelFileSystemWatcher(rebind);
|
||||
|
||||
// Output service per connection.
|
||||
bind(ConnectionContainerModule).toConstantValue(
|
||||
@@ -383,23 +378,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
HostedPluginLocalizationService
|
||||
);
|
||||
|
||||
// Survey notification bindings
|
||||
// It's currently unused. https://github.com/arduino/arduino-ide/pull/1150
|
||||
bind(SurveyNotificationServiceImpl).toSelf().inSingletonScope();
|
||||
bind(SurveyNotificationService).toService(SurveyNotificationServiceImpl);
|
||||
bind(ConnectionHandler)
|
||||
.toDynamicValue(
|
||||
({ container }) =>
|
||||
new JsonRpcConnectionHandler(SurveyNotificationServicePath, () =>
|
||||
container.get<SurveyNotificationService>(SurveyNotificationService)
|
||||
)
|
||||
)
|
||||
.inSingletonScope();
|
||||
|
||||
bind(IsTempSketch).toSelf().inSingletonScope();
|
||||
rebind(MessagingService.Identifier)
|
||||
.to(MessagingContribution)
|
||||
.inSingletonScope();
|
||||
rebind(MessagingService.Identifier).to(WebsocketEndpoint).inSingletonScope();
|
||||
|
||||
// Removed undesired contributions from VS Code extensions
|
||||
// Such as the RTOS view from the `cortex-debug` extension
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { constants, promises as fs } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { notEmpty } from '@theia/core/lib/common/objects';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import {
|
||||
Range,
|
||||
Position,
|
||||
|
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
|
||||
import { injectable, inject, named } from '@theia/core/shared/inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { Event, Emitter } from '@theia/core/lib/common/event';
|
||||
import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
|
||||
import {
|
||||
|
@@ -5,12 +5,13 @@ import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import type { Mutable } from '@theia/core/lib/common/types';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import * as jspb from 'google-protobuf';
|
||||
import path from 'node:path';
|
||||
import { userAbort } from '../common/nls';
|
||||
import {
|
||||
UploadResponse as ApiUploadResponse,
|
||||
OutputMessage,
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
isCompileSummary,
|
||||
isUploadResponse,
|
||||
} from '../common/protocol/core-service';
|
||||
import { UserAbortApplicationError } from '../common/protocol/progressible';
|
||||
import { ResponseService } from '../common/protocol/response-service';
|
||||
import { firstToUpperCase, notEmpty } from '../common/utils';
|
||||
import { BoardDiscovery, createApiPort } from './board-discovery';
|
||||
@@ -52,8 +54,6 @@ import { ExecuteWithProgress, ProgressResponse } from './grpc-progressible';
|
||||
import { MonitorManager } from './monitor-manager';
|
||||
import { ServiceError } from './service-error';
|
||||
import { AutoFlushingBuffer } from './utils/buffers';
|
||||
import { userAbort } from '../common/nls';
|
||||
import { UserAbortApplicationError } from '../common/protocol/progressible';
|
||||
|
||||
namespace Uploadable {
|
||||
export type Request = UploadRequest | UploadUsingProgrammerRequest;
|
||||
|
@@ -5,7 +5,7 @@ import {
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { join } from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import {
|
||||
SketchRef,
|
||||
SketchContainer,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { ExecutableService } from '../common/protocol/executable-service';
|
||||
import {
|
||||
|
@@ -6,7 +6,7 @@ import {
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { promisify } from 'util';
|
||||
import { MonitorSettingsProvider } from './monitor-settings-provider';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { FileSystemExt } from '../common/protocol/filesystem-ext';
|
||||
|
||||
@injectable()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import {
|
||||
|
@@ -6,7 +6,7 @@ import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { escapeRegExpCharacters } from '@theia/core/lib/common/strings';
|
||||
import type { Mutable } from '@theia/core/lib/common/types';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
||||
import { glob } from 'glob';
|
||||
import crypto from 'node:crypto';
|
||||
|
@@ -1,20 +0,0 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { SurveyNotificationService } from '../common/protocol/survey-service';
|
||||
|
||||
/**
|
||||
* Service for checking if it is the first instance of the IDE, in this case it sets a flag to true.
|
||||
* This flag is used to prevent the survey notification from being visible in every open window. It must only be shown on one window.
|
||||
*/
|
||||
@injectable()
|
||||
export class SurveyNotificationServiceImpl
|
||||
implements SurveyNotificationService
|
||||
{
|
||||
private surveyDidShow = false;
|
||||
async isFirstInstance(): Promise<boolean> {
|
||||
if (this.surveyDidShow) {
|
||||
return false;
|
||||
}
|
||||
this.surveyDidShow = true;
|
||||
return this.surveyDidShow;
|
||||
}
|
||||
}
|
@@ -1,7 +1,8 @@
|
||||
import { MessagingContribution as TheiaMessagingContribution } from '@theia/core/lib/node/messaging/messaging-contribution';
|
||||
import { WebsocketEndpoint as TheiaWebsocketEndpoint } from '@theia/core/lib/node/messaging/websocket-endpoint';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
|
||||
@injectable()
|
||||
export class MessagingContribution extends TheiaMessagingContribution {
|
||||
export class WebsocketEndpoint extends TheiaWebsocketEndpoint {
|
||||
// https://github.com/eclipse-theia/theia/discussions/11543
|
||||
protected override checkAliveTimeout = process.argv.includes(
|
||||
'--no-ping-timeout'
|
@@ -5,7 +5,7 @@ import {
|
||||
import { isWindows } from '@theia/core/lib/common/os';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { BackendApplicationConfigProvider } from '@theia/core/lib/node/backend-application-config-provider';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
|
@@ -1,42 +0,0 @@
|
||||
import { join } from 'node:path';
|
||||
import { interfaces } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
NsfwFileSystemWatcherServiceProcessOptions,
|
||||
NSFW_SINGLE_THREADED,
|
||||
spawnNsfwFileSystemWatcherServiceProcess,
|
||||
} from '@theia/filesystem/lib/node/filesystem-backend-module';
|
||||
import { FileSystemWatcherService } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
import { NsfwFileSystemWatcherServerOptions } from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service';
|
||||
import { FileSystemWatcherServiceDispatcher } from '@theia/filesystem/lib/node/filesystem-watcher-dispatcher';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-watcher/nsfw-filesystem-service';
|
||||
|
||||
export function rebindNsfwFileSystemWatcher(rebind: interfaces.Rebind): void {
|
||||
rebind<NsfwFileSystemWatcherServiceProcessOptions>(
|
||||
NsfwFileSystemWatcherServiceProcessOptions
|
||||
).toConstantValue({
|
||||
entryPoint: join(__dirname, 'nsfw-watcher'),
|
||||
});
|
||||
rebind<FileSystemWatcherService>(FileSystemWatcherService)
|
||||
.toDynamicValue((context) =>
|
||||
NSFW_SINGLE_THREADED
|
||||
? createNsfwFileSystemWatcherService(context)
|
||||
: spawnNsfwFileSystemWatcherServiceProcess(context)
|
||||
)
|
||||
.inSingletonScope();
|
||||
}
|
||||
|
||||
function createNsfwFileSystemWatcherService({
|
||||
container,
|
||||
}: interfaces.Context): FileSystemWatcherService {
|
||||
const options = container.get<NsfwFileSystemWatcherServerOptions>(
|
||||
NsfwFileSystemWatcherServerOptions
|
||||
);
|
||||
const dispatcher = container.get<FileSystemWatcherServiceDispatcher>(
|
||||
FileSystemWatcherServiceDispatcher
|
||||
);
|
||||
const server = new NoDelayDisposalTimeoutNsfwFileSystemWatcherService(
|
||||
options
|
||||
);
|
||||
server.setClient(dispatcher);
|
||||
return server;
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
import { join } from 'node:path';
|
||||
import { interfaces } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
FileSystemWatcherServiceProcessOptions,
|
||||
WATCHER_SINGLE_THREADED,
|
||||
spawnParcelFileSystemWatcherServiceProcess,
|
||||
} from '@theia/filesystem/lib/node/filesystem-backend-module';
|
||||
import { FileSystemWatcherService } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
import { ParcelFileSystemWatcherServerOptions } from '@theia/filesystem/lib/node/parcel-watcher/parcel-filesystem-service';
|
||||
import { FileSystemWatcherServiceDispatcher } from '@theia/filesystem/lib/node/filesystem-watcher-dispatcher';
|
||||
import { NoDelayDisposalTimeoutParcelFileSystemWatcherService } from './parcel-watcher/parcel-filesystem-service';
|
||||
|
||||
export function rebindParcelFileSystemWatcher(rebind: interfaces.Rebind): void {
|
||||
rebind<FileSystemWatcherServiceProcessOptions>(
|
||||
FileSystemWatcherServiceProcessOptions
|
||||
).toConstantValue({
|
||||
entryPoint: join(__dirname, 'parcel-watcher'),
|
||||
});
|
||||
rebind<FileSystemWatcherService>(FileSystemWatcherService)
|
||||
.toDynamicValue((context) =>
|
||||
WATCHER_SINGLE_THREADED
|
||||
? createParcelFileSystemWatcherService(context)
|
||||
: spawnParcelFileSystemWatcherServiceProcess(context)
|
||||
)
|
||||
.inSingletonScope();
|
||||
}
|
||||
|
||||
function createParcelFileSystemWatcherService({
|
||||
container,
|
||||
}: interfaces.Context): FileSystemWatcherService {
|
||||
const options = container.get<ParcelFileSystemWatcherServerOptions>(
|
||||
ParcelFileSystemWatcherServerOptions
|
||||
);
|
||||
const dispatcher = container.get<FileSystemWatcherServiceDispatcher>(
|
||||
FileSystemWatcherServiceDispatcher
|
||||
);
|
||||
const server = new NoDelayDisposalTimeoutParcelFileSystemWatcherService(
|
||||
options
|
||||
);
|
||||
server.setClient(dispatcher);
|
||||
return server;
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
import * as yargs from '@theia/core/shared/yargs';
|
||||
import { JsonRpcProxyFactory } from '@theia/core/lib/common/messaging/proxy-factory';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-filesystem-service';
|
||||
import { NoDelayDisposalTimeoutParcelFileSystemWatcherService } from './parcel-filesystem-service';
|
||||
import type { IPCEntryPoint } from '@theia/core/lib/node/messaging/ipc-protocol';
|
||||
import type { FileSystemWatcherServiceClient } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
|
||||
@@ -20,7 +20,7 @@ const options: {
|
||||
}).argv as any;
|
||||
|
||||
export default <IPCEntryPoint>((connection) => {
|
||||
const server = new NoDelayDisposalTimeoutNsfwFileSystemWatcherService(
|
||||
const server = new NoDelayDisposalTimeoutParcelFileSystemWatcherService(
|
||||
options
|
||||
);
|
||||
const factory = new JsonRpcProxyFactory<FileSystemWatcherServiceClient>(
|
@@ -1,26 +1,26 @@
|
||||
import { Minimatch } from 'minimatch';
|
||||
import type { WatchOptions } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
import {
|
||||
NsfwFileSystemWatcherService,
|
||||
NsfwWatcher,
|
||||
} from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service';
|
||||
ParcelFileSystemWatcherService,
|
||||
ParcelWatcher,
|
||||
} from '@theia/filesystem/lib/node/parcel-watcher/parcel-filesystem-service';
|
||||
|
||||
// Dispose the watcher immediately when the last reference is removed. By default, Theia waits 10 sec.
|
||||
// https://github.com/eclipse-theia/theia/issues/11639#issuecomment-1238980708
|
||||
const NoDelay = 0;
|
||||
|
||||
export class NoDelayDisposalTimeoutNsfwFileSystemWatcherService extends NsfwFileSystemWatcherService {
|
||||
export class NoDelayDisposalTimeoutParcelFileSystemWatcherService extends ParcelFileSystemWatcherService {
|
||||
protected override createWatcher(
|
||||
clientId: number,
|
||||
fsPath: string,
|
||||
options: WatchOptions
|
||||
): NsfwWatcher {
|
||||
): ParcelWatcher {
|
||||
const watcherOptions = {
|
||||
ignored: options.ignored.map(
|
||||
(pattern) => new Minimatch(pattern, { dot: true })
|
||||
),
|
||||
};
|
||||
return new NsfwWatcher(
|
||||
return new ParcelWatcher(
|
||||
clientId,
|
||||
fsPath,
|
||||
watcherOptions,
|
@@ -83,7 +83,9 @@ const cortexDebugMapper: PluginContributionMapper = (
|
||||
}
|
||||
for (const _debugger of contribution.debuggers ?? []) {
|
||||
if (_debugger.type === 'cortex-debug') {
|
||||
for (const attributes of _debugger.configurationAttributes ?? []) {
|
||||
for (const attributes of Object.values(
|
||||
_debugger.configurationAttributes ?? {}
|
||||
)) {
|
||||
if (attributes.properties) {
|
||||
// Patch the cortex-debug debug config schema to allow the in-house `configId`.
|
||||
attributes.properties['configId'] = {
|
||||
|
@@ -2,7 +2,7 @@ import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { expect } from 'chai';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import type { MaybePromise } from '@theia/core/lib/common/types';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { Container } from '@theia/core/shared/inversify';
|
||||
import { expect } from 'chai';
|
||||
import { dump, load } from 'js-yaml';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { sync as deleteSync } from 'rimraf';
|
||||
import { rimrafSync } from 'rimraf';
|
||||
import {
|
||||
BoardsService,
|
||||
CoreService,
|
||||
@@ -65,7 +65,7 @@ describe('core-client-provider', () => {
|
||||
it("should recover when the 'directories.data' folder is missing", async function () {
|
||||
this.timeout(timeout);
|
||||
const configDirPath = await prepareTestConfigDir();
|
||||
deleteSync(join(configDirPath, 'data'));
|
||||
rimrafSync(join(configDirPath, 'data'));
|
||||
|
||||
const container = await startCli(configDirPath, toDispose);
|
||||
await assertFunctionalCli(container, ({ coreClientProvider }) => {
|
||||
@@ -84,7 +84,7 @@ describe('core-client-provider', () => {
|
||||
'Arduino15',
|
||||
'package_index.json'
|
||||
);
|
||||
deleteSync(primaryPackageIndexPath);
|
||||
rimrafSync(primaryPackageIndexPath);
|
||||
|
||||
const container = await startCli(configDirPath, toDispose);
|
||||
await assertFunctionalCli(container, ({ coreClientProvider }) => {
|
||||
@@ -118,7 +118,7 @@ describe('core-client-provider', () => {
|
||||
'tools',
|
||||
tool
|
||||
);
|
||||
deleteSync(builtinToolsPath);
|
||||
rimrafSync(builtinToolsPath);
|
||||
|
||||
const container = await startCli(configDirPath, toDispose);
|
||||
await assertFunctionalCli(container, ({ coreClientProvider }) => {
|
||||
@@ -140,7 +140,7 @@ describe('core-client-provider', () => {
|
||||
'Arduino15',
|
||||
'library_index.json'
|
||||
);
|
||||
deleteSync(libraryPackageIndexPath);
|
||||
rimrafSync(libraryPackageIndexPath);
|
||||
|
||||
const container = await startCli(configDirPath, toDispose);
|
||||
await assertFunctionalCli(container, ({ coreClientProvider }) => {
|
||||
@@ -176,7 +176,7 @@ describe('core-client-provider', () => {
|
||||
'Arduino15',
|
||||
'package_teensy_index.json'
|
||||
);
|
||||
deleteSync(thirdPartyPackageIndexPath);
|
||||
rimrafSync(thirdPartyPackageIndexPath);
|
||||
|
||||
const container = await startCli(configDirPath, toDispose);
|
||||
await assertFunctionalCli(
|
||||
@@ -193,7 +193,7 @@ describe('core-client-provider', () => {
|
||||
it("should recover when invalid 3rd package URL is defined in the CLI config and the 'directories.data' folder is missing", async function () {
|
||||
this.timeout(timeout);
|
||||
const configDirPath = await prepareTestConfigDir();
|
||||
deleteSync(join(configDirPath, 'data'));
|
||||
rimrafSync(join(configDirPath, 'data'));
|
||||
|
||||
// set an invalid URL so the CLI will try to download it
|
||||
const cliConfigPath = join(configDirPath, 'arduino-cli.yaml');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { isWindows } from '@theia/core/lib/common/os';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { Container } from '@theia/core/shared/inversify';
|
||||
import { expect } from 'chai';
|
||||
import {
|
||||
|
@@ -5,7 +5,7 @@ import {
|
||||
import { EnvVariablesServer as TheiaEnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { waitForEvent } from '@theia/core/lib/common/promise-util';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { ProcessUtils } from '@theia/core/lib/node/process-utils';
|
||||
import {
|
||||
Container,
|
||||
|
@@ -2,15 +2,15 @@ import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import { isWindows } from '@theia/core/lib/common/os';
|
||||
import { URI } from '@theia/core/lib/common/uri';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { Container } from '@theia/core/shared/inversify';
|
||||
import { expect } from 'chai';
|
||||
import { rejects } from 'node:assert/strict';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import path, { basename, join } from 'node:path';
|
||||
import { sync as rimrafSync } from 'rimraf';
|
||||
import { rimrafSync } from 'rimraf';
|
||||
import temp from 'temp';
|
||||
import { Sketch, SketchesError, SketchesService } from '../../common/protocol';
|
||||
import {
|
||||
@@ -574,7 +574,7 @@ function disposeSketch(...sketch: Sketch[]): Disposable {
|
||||
function disposeFolder(...paths: string[]): Disposable {
|
||||
return new DisposableCollection(
|
||||
...paths.map((path) =>
|
||||
Disposable.create(() => rimrafSync(path, { maxBusyTries: 5 }))
|
||||
Disposable.create(() => rimrafSync(path, { maxRetries: 5 }))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import type { Mutable } from '@theia/core/lib/common/types';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { FileUri } from '@theia/core/lib/common/file-uri';
|
||||
import stableJsonStringify from 'fast-json-stable-stringify';
|
||||
import assert from 'node:assert/strict';
|
||||
import { basename, join } from 'node:path';
|
||||
|
@@ -20,5 +20,4 @@
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"files": ["../node_modules/nsfw/index.d.ts"]
|
||||
}
|
||||
|
Reference in New Issue
Block a user