mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-06 18:18:33 +00:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1104467329 | ||
![]() |
5695fd8afb | ||
![]() |
d0e383853f | ||
![]() |
3bc412b42f | ||
![]() |
f553d6919d | ||
![]() |
d6a4b0f910 | ||
![]() |
c0488d1f64 | ||
![]() |
81195431b0 | ||
![]() |
87109e6559 | ||
![]() |
c0af1e62e8 | ||
![]() |
ac9cce16f7 | ||
![]() |
3ad660927f | ||
![]() |
8778d70ad7 | ||
![]() |
fe3fbb189c |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,7 +7,7 @@ build/
|
||||
Examples/
|
||||
!electron/build/
|
||||
src-gen/
|
||||
!webpack.config.js
|
||||
webpack.config.js
|
||||
gen-webpack.config.js
|
||||
.DS_Store
|
||||
# switching from `electron` to `browser` in dev mode.
|
||||
@@ -15,8 +15,6 @@ gen-webpack.config.js
|
||||
yarn*.log
|
||||
# For the VS Code extensions used by Theia.
|
||||
plugins
|
||||
# the config files for the CLI
|
||||
arduino-ide-extension/data/cli/config
|
||||
# the tokens folder for the themes
|
||||
scripts/themes/tokens
|
||||
# environment variables
|
||||
|
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@@ -21,7 +21,8 @@
|
||||
"--plugins=local-dir:../plugins",
|
||||
"--hosted-plugin-inspect=9339",
|
||||
"--content-trace",
|
||||
"--open-devtools"
|
||||
"--open-devtools",
|
||||
"--no-ping-timeout",
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
@@ -56,7 +57,8 @@
|
||||
"--remote-debugging-port=9222",
|
||||
"--no-app-auto-install",
|
||||
"--plugins=local-dir:../plugins",
|
||||
"--hosted-plugin-inspect=9339"
|
||||
"--hosted-plugin-inspect=9339",
|
||||
"--no-ping-timeout",
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "arduino-ide-extension",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"description": "An extension for Theia building the Arduino IDE",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -21,27 +21,31 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.6.7",
|
||||
"@theia/application-package": "1.25.0",
|
||||
"@theia/core": "1.25.0",
|
||||
"@theia/editor": "1.25.0",
|
||||
"@theia/electron": "1.25.0",
|
||||
"@theia/filesystem": "1.25.0",
|
||||
"@theia/keymaps": "1.25.0",
|
||||
"@theia/markers": "1.25.0",
|
||||
"@theia/monaco": "1.25.0",
|
||||
"@theia/navigator": "1.25.0",
|
||||
"@theia/outline-view": "1.25.0",
|
||||
"@theia/output": "1.25.0",
|
||||
"@theia/preferences": "1.25.0",
|
||||
"@theia/search-in-workspace": "1.25.0",
|
||||
"@theia/terminal": "1.25.0",
|
||||
"@theia/workspace": "1.25.0",
|
||||
"@theia/application-package": "1.31.1",
|
||||
"@theia/core": "1.31.1",
|
||||
"@theia/debug": "1.31.1",
|
||||
"@theia/editor": "1.31.1",
|
||||
"@theia/electron": "1.31.1",
|
||||
"@theia/filesystem": "1.31.1",
|
||||
"@theia/keymaps": "1.31.1",
|
||||
"@theia/markers": "1.31.1",
|
||||
"@theia/messages": "1.31.1",
|
||||
"@theia/monaco": "1.31.1",
|
||||
"@theia/monaco-editor-core": "1.67.2",
|
||||
"@theia/navigator": "1.31.1",
|
||||
"@theia/outline-view": "1.31.1",
|
||||
"@theia/output": "1.31.1",
|
||||
"@theia/plugin-ext": "1.31.1",
|
||||
"@theia/preferences": "1.31.1",
|
||||
"@theia/scm": "1.31.1",
|
||||
"@theia/search-in-workspace": "1.31.1",
|
||||
"@theia/terminal": "1.31.1",
|
||||
"@theia/typehierarchy": "1.31.1",
|
||||
"@theia/workspace": "1.31.1",
|
||||
"@tippyjs/react": "^4.2.5",
|
||||
"@types/atob": "^2.1.2",
|
||||
"@types/auth0-js": "^9.14.0",
|
||||
"@types/btoa": "^1.2.3",
|
||||
"@types/dateformat": "^3.0.1",
|
||||
"@types/deep-equal": "^1.0.1",
|
||||
"@types/deepmerge": "^2.2.0",
|
||||
"@types/glob": "^7.2.0",
|
||||
"@types/google-protobuf": "^3.7.2",
|
||||
@@ -50,49 +54,50 @@
|
||||
"@types/lodash.debounce": "^4.0.6",
|
||||
"@types/ncp": "^2.0.4",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/p-queue": "^2.3.1",
|
||||
"@types/ps-tree": "^1.1.0",
|
||||
"@types/react-select": "^3.0.0",
|
||||
"@types/react-tabs": "^2.3.2",
|
||||
"@types/react-virtualized": "^9.21.21",
|
||||
"@types/temp": "^0.8.34",
|
||||
"@types/which": "^1.3.1",
|
||||
"ajv": "^6.5.3",
|
||||
"@vscode/debugprotocol": "^1.51.0",
|
||||
"arduino-serial-plotter-webapp": "0.2.0",
|
||||
"async-mutex": "^0.3.0",
|
||||
"atob": "^2.1.2",
|
||||
"auth0-js": "^9.14.0",
|
||||
"btoa": "^1.2.1",
|
||||
"classnames": "^2.3.1",
|
||||
"dateformat": "^3.0.3",
|
||||
"deep-equal": "^2.0.5",
|
||||
"deepmerge": "2.0.1",
|
||||
"electron-updater": "^4.6.5",
|
||||
"fast-safe-stringify": "^2.1.1",
|
||||
"glob": "^7.1.6",
|
||||
"google-protobuf": "^3.20.1",
|
||||
"hash.js": "^1.1.7",
|
||||
"is-valid-path": "^0.1.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"just-diff": "^5.1.1",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"keytar": "7.2.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"minimatch": "^3.1.2",
|
||||
"ncp": "^2.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"open": "^8.0.6",
|
||||
"p-queue": "^5.0.0",
|
||||
"p-debounce": "^2.1.0",
|
||||
"p-queue": "^2.4.2",
|
||||
"ps-tree": "^1.2.0",
|
||||
"query-string": "^7.0.1",
|
||||
"react-disable": "^0.1.0",
|
||||
"react-disable": "^0.1.1",
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-select": "^3.0.4",
|
||||
"react-perfect-scrollbar": "^1.5.8",
|
||||
"react-select": "^5.6.0",
|
||||
"react-tabs": "^3.1.2",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"react-window": "^1.8.6",
|
||||
"semver": "^7.3.2",
|
||||
"string-natural-compare": "^2.0.3",
|
||||
"temp": "^0.9.1",
|
||||
"temp-dir": "^2.0.0",
|
||||
"tree-kill": "^1.2.1",
|
||||
"upath": "^1.1.2",
|
||||
"url": "^0.11.0",
|
||||
"which": "^1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -101,11 +106,10 @@
|
||||
"@types/chai-string": "^1.4.2",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/react-window": "^1.8.5",
|
||||
"@types/sinon": "^10.0.6",
|
||||
"@types/sinon-chai": "^3.2.6",
|
||||
"chai": "^4.2.0",
|
||||
"chai-string": "^1.5.0",
|
||||
"decompress": "^4.2.0",
|
||||
"decompress-tarbz2": "^4.1.1",
|
||||
"decompress-targz": "^4.1.1",
|
||||
"decompress-unzip": "^4.0.1",
|
||||
"download": "^7.1.0",
|
||||
@@ -115,9 +119,6 @@
|
||||
"moment": "^2.24.0",
|
||||
"protoc": "^1.0.4",
|
||||
"shelljs": "^0.8.3",
|
||||
"sinon": "^12.0.1",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"typemoq": "^2.1.0",
|
||||
"uuid": "^3.2.1",
|
||||
"yargs": "^11.1.0"
|
||||
},
|
||||
|
@@ -31,7 +31,7 @@ import { EditorCommands, EditorMainMenu } from '@theia/editor/lib/browser';
|
||||
import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu';
|
||||
import { FileNavigatorCommands } from '@theia/navigator/lib/browser/navigator-contribution';
|
||||
import { TerminalMenus } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
|
||||
import { ArduinoPreferences } from './arduino-preferences';
|
||||
import { ElectronWindowPreferences } from '@theia/core/lib/electron-browser/window/electron-window-preferences';
|
||||
import { BoardsServiceProvider } from './boards/boards-service-provider';
|
||||
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
|
||||
import { ArduinoMenus } from './menu/arduino-menus';
|
||||
@@ -58,8 +58,8 @@ export class ArduinoFrontendContribution
|
||||
@inject(CommandRegistry)
|
||||
private readonly commandRegistry: CommandRegistry;
|
||||
|
||||
@inject(ArduinoPreferences)
|
||||
private readonly arduinoPreferences: ArduinoPreferences;
|
||||
@inject(ElectronWindowPreferences)
|
||||
private readonly electronWindowPreferences: ElectronWindowPreferences;
|
||||
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
@@ -78,10 +78,10 @@ export class ArduinoFrontendContribution
|
||||
}
|
||||
|
||||
onStart(app: FrontendApplication): void {
|
||||
this.arduinoPreferences.onPreferenceChanged((event) => {
|
||||
this.electronWindowPreferences.onPreferenceChanged((event) => {
|
||||
if (event.newValue !== event.oldValue) {
|
||||
switch (event.preferenceName) {
|
||||
case 'arduino.window.zoomLevel':
|
||||
case 'window.zoomLevel':
|
||||
if (typeof event.newValue === 'number') {
|
||||
const webContents = remote.getCurrentWebContents();
|
||||
webContents.setZoomLevel(event.newValue || 0);
|
||||
@@ -91,11 +91,10 @@ export class ArduinoFrontendContribution
|
||||
}
|
||||
});
|
||||
this.appStateService.reachedState('ready').then(() =>
|
||||
this.arduinoPreferences.ready.then(() => {
|
||||
this.electronWindowPreferences.ready.then(() => {
|
||||
const webContents = remote.getCurrentWebContents();
|
||||
const zoomLevel = this.arduinoPreferences.get(
|
||||
'arduino.window.zoomLevel'
|
||||
);
|
||||
const zoomLevel =
|
||||
this.electronWindowPreferences.get('window.zoomLevel');
|
||||
webContents.setZoomLevel(zoomLevel);
|
||||
})
|
||||
);
|
||||
|
@@ -1,12 +1,9 @@
|
||||
import '../../src/browser/style/index.css';
|
||||
import { ContainerModule } 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,
|
||||
TabBarToolbarFactory,
|
||||
} from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging/ws-connection-provider';
|
||||
import {
|
||||
FrontendApplicationContribution,
|
||||
@@ -84,10 +81,7 @@ import { BoardsAutoInstaller } from './boards/boards-auto-installer';
|
||||
import { ShellLayoutRestorer } from './theia/core/shell-layout-restorer';
|
||||
import { ListItemRenderer } from './widgets/component-list/list-item-renderer';
|
||||
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
||||
import {
|
||||
MonacoThemeJson,
|
||||
MonacoThemingService,
|
||||
} from '@theia/monaco/lib/browser/monaco-theming-service';
|
||||
|
||||
import {
|
||||
ArduinoDaemonPath,
|
||||
ArduinoDaemon,
|
||||
@@ -137,7 +131,6 @@ import { Settings } from './contributions/settings';
|
||||
import { WorkspaceCommandContribution } from './theia/workspace/workspace-commands';
|
||||
import { WorkspaceDeleteHandler as TheiaWorkspaceDeleteHandler } from '@theia/workspace/lib/browser/workspace-delete-handler';
|
||||
import { WorkspaceDeleteHandler } from './theia/workspace/workspace-delete-handler';
|
||||
import { TabBarToolbar } from './theia/core/tab-bar-toolbar';
|
||||
import { EditorWidgetFactory as TheiaEditorWidgetFactory } from '@theia/editor/lib/browser/editor-widget-factory';
|
||||
import { EditorWidgetFactory } from './theia/editor/editor-widget-factory';
|
||||
import { BurnBootloader } from './contributions/burn-bootloader';
|
||||
@@ -181,8 +174,6 @@ 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 } from './contributions/debug';
|
||||
import { DebugSessionManager } from './theia/debug/debug-session-manager';
|
||||
import { DebugSessionManager as TheiaDebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
|
||||
import { Sketchbook } from './contributions/sketchbook';
|
||||
import { DebugFrontendApplicationContribution } from './theia/debug/debug-frontend-application-contribution';
|
||||
import { DebugFrontendApplicationContribution as TheiaDebugFrontendApplicationContribution } from '@theia/debug/lib/browser/debug-frontend-application-contribution';
|
||||
@@ -241,7 +232,6 @@ import { UploadFirmware } from './contributions/upload-firmware';
|
||||
import {
|
||||
UploadFirmwareDialog,
|
||||
UploadFirmwareDialogProps,
|
||||
UploadFirmwareDialogWidget,
|
||||
} from './dialogs/firmware-uploader/firmware-uploader-dialog';
|
||||
|
||||
import { UploadCertificate } from './contributions/upload-certificate';
|
||||
@@ -258,7 +248,6 @@ import { PlotterFrontendContribution } from './serial/plotter/plotter-frontend-c
|
||||
import {
|
||||
UserFieldsDialog,
|
||||
UserFieldsDialogProps,
|
||||
UserFieldsDialogWidget,
|
||||
} from './dialogs/user-fields/user-fields-dialog';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { IDEUpdaterCommands } from './ide-updater/ide-updater-commands';
|
||||
@@ -271,7 +260,6 @@ import { IDEUpdaterClientImpl } from './ide-updater/ide-updater-client-impl';
|
||||
import {
|
||||
IDEUpdaterDialog,
|
||||
IDEUpdaterDialogProps,
|
||||
IDEUpdaterDialogWidget,
|
||||
} from './dialogs/ide-updater/ide-updater-dialog';
|
||||
import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-provider';
|
||||
import { MonitorModel } from './monitor-model';
|
||||
@@ -313,10 +301,6 @@ import { SelectedBoard } from './contributions/selected-board';
|
||||
import { CheckForIDEUpdates } from './contributions/check-for-ide-updates';
|
||||
import { OpenBoardsConfig } from './contributions/open-boards-config';
|
||||
import { SketchFilesTracker } from './contributions/sketch-files-tracker';
|
||||
import { MonacoThemeServiceIsReady } from './utils/window';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { StatusBarImpl } from './theia/core/status-bar';
|
||||
import { StatusBarImpl as TheiaStatusBarImpl } from '@theia/core/lib/browser';
|
||||
import { EditorMenuContribution } from './theia/editor/editor-file';
|
||||
import { EditorMenuContribution as TheiaEditorMenuContribution } from '@theia/editor/lib/browser/editor-menu';
|
||||
import { PreferencesEditorWidget as TheiaPreferencesEditorWidget } from '@theia/preferences/lib/browser/views/preference-editor-widget';
|
||||
@@ -337,32 +321,28 @@ import { InterfaceScale } from './contributions/interface-scale';
|
||||
import { OpenHandler } from '@theia/core/lib/browser/opener-service';
|
||||
import { NewCloudSketch } from './contributions/new-cloud-sketch';
|
||||
import { SketchbookCompositeWidget } from './widgets/sketchbook/sketchbook-composite-widget';
|
||||
|
||||
const registerArduinoThemes = () => {
|
||||
const themes: MonacoThemeJson[] = [
|
||||
{
|
||||
id: 'arduino-theme',
|
||||
label: 'Light (Arduino)',
|
||||
uiTheme: 'vs',
|
||||
json: require('../../src/browser/data/default.color-theme.json'),
|
||||
},
|
||||
{
|
||||
id: 'arduino-theme-dark',
|
||||
label: 'Dark (Arduino)',
|
||||
uiTheme: 'vs-dark',
|
||||
json: require('../../src/browser/data/dark.color-theme.json'),
|
||||
},
|
||||
];
|
||||
themes.forEach((theme) => MonacoThemingService.register(theme));
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const global = window as any;
|
||||
const ready = global[MonacoThemeServiceIsReady] as Deferred;
|
||||
if (ready) {
|
||||
ready.promise.then(registerArduinoThemes);
|
||||
} else {
|
||||
registerArduinoThemes();
|
||||
}
|
||||
import { WindowTitleUpdater } from './theia/core/window-title-updater';
|
||||
import { WindowTitleUpdater as TheiaWindowTitleUpdater } from '@theia/core/lib/browser/window/window-title-updater';
|
||||
import { ThemeService } from './theia/core/theming';
|
||||
import { ThemeService as TheiaThemeService } from '@theia/core/lib/browser/theming';
|
||||
import { MonacoThemingService } from './theia/monaco/monaco-theming-service';
|
||||
import { MonacoThemingService as TheiaMonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service';
|
||||
import { TypeHierarchyServiceProvider } from './theia/typehierarchy/type-hierarchy-service';
|
||||
import { TypeHierarchyServiceProvider as TheiaTypeHierarchyServiceProvider } from '@theia/typehierarchy/lib/browser/typehierarchy-service';
|
||||
import { TypeHierarchyContribution } from './theia/typehierarchy/type-hierarchy-contribution';
|
||||
import { TypeHierarchyContribution as TheiaTypeHierarchyContribution } from '@theia/typehierarchy/lib/browser/typehierarchy-contribution';
|
||||
import { DefaultDebugSessionFactory } from './theia/debug/debug-session-contribution';
|
||||
import { DebugSessionFactory } from '@theia/debug/lib/browser/debug-session-contribution';
|
||||
import { DebugToolbar } from './theia/debug/debug-toolbar-widget';
|
||||
import { DebugToolBar as TheiaDebugToolbar } from '@theia/debug/lib/browser/view/debug-toolbar-widget';
|
||||
import { PluginMenuCommandAdapter } from './theia/plugin-ext/plugin-menu-command-adapter';
|
||||
import { PluginMenuCommandAdapter as TheiaPluginMenuCommandAdapter } from '@theia/plugin-ext/lib/main/browser/menus/plugin-menu-command-adapter';
|
||||
import { DebugSessionManager } from './theia/debug/debug-session-manager';
|
||||
import { DebugSessionManager as TheiaDebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
|
||||
import { DebugWidget } from '@theia/debug/lib/browser/view/debug-widget';
|
||||
import { DebugViewModel } from '@theia/debug/lib/browser/view/debug-view-model';
|
||||
import { DebugSessionWidget } from '@theia/debug/lib/browser/view/debug-session-widget';
|
||||
import { DebugConfigurationWidget } from '@theia/debug/lib/browser/view/debug-configuration-widget';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
// Commands and toolbar items
|
||||
@@ -587,14 +567,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
.to(WorkspaceDeleteHandler)
|
||||
.inSingletonScope();
|
||||
rebind(TheiaEditorWidgetFactory).to(EditorWidgetFactory).inSingletonScope();
|
||||
rebind(TabBarToolbarFactory).toFactory(
|
||||
({ container: parentContainer }) =>
|
||||
() => {
|
||||
const container = parentContainer.createChild();
|
||||
container.bind(TabBarToolbar).toSelf().inSingletonScope();
|
||||
return container.get(TabBarToolbar);
|
||||
}
|
||||
);
|
||||
bind(OutputChannelManager).toSelf().inSingletonScope();
|
||||
rebind(TheiaOutputChannelManager).toService(OutputChannelManager);
|
||||
bind(OutputChannelRegistryMainImpl).toSelf().inTransientScope();
|
||||
@@ -838,9 +810,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(AboutDialog).toSelf().inSingletonScope();
|
||||
rebind(TheiaAboutDialog).toService(AboutDialog);
|
||||
|
||||
// To avoid running `Save All` when there are no dirty editors before starting the debug session.
|
||||
bind(DebugSessionManager).toSelf().inSingletonScope();
|
||||
rebind(TheiaDebugSessionManager).toService(DebugSessionManager);
|
||||
// To remove the `Run` menu item from the application menu.
|
||||
bind(DebugFrontendApplicationContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaDebugFrontendApplicationContribution).toService(
|
||||
@@ -854,10 +823,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(WidgetManager).toSelf().inSingletonScope();
|
||||
rebind(TheiaWidgetManager).toService(WidgetManager);
|
||||
|
||||
// To avoid running a status bar update on every single `keypress` event from the editor.
|
||||
bind(StatusBarImpl).toSelf().inSingletonScope();
|
||||
rebind(TheiaStatusBarImpl).toService(StatusBarImpl);
|
||||
|
||||
// Debounced update for the tab-bar toolbar when typing in the editor.
|
||||
bind(DockPanelRenderer).toSelf();
|
||||
rebind(TheiaDockPanelRenderer).toService(DockPanelRenderer);
|
||||
@@ -942,12 +907,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(LocalCacheFsProvider).toSelf().inSingletonScope();
|
||||
bind(FileServiceContribution).toService(LocalCacheFsProvider);
|
||||
bind(CloudSketchbookCompositeWidget).toSelf();
|
||||
bind<WidgetFactory>(WidgetFactory).toDynamicValue((ctx) => ({
|
||||
bind(WidgetFactory).toDynamicValue((ctx) => ({
|
||||
id: 'cloud-sketchbook-composite-widget',
|
||||
createWidget: () => ctx.container.get(CloudSketchbookCompositeWidget),
|
||||
}));
|
||||
|
||||
bind(UploadFirmwareDialogWidget).toSelf().inSingletonScope();
|
||||
bind(UploadFirmwareDialog).toSelf().inSingletonScope();
|
||||
bind(UploadFirmwareDialogProps).toConstantValue({
|
||||
title: 'UploadFirmware',
|
||||
@@ -958,13 +922,11 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
title: 'UploadCertificate',
|
||||
});
|
||||
|
||||
bind(IDEUpdaterDialogWidget).toSelf().inSingletonScope();
|
||||
bind(IDEUpdaterDialog).toSelf().inSingletonScope();
|
||||
bind(IDEUpdaterDialogProps).toConstantValue({
|
||||
title: 'IDEUpdater',
|
||||
});
|
||||
|
||||
bind(UserFieldsDialogWidget).toSelf().inSingletonScope();
|
||||
bind(UserFieldsDialog).toSelf().inSingletonScope();
|
||||
bind(UserFieldsDialogProps).toConstantValue({
|
||||
title: 'UserFields',
|
||||
@@ -991,4 +953,55 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
rebind(TheiaHostedPluginSupport).toService(HostedPluginSupport);
|
||||
bind(HostedPluginEvents).toSelf().inSingletonScope();
|
||||
bind(FrontendApplicationContribution).toService(HostedPluginEvents);
|
||||
|
||||
// custom window titles
|
||||
bind(WindowTitleUpdater).toSelf().inSingletonScope();
|
||||
rebind(TheiaWindowTitleUpdater).toService(WindowTitleUpdater);
|
||||
|
||||
// register Arduino themes
|
||||
bind(ThemeService).toSelf().inSingletonScope();
|
||||
rebind(TheiaThemeService).toService(ThemeService);
|
||||
bind(MonacoThemingService).toSelf().inSingletonScope();
|
||||
rebind(TheiaMonacoThemingService).toService(MonacoThemingService);
|
||||
|
||||
// disable type-hierarchy support
|
||||
// https://github.com/eclipse-theia/theia/commit/16c88a584bac37f5cf3cc5eb92ffdaa541bda5be
|
||||
bind(TypeHierarchyServiceProvider).toSelf().inSingletonScope();
|
||||
rebind(TheiaTypeHierarchyServiceProvider).toService(
|
||||
TypeHierarchyServiceProvider
|
||||
);
|
||||
bind(TypeHierarchyContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaTypeHierarchyContribution).toService(TypeHierarchyContribution);
|
||||
|
||||
// patched the debugger for `cortex-debug@1.5.1`
|
||||
// https://github.com/eclipse-theia/theia/issues/11871
|
||||
// https://github.com/eclipse-theia/theia/issues/11879
|
||||
// https://github.com/eclipse-theia/theia/issues/11880
|
||||
// https://github.com/eclipse-theia/theia/issues/11885
|
||||
// https://github.com/eclipse-theia/theia/issues/11886
|
||||
// https://github.com/eclipse-theia/theia/issues/11916
|
||||
// based on: https://github.com/eclipse-theia/theia/compare/master...kittaakos:theia:%2311871
|
||||
bind(DefaultDebugSessionFactory).toSelf().inSingletonScope();
|
||||
rebind(DebugSessionFactory).toService(DefaultDebugSessionFactory);
|
||||
bind(DebugSessionManager).toSelf().inSingletonScope();
|
||||
rebind(TheiaDebugSessionManager).toService(DebugSessionManager);
|
||||
bind(DebugToolbar).toSelf().inSingletonScope();
|
||||
rebind(TheiaDebugToolbar).toService(DebugToolbar);
|
||||
bind(PluginMenuCommandAdapter).toSelf().inSingletonScope();
|
||||
rebind(TheiaPluginMenuCommandAdapter).toService(PluginMenuCommandAdapter);
|
||||
bind(WidgetFactory)
|
||||
.toDynamicValue(({ container }) => ({
|
||||
id: DebugWidget.ID,
|
||||
createWidget: () => {
|
||||
const child = new Container({ defaultScope: 'Singleton' });
|
||||
child.parent = container;
|
||||
child.bind(DebugViewModel).toSelf();
|
||||
child.bind(DebugToolbar).toSelf(); // patched toolbar
|
||||
child.bind(DebugSessionWidget).toSelf();
|
||||
child.bind(DebugConfigurationWidget).toSelf();
|
||||
child.bind(DebugWidget).toSelf();
|
||||
return child.get(DebugWidget);
|
||||
},
|
||||
}))
|
||||
.inSingletonScope();
|
||||
});
|
||||
|
@@ -114,11 +114,12 @@ export const ArduinoConfigSchema: PreferenceSchema = {
|
||||
},
|
||||
'arduino.window.zoomLevel': {
|
||||
type: 'number',
|
||||
description: nls.localize(
|
||||
'arduino/preferences/window.zoomLevel',
|
||||
'Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.'
|
||||
),
|
||||
description: '',
|
||||
default: 0,
|
||||
deprecationMessage: nls.localize(
|
||||
'arduino/preferences/window.zoomLevel/deprecationMessage',
|
||||
"Deprecated. Use 'window.zoomLevel' instead."
|
||||
),
|
||||
},
|
||||
'arduino.ide.updateChannel': {
|
||||
type: 'string',
|
||||
@@ -270,7 +271,6 @@ export interface ArduinoConfiguration {
|
||||
'arduino.upload.verbose': boolean;
|
||||
'arduino.upload.verify': boolean;
|
||||
'arduino.window.autoScale': boolean;
|
||||
'arduino.window.zoomLevel': number;
|
||||
'arduino.ide.updateChannel': UpdateChannel;
|
||||
'arduino.ide.updateBaseUrl': string;
|
||||
'arduino.board.certificates': string;
|
||||
|
@@ -202,11 +202,12 @@ export class NewCloudSketch extends Contribution {
|
||||
private treeModelFrom(
|
||||
widget: SketchbookWidget
|
||||
): CloudSketchbookTreeModel | undefined {
|
||||
const treeWidget = widget.getTreeWidget();
|
||||
if (treeWidget instanceof CloudSketchbookTreeWidget) {
|
||||
const model = treeWidget.model;
|
||||
if (model instanceof CloudSketchbookTreeModel) {
|
||||
return model;
|
||||
for (const treeWidget of widget.getTreeWidgets()) {
|
||||
if (treeWidget instanceof CloudSketchbookTreeWidget) {
|
||||
const model = treeWidget.model;
|
||||
if (model instanceof CloudSketchbookTreeModel) {
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
@@ -20,7 +20,8 @@ import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
export class OpenSketchFiles extends SketchContribution {
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(OpenSketchFiles.Commands.OPEN_SKETCH_FILES, {
|
||||
execute: (uri: URI) => this.openSketchFiles(uri),
|
||||
execute: (uri: URI, focusMainSketchFile) =>
|
||||
this.openSketchFiles(uri, focusMainSketchFile),
|
||||
});
|
||||
registry.registerCommand(OpenSketchFiles.Commands.ENSURE_OPENED, {
|
||||
execute: (
|
||||
@@ -33,13 +34,19 @@ export class OpenSketchFiles extends SketchContribution {
|
||||
});
|
||||
}
|
||||
|
||||
private async openSketchFiles(uri: URI): Promise<void> {
|
||||
private async openSketchFiles(
|
||||
uri: URI,
|
||||
focusMainSketchFile = false
|
||||
): Promise<void> {
|
||||
try {
|
||||
const sketch = await this.sketchService.loadSketch(uri.toString());
|
||||
const { mainFileUri, rootFolderFileUris } = sketch;
|
||||
for (const uri of [mainFileUri, ...rootFolderFileUris]) {
|
||||
await this.ensureOpened(uri);
|
||||
}
|
||||
if (focusMainSketchFile) {
|
||||
await this.ensureOpened(mainFileUri, true, { mode: 'activate' });
|
||||
}
|
||||
if (mainFileUri.endsWith('.pde')) {
|
||||
const message = nls.localize(
|
||||
'arduino/common/oldFormat',
|
||||
@@ -126,7 +133,7 @@ export class OpenSketchFiles extends SketchContribution {
|
||||
uri: string,
|
||||
forceOpen = false,
|
||||
options?: EditorOpenerOptions
|
||||
): Promise<unknown> {
|
||||
): Promise<EditorWidget | undefined> {
|
||||
const widget = this.editorManager.all.find(
|
||||
(widget) => widget.editor.uri.toString() === uri
|
||||
);
|
||||
@@ -184,23 +191,24 @@ export class OpenSketchFiles extends SketchContribution {
|
||||
// The editor is expected to be attached to the shell and visible in the UI.
|
||||
// The deferred promise does not have to wait for the `editorManager#onCreated` event.
|
||||
// It can resolve earlier.
|
||||
if (!widget) {
|
||||
if (widget) {
|
||||
deferred.resolve(editorWidget);
|
||||
}
|
||||
});
|
||||
|
||||
const timeout = 5_000; // number of ms IDE2 waits for the editor to show up in the UI
|
||||
const result = await Promise.race([
|
||||
const result: EditorWidget | undefined | 'timeout' = await Promise.race([
|
||||
deferred.promise,
|
||||
wait(timeout).then(() => {
|
||||
disposables.dispose();
|
||||
return 'timeout';
|
||||
return 'timeout' as const;
|
||||
}),
|
||||
]);
|
||||
if (result === 'timeout') {
|
||||
console.warn(
|
||||
`Timeout after ${timeout} millis. The editor has not shown up in time. URI: ${uri}`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -235,7 +235,7 @@ export class SketchControl extends SketchContribution {
|
||||
});
|
||||
registry.registerKeybinding({
|
||||
command: CommonCommands.PREVIOUS_TAB.id,
|
||||
keybinding: 'CtrlCmd+Alt+Left', // TODO: check why electron does not show the keybindings in the UI.
|
||||
keybinding: 'CtrlCmd+Alt+Left',
|
||||
});
|
||||
registry.registerKeybinding({
|
||||
command: CommonCommands.NEXT_TAB.id,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { URI as Uri } from 'vscode-uri';
|
||||
import { URI as Uri } from '@theia/core/shared/vscode-uri';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { toPosixPath, parentPosix, posix } from './create-paths';
|
||||
import { Create } from './typings';
|
||||
|
@@ -5,10 +5,8 @@ import {
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { DialogProps } from '@theia/core/lib/browser/dialogs';
|
||||
import { AbstractDialog } from '../../theia/dialogs/dialogs';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
import { ReactDialog } from '../../theia/dialogs/dialogs';
|
||||
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
|
||||
import {
|
||||
AvailableBoard,
|
||||
BoardsServiceProvider,
|
||||
@@ -23,26 +21,30 @@ import { Port } from '../../../common/protocol';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
|
||||
@injectable()
|
||||
export class UploadFirmwareDialogWidget extends ReactWidget {
|
||||
export class UploadFirmwareDialogProps extends DialogProps {}
|
||||
|
||||
@injectable()
|
||||
export class UploadFirmwareDialog extends ReactDialog<void> {
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClient: BoardsServiceProvider;
|
||||
|
||||
private readonly boardsServiceClient: BoardsServiceProvider;
|
||||
@inject(ArduinoFirmwareUploader)
|
||||
protected readonly arduinoFirmwareUploader: ArduinoFirmwareUploader;
|
||||
|
||||
private readonly arduinoFirmwareUploader: ArduinoFirmwareUploader;
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStatusService: FrontendApplicationStateService;
|
||||
|
||||
protected updatableFqbns: string[] = [];
|
||||
protected availableBoards: AvailableBoard[] = [];
|
||||
protected isOpen = new Object();
|
||||
private updatableFqbns: string[] = [];
|
||||
private availableBoards: AvailableBoard[] = [];
|
||||
private isOpen = new Object();
|
||||
private busy = false;
|
||||
|
||||
public busyCallback = (busy: boolean) => {
|
||||
return;
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(
|
||||
@inject(UploadFirmwareDialogProps)
|
||||
protected override readonly props: UploadFirmwareDialogProps
|
||||
) {
|
||||
super({ title: UploadFirmware.Commands.OPEN.label || '' });
|
||||
this.node.id = 'firmware-uploader-dialog-container';
|
||||
this.contentNode.classList.add('firmware-uploader-dialog');
|
||||
this.acceptButton = undefined;
|
||||
}
|
||||
|
||||
@postConstruct()
|
||||
@@ -59,79 +61,34 @@ export class UploadFirmwareDialogWidget extends ReactWidget {
|
||||
});
|
||||
}
|
||||
|
||||
protected flashFirmware(firmware: FirmwareInfo, port: Port): Promise<any> {
|
||||
this.busyCallback(true);
|
||||
return this.arduinoFirmwareUploader
|
||||
.flash(firmware, port)
|
||||
.finally(() => this.busyCallback(false));
|
||||
}
|
||||
|
||||
protected override onCloseRequest(msg: Message): void {
|
||||
super.onCloseRequest(msg);
|
||||
this.isOpen = new Object();
|
||||
}
|
||||
|
||||
protected render(): React.ReactNode {
|
||||
return (
|
||||
<form>
|
||||
<FirmwareUploaderComponent
|
||||
availableBoards={this.availableBoards}
|
||||
firmwareUploader={this.arduinoFirmwareUploader}
|
||||
flashFirmware={this.flashFirmware.bind(this)}
|
||||
updatableFqbns={this.updatableFqbns}
|
||||
isOpen={this.isOpen}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class UploadFirmwareDialogProps extends DialogProps {}
|
||||
|
||||
@injectable()
|
||||
export class UploadFirmwareDialog extends AbstractDialog<void> {
|
||||
@inject(UploadFirmwareDialogWidget)
|
||||
protected readonly widget: UploadFirmwareDialogWidget;
|
||||
|
||||
private busy = false;
|
||||
|
||||
constructor(
|
||||
@inject(UploadFirmwareDialogProps)
|
||||
protected override readonly props: UploadFirmwareDialogProps
|
||||
) {
|
||||
super({ title: UploadFirmware.Commands.OPEN.label || '' });
|
||||
this.node.id = 'firmware-uploader-dialog-container';
|
||||
this.contentNode.classList.add('firmware-uploader-dialog');
|
||||
this.acceptButton = undefined;
|
||||
}
|
||||
|
||||
get value(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
protected override render(): React.ReactNode {
|
||||
return (
|
||||
<div>
|
||||
<form>
|
||||
<FirmwareUploaderComponent
|
||||
availableBoards={this.availableBoards}
|
||||
firmwareUploader={this.arduinoFirmwareUploader}
|
||||
flashFirmware={this.flashFirmware.bind(this)}
|
||||
updatableFqbns={this.updatableFqbns}
|
||||
isOpen={this.isOpen}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
protected override onAfterAttach(msg: Message): void {
|
||||
if (this.widget.isAttached) {
|
||||
Widget.detach(this.widget);
|
||||
}
|
||||
Widget.attach(this.widget, this.contentNode);
|
||||
const firstButton = this.widget.node.querySelector('button');
|
||||
const firstButton = this.node.querySelector('button');
|
||||
firstButton?.focus();
|
||||
this.widget.busyCallback = this.busyCallback.bind(this);
|
||||
super.onAfterAttach(msg);
|
||||
this.update();
|
||||
}
|
||||
|
||||
protected override onUpdateRequest(msg: Message): void {
|
||||
super.onUpdateRequest(msg);
|
||||
this.widget.update();
|
||||
}
|
||||
|
||||
protected override onActivateRequest(msg: Message): void {
|
||||
super.onActivateRequest(msg);
|
||||
this.widget.activate();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
protected override handleEnter(event: KeyboardEvent): boolean | void {
|
||||
return false;
|
||||
}
|
||||
@@ -140,11 +97,11 @@ export class UploadFirmwareDialog extends AbstractDialog<void> {
|
||||
if (this.busy) {
|
||||
return;
|
||||
}
|
||||
this.widget.close();
|
||||
super.close();
|
||||
this.isOpen = new Object();
|
||||
}
|
||||
|
||||
busyCallback(busy: boolean): void {
|
||||
private busyCallback(busy: boolean): void {
|
||||
this.busy = busy;
|
||||
if (busy) {
|
||||
this.closeCrossNode.classList.add('disabled');
|
||||
@@ -152,4 +109,11 @@ export class UploadFirmwareDialog extends AbstractDialog<void> {
|
||||
this.closeCrossNode.classList.remove('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
private flashFirmware(firmware: FirmwareInfo, port: Port): Promise<any> {
|
||||
this.busyCallback(true);
|
||||
return this.arduinoFirmwareUploader
|
||||
.flash(firmware, port)
|
||||
.finally(() => this.busyCallback(false));
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { shell } from 'electron';
|
||||
import { shell } from '@theia/core/electron-shared/@electron/remote';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import * as ReactDOM from '@theia/core/shared/react-dom';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { ProgressInfo, UpdateInfo } from '../../../common/protocol/ide-updater';
|
||||
import ProgressBar from '../../components/ProgressBar';
|
||||
@@ -28,32 +27,19 @@ export const IDEUpdaterComponent = ({
|
||||
},
|
||||
}: IDEUpdaterComponentProps): React.ReactElement => {
|
||||
const { version, releaseNotes } = updateInfo;
|
||||
const changelogDivRef =
|
||||
React.useRef() as React.MutableRefObject<HTMLDivElement>;
|
||||
const [changelog, setChangelog] = React.useState<string>('');
|
||||
React.useEffect(() => {
|
||||
if (!!releaseNotes && changelogDivRef.current) {
|
||||
let changelog: string;
|
||||
if (typeof releaseNotes === 'string') changelog = releaseNotes;
|
||||
else
|
||||
changelog = releaseNotes.reduce((acc, item) => {
|
||||
return item.note ? (acc += `${item.note}\n\n`) : acc;
|
||||
}, '');
|
||||
ReactDOM.render(
|
||||
<ReactMarkdown
|
||||
components={{
|
||||
a: ({ href, children, ...props }) => (
|
||||
<a onClick={() => href && shell.openExternal(href)} {...props}>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{changelog}
|
||||
</ReactMarkdown>,
|
||||
changelogDivRef.current
|
||||
if (releaseNotes) {
|
||||
setChangelog(
|
||||
typeof releaseNotes === 'string'
|
||||
? releaseNotes
|
||||
: releaseNotes.reduce(
|
||||
(acc, item) => (item.note ? (acc += `${item.note}\n\n`) : acc),
|
||||
''
|
||||
)
|
||||
);
|
||||
}
|
||||
}, [updateInfo]);
|
||||
}, [releaseNotes, changelog]);
|
||||
|
||||
const DownloadCompleted: () => React.ReactElement = () => (
|
||||
<div className="ide-updater-dialog--downloaded">
|
||||
@@ -106,9 +92,24 @@ export const IDEUpdaterComponent = ({
|
||||
version
|
||||
)}
|
||||
</div>
|
||||
{releaseNotes && (
|
||||
{changelog && (
|
||||
<div className="dialogRow changelog-container">
|
||||
<div className="changelog" ref={changelogDivRef} />
|
||||
<div className="changelog">
|
||||
<ReactMarkdown
|
||||
components={{
|
||||
a: ({ href, children, ...props }) => (
|
||||
<a
|
||||
onClick={() => href && shell.openExternal(href)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{changelog}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@@ -5,10 +5,8 @@ import {
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { DialogProps } from '@theia/core/lib/browser/dialogs';
|
||||
import { AbstractDialog } from '../../theia/dialogs/dialogs';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
|
||||
import { ReactDialog } from '../../theia/dialogs/dialogs';
|
||||
import { nls } from '@theia/core';
|
||||
import { IDEUpdaterComponent, UpdateProgress } from './ide-updater-component';
|
||||
import {
|
||||
@@ -22,47 +20,11 @@ import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||
|
||||
const DOWNLOAD_PAGE_URL = 'https://www.arduino.cc/en/software';
|
||||
|
||||
@injectable()
|
||||
export class IDEUpdaterDialogWidget extends ReactWidget {
|
||||
private _updateInfo: UpdateInfo;
|
||||
private _updateProgress: UpdateProgress = {};
|
||||
|
||||
setUpdateInfo(updateInfo: UpdateInfo): void {
|
||||
this._updateInfo = updateInfo;
|
||||
this.update();
|
||||
}
|
||||
|
||||
mergeUpdateProgress(updateProgress: UpdateProgress): void {
|
||||
this._updateProgress = { ...this._updateProgress, ...updateProgress };
|
||||
this.update();
|
||||
}
|
||||
|
||||
get updateInfo(): UpdateInfo {
|
||||
return this._updateInfo;
|
||||
}
|
||||
|
||||
get updateProgress(): UpdateProgress {
|
||||
return this._updateProgress;
|
||||
}
|
||||
|
||||
protected render(): React.ReactNode {
|
||||
return !!this._updateInfo ? (
|
||||
<IDEUpdaterComponent
|
||||
updateInfo={this._updateInfo}
|
||||
updateProgress={this._updateProgress}
|
||||
/>
|
||||
) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class IDEUpdaterDialogProps extends DialogProps {}
|
||||
|
||||
@injectable()
|
||||
export class IDEUpdaterDialog extends AbstractDialog<UpdateInfo> {
|
||||
@inject(IDEUpdaterDialogWidget)
|
||||
private readonly widget: IDEUpdaterDialogWidget;
|
||||
|
||||
export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> {
|
||||
@inject(IDEUpdater)
|
||||
private readonly updater: IDEUpdater;
|
||||
|
||||
@@ -75,6 +37,9 @@ export class IDEUpdaterDialog extends AbstractDialog<UpdateInfo> {
|
||||
@inject(WindowService)
|
||||
private readonly windowService: WindowService;
|
||||
|
||||
private _updateInfo: UpdateInfo | undefined;
|
||||
private _updateProgress: UpdateProgress = {};
|
||||
|
||||
constructor(
|
||||
@inject(IDEUpdaterDialogProps)
|
||||
protected override readonly props: IDEUpdaterDialogProps
|
||||
@@ -94,26 +59,34 @@ export class IDEUpdaterDialog extends AbstractDialog<UpdateInfo> {
|
||||
protected init(): void {
|
||||
this.updaterClient.onUpdaterDidFail((error) => {
|
||||
this.appendErrorButtons();
|
||||
this.widget.mergeUpdateProgress({ error });
|
||||
this.mergeUpdateProgress({ error });
|
||||
});
|
||||
this.updaterClient.onDownloadProgressDidChange((progressInfo) => {
|
||||
this.widget.mergeUpdateProgress({ progressInfo });
|
||||
this.mergeUpdateProgress({ progressInfo });
|
||||
});
|
||||
this.updaterClient.onDownloadDidFinish(() => {
|
||||
this.appendInstallButtons();
|
||||
this.widget.mergeUpdateProgress({ downloadFinished: true });
|
||||
this.mergeUpdateProgress({ downloadFinished: true });
|
||||
});
|
||||
}
|
||||
|
||||
get value(): UpdateInfo {
|
||||
return this.widget.updateInfo;
|
||||
protected render(): React.ReactNode {
|
||||
return (
|
||||
this.updateInfo && (
|
||||
<IDEUpdaterComponent
|
||||
updateInfo={this.updateInfo}
|
||||
updateProgress={this.updateProgress}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
get value(): UpdateInfo | undefined {
|
||||
return this.updateInfo;
|
||||
}
|
||||
|
||||
protected override onAfterAttach(msg: Message): void {
|
||||
if (this.widget.isAttached) {
|
||||
Widget.detach(this.widget);
|
||||
}
|
||||
Widget.attach(this.widget, this.contentNode);
|
||||
this.update();
|
||||
this.appendInitialButtons();
|
||||
super.onAfterAttach(msg);
|
||||
}
|
||||
@@ -196,15 +169,19 @@ export class IDEUpdaterDialog extends AbstractDialog<UpdateInfo> {
|
||||
}
|
||||
|
||||
private skipVersion(): void {
|
||||
if (!this.updateInfo) {
|
||||
console.warn(`Nothing to skip. No update info is available`);
|
||||
return;
|
||||
}
|
||||
this.localStorageService.setData<string>(
|
||||
SKIP_IDE_VERSION,
|
||||
this.widget.updateInfo.version
|
||||
this.updateInfo.version
|
||||
);
|
||||
this.close();
|
||||
}
|
||||
|
||||
private startDownload(): void {
|
||||
this.widget.mergeUpdateProgress({
|
||||
this.mergeUpdateProgress({
|
||||
downloadStarted: true,
|
||||
});
|
||||
this.clearButtons();
|
||||
@@ -216,31 +193,48 @@ export class IDEUpdaterDialog extends AbstractDialog<UpdateInfo> {
|
||||
this.close();
|
||||
}
|
||||
|
||||
private set updateInfo(updateInfo: UpdateInfo | undefined) {
|
||||
this._updateInfo = updateInfo;
|
||||
this.update();
|
||||
}
|
||||
|
||||
private get updateInfo(): UpdateInfo | undefined {
|
||||
return this._updateInfo;
|
||||
}
|
||||
|
||||
private get updateProgress(): UpdateProgress {
|
||||
return this._updateProgress;
|
||||
}
|
||||
|
||||
private mergeUpdateProgress(updateProgress: UpdateProgress): void {
|
||||
this._updateProgress = { ...this._updateProgress, ...updateProgress };
|
||||
this.update();
|
||||
}
|
||||
|
||||
override async open(
|
||||
data: UpdateInfo | undefined = undefined
|
||||
): Promise<UpdateInfo | undefined> {
|
||||
if (data && data.version) {
|
||||
this.widget.mergeUpdateProgress({
|
||||
this.mergeUpdateProgress({
|
||||
progressInfo: undefined,
|
||||
downloadStarted: false,
|
||||
downloadFinished: false,
|
||||
error: undefined,
|
||||
});
|
||||
this.widget.setUpdateInfo(data);
|
||||
this.updateInfo = data;
|
||||
return super.open();
|
||||
}
|
||||
}
|
||||
|
||||
protected override onActivateRequest(msg: Message): void {
|
||||
super.onActivateRequest(msg);
|
||||
this.widget.activate();
|
||||
this.update();
|
||||
}
|
||||
|
||||
override close(): void {
|
||||
this.widget.dispose();
|
||||
if (
|
||||
this.widget.updateProgress?.downloadStarted &&
|
||||
!this.widget.updateProgress?.downloadFinished
|
||||
this.updateProgress?.downloadStarted &&
|
||||
!this.updateProgress?.downloadFinished
|
||||
) {
|
||||
this.updater.stopDownload();
|
||||
}
|
||||
|
@@ -218,16 +218,14 @@ export class SettingsComponent extends React.Component<
|
||||
<div className="flex-line">
|
||||
<select
|
||||
className="theia-select"
|
||||
value={ThemeService.get().getCurrentTheme().label}
|
||||
value={this.props.themeService.getCurrentTheme().label}
|
||||
onChange={this.themeDidChange}
|
||||
>
|
||||
{ThemeService.get()
|
||||
.getThemes()
|
||||
.map(({ id, label }) => (
|
||||
<option key={id} value={label}>
|
||||
{label}
|
||||
</option>
|
||||
))}
|
||||
{this.props.themeService.getThemes().map(({ id, label }) => (
|
||||
<option key={id} value={label}>
|
||||
{label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex-line">
|
||||
@@ -612,11 +610,11 @@ export class SettingsComponent extends React.Component<
|
||||
event: React.ChangeEvent<HTMLSelectElement>
|
||||
): void => {
|
||||
const { selectedIndex } = event.target.options;
|
||||
const theme = ThemeService.get().getThemes()[selectedIndex];
|
||||
const theme = this.props.themeService.getThemes()[selectedIndex];
|
||||
if (theme) {
|
||||
this.setState({ themeId: theme.id });
|
||||
if (ThemeService.get().getCurrentTheme().id !== theme.id) {
|
||||
ThemeService.get().setCurrentTheme(theme.id);
|
||||
if (this.props.themeService.getCurrentTheme().id !== theme.id) {
|
||||
this.props.themeService.setCurrentTheme(theme.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -755,6 +753,7 @@ export namespace SettingsComponent {
|
||||
readonly fileDialogService: FileDialogService;
|
||||
readonly windowService: WindowService;
|
||||
readonly localizationProvider: AsyncLocalizationProvider;
|
||||
readonly themeService: ThemeService;
|
||||
}
|
||||
export type State = Settings & {
|
||||
rawAdditionalUrlsValue: string;
|
||||
|
@@ -35,6 +35,9 @@ export class SettingsWidget extends ReactWidget {
|
||||
@inject(AsyncLocalizationProvider)
|
||||
protected readonly localizationProvider: AsyncLocalizationProvider;
|
||||
|
||||
@inject(ThemeService)
|
||||
private readonly themeService: ThemeService;
|
||||
|
||||
protected render(): React.ReactNode {
|
||||
return (
|
||||
<SettingsComponent
|
||||
@@ -43,6 +46,7 @@ export class SettingsWidget extends ReactWidget {
|
||||
fileDialogService={this.fileDialogService}
|
||||
windowService={this.windowService}
|
||||
localizationProvider={this.localizationProvider}
|
||||
themeService={this.themeService}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -59,6 +63,9 @@ export class SettingsDialog extends AbstractDialog<Promise<Settings>> {
|
||||
@inject(SettingsWidget)
|
||||
protected readonly widget: SettingsWidget;
|
||||
|
||||
@inject(ThemeService)
|
||||
private readonly themeService: ThemeService;
|
||||
|
||||
constructor(
|
||||
@inject(SettingsDialogProps)
|
||||
protected override readonly props: SettingsDialogProps
|
||||
@@ -121,11 +128,11 @@ export class SettingsDialog extends AbstractDialog<Promise<Settings>> {
|
||||
}
|
||||
|
||||
override async open(): Promise<Promise<Settings> | undefined> {
|
||||
const themeIdBeforeOpen = ThemeService.get().getCurrentTheme().id;
|
||||
const themeIdBeforeOpen = this.themeService.getCurrentTheme().id;
|
||||
const result = await super.open();
|
||||
if (!result) {
|
||||
if (ThemeService.get().getCurrentTheme().id !== themeIdBeforeOpen) {
|
||||
ThemeService.get().setCurrentTheme(themeIdBeforeOpen);
|
||||
if (this.themeService.getCurrentTheme().id !== themeIdBeforeOpen) {
|
||||
this.themeService.setCurrentTheme(themeIdBeforeOpen);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@@ -5,7 +5,7 @@ import {
|
||||
} from '@theia/core/shared/inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { Deferred, timeout } from '@theia/core/lib/common/promise-util';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { deepClone } from '@theia/core/lib/common/objects';
|
||||
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
||||
import { ThemeService } from '@theia/core/lib/browser/theming';
|
||||
@@ -25,17 +25,20 @@ import {
|
||||
LanguageInfo,
|
||||
} from '@theia/core/lib/common/i18n/localization';
|
||||
import { ElectronCommands } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution';
|
||||
import { DefaultTheme } from '@theia/application-package/lib/application-props';
|
||||
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
||||
|
||||
export const WINDOW_SETTING = 'window';
|
||||
export const EDITOR_SETTING = 'editor';
|
||||
export const FONT_SIZE_SETTING = `${EDITOR_SETTING}.fontSize`;
|
||||
export const AUTO_SAVE_SETTING = `files.autoSave`;
|
||||
export const QUICK_SUGGESTIONS_SETTING = `${EDITOR_SETTING}.quickSuggestions`;
|
||||
export const ARDUINO_SETTING = 'arduino';
|
||||
export const WINDOW_SETTING = `${ARDUINO_SETTING}.window`;
|
||||
export const ARDUINO_WINDOW_SETTING = `${ARDUINO_SETTING}.window`;
|
||||
export const COMPILE_SETTING = `${ARDUINO_SETTING}.compile`;
|
||||
export const UPLOAD_SETTING = `${ARDUINO_SETTING}.upload`;
|
||||
export const SKETCHBOOK_SETTING = `${ARDUINO_SETTING}.sketchbook`;
|
||||
export const AUTO_SCALE_SETTING = `${WINDOW_SETTING}.autoScale`;
|
||||
export const AUTO_SCALE_SETTING = `${ARDUINO_WINDOW_SETTING}.autoScale`;
|
||||
export const ZOOM_LEVEL_SETTING = `${WINDOW_SETTING}.zoomLevel`;
|
||||
export const COMPILE_VERBOSE_SETTING = `${COMPILE_SETTING}.verbose`;
|
||||
export const COMPILE_WARNINGS_SETTING = `${COMPILE_SETTING}.warnings`;
|
||||
@@ -53,7 +56,7 @@ export interface Settings {
|
||||
currentLanguage: string;
|
||||
|
||||
autoScaleInterface: boolean; // `arduino.window.autoScale`
|
||||
interfaceScale: number; // `arduino.window.zoomLevel` https://github.com/eclipse-theia/theia/issues/8751
|
||||
interfaceScale: number; // `window.zoomLevel`
|
||||
verboseOnCompile: boolean; // `arduino.compile.verbose`
|
||||
compilerWarnings: CompilerWarnings; // `arduino.compile.warnings`
|
||||
verboseOnUpload: boolean; // `arduino.upload.verbose`
|
||||
@@ -101,6 +104,9 @@ export class SettingsService {
|
||||
@inject(CommandService)
|
||||
protected commandService: CommandService;
|
||||
|
||||
@inject(ThemeService)
|
||||
private readonly themeService: ThemeService;
|
||||
|
||||
protected readonly onDidChangeEmitter = new Emitter<Readonly<Settings>>();
|
||||
readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
protected readonly onDidResetEmitter = new Emitter<Readonly<Settings>>();
|
||||
@@ -141,10 +147,9 @@ export class SettingsService {
|
||||
this.preferenceService.get<number>(FONT_SIZE_SETTING, 12),
|
||||
this.preferenceService.get<string>(
|
||||
'workbench.colorTheme',
|
||||
window.matchMedia &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? 'arduino-theme-dark'
|
||||
: 'arduino-theme'
|
||||
DefaultTheme.defaultForOSTheme(
|
||||
FrontendApplicationConfigProvider.get().defaultTheme
|
||||
)
|
||||
),
|
||||
this.preferenceService.get<Settings.AutoSave>(
|
||||
AUTO_SAVE_SETTING,
|
||||
@@ -231,11 +236,7 @@ export class SettingsService {
|
||||
'Invalid editor font size. It must be a positive integer.'
|
||||
);
|
||||
}
|
||||
if (
|
||||
!ThemeService.get()
|
||||
.getThemes()
|
||||
.find(({ id }) => id === themeId)
|
||||
) {
|
||||
if (!this.themeService.getThemes().find(({ id }) => id === themeId)) {
|
||||
return nls.localize(
|
||||
'arduino/preferences/invalid.theme',
|
||||
'Invalid theme.'
|
||||
@@ -252,7 +253,6 @@ export class SettingsService {
|
||||
|
||||
private async savePreference(name: string, value: unknown): Promise<void> {
|
||||
await this.preferenceService.set(name, value, PreferenceScope.User);
|
||||
await timeout(5);
|
||||
}
|
||||
|
||||
async save(): Promise<string | true> {
|
||||
@@ -283,19 +283,20 @@ export class SettingsService {
|
||||
(config as any).network = network;
|
||||
(config as any).locale = currentLanguage;
|
||||
|
||||
await this.savePreference('editor.fontSize', editorFontSize);
|
||||
await this.savePreference('workbench.colorTheme', themeId);
|
||||
await this.savePreference(AUTO_SAVE_SETTING, autoSave);
|
||||
await this.savePreference('editor.quickSuggestions', quickSuggestions);
|
||||
await this.savePreference(AUTO_SCALE_SETTING, autoScaleInterface);
|
||||
await this.savePreference(ZOOM_LEVEL_SETTING, interfaceScale);
|
||||
await this.savePreference(ZOOM_LEVEL_SETTING, interfaceScale);
|
||||
await this.savePreference(COMPILE_VERBOSE_SETTING, verboseOnCompile);
|
||||
await this.savePreference(COMPILE_WARNINGS_SETTING, compilerWarnings);
|
||||
await this.savePreference(UPLOAD_VERBOSE_SETTING, verboseOnUpload);
|
||||
await this.savePreference(UPLOAD_VERIFY_SETTING, verifyAfterUpload);
|
||||
await this.savePreference(SHOW_ALL_FILES_SETTING, sketchbookShowAllFiles);
|
||||
await this.configService.setConfiguration(config);
|
||||
await Promise.all([
|
||||
this.savePreference('editor.fontSize', editorFontSize),
|
||||
this.savePreference('workbench.colorTheme', themeId),
|
||||
this.savePreference(AUTO_SAVE_SETTING, autoSave),
|
||||
this.savePreference('editor.quickSuggestions', quickSuggestions),
|
||||
this.savePreference(AUTO_SCALE_SETTING, autoScaleInterface),
|
||||
this.savePreference(ZOOM_LEVEL_SETTING, interfaceScale),
|
||||
this.savePreference(COMPILE_VERBOSE_SETTING, verboseOnCompile),
|
||||
this.savePreference(COMPILE_WARNINGS_SETTING, compilerWarnings),
|
||||
this.savePreference(UPLOAD_VERBOSE_SETTING, verboseOnUpload),
|
||||
this.savePreference(UPLOAD_VERIFY_SETTING, verifyAfterUpload),
|
||||
this.savePreference(SHOW_ALL_FILES_SETTING, sketchbookShowAllFiles),
|
||||
this.configService.setConfiguration(config),
|
||||
]);
|
||||
this.onDidChangeEmitter.fire(this._settings);
|
||||
|
||||
// after saving all the settings, if we need to change the language we need to perform a reload
|
||||
|
@@ -1,63 +1,18 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
AbstractDialog,
|
||||
DialogProps,
|
||||
ReactWidget,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
import { DialogProps } from '@theia/core/lib/browser/dialogs';
|
||||
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||
import { UploadSketch } from '../../contributions/upload-sketch';
|
||||
import { UserFieldsComponent } from './user-fields-component';
|
||||
import { BoardUserField } from '../../../common/protocol';
|
||||
|
||||
@injectable()
|
||||
export class UserFieldsDialogWidget extends ReactWidget {
|
||||
private _currentUserFields: BoardUserField[] = [];
|
||||
|
||||
constructor(private cancel: () => void, private accept: () => Promise<void>) {
|
||||
super();
|
||||
}
|
||||
|
||||
set currentUserFields(userFields: BoardUserField[]) {
|
||||
this.setUserFields(userFields);
|
||||
}
|
||||
|
||||
get currentUserFields(): BoardUserField[] {
|
||||
return this._currentUserFields;
|
||||
}
|
||||
|
||||
resetUserFieldsValue(): void {
|
||||
this._currentUserFields = this._currentUserFields.map((field) => {
|
||||
field.value = '';
|
||||
return field;
|
||||
});
|
||||
}
|
||||
|
||||
private setUserFields(userFields: BoardUserField[]): void {
|
||||
this._currentUserFields = userFields;
|
||||
}
|
||||
|
||||
protected render(): React.ReactNode {
|
||||
return (
|
||||
<form>
|
||||
<UserFieldsComponent
|
||||
initialBoardUserFields={this._currentUserFields}
|
||||
updateUserFields={this.setUserFields.bind(this)}
|
||||
cancel={this.cancel}
|
||||
accept={this.accept}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
import { ReactDialog } from '../../theia/dialogs/dialogs';
|
||||
|
||||
@injectable()
|
||||
export class UserFieldsDialogProps extends DialogProps {}
|
||||
|
||||
@injectable()
|
||||
export class UserFieldsDialog extends AbstractDialog<BoardUserField[]> {
|
||||
protected readonly widget: UserFieldsDialogWidget;
|
||||
export class UserFieldsDialog extends ReactDialog<BoardUserField[]> {
|
||||
private _currentUserFields: BoardUserField[] = [];
|
||||
|
||||
constructor(
|
||||
@inject(UserFieldsDialogProps)
|
||||
@@ -69,39 +24,36 @@ export class UserFieldsDialog extends AbstractDialog<BoardUserField[]> {
|
||||
this.titleNode.classList.add('user-fields-dialog-title');
|
||||
this.contentNode.classList.add('user-fields-dialog-content');
|
||||
this.acceptButton = undefined;
|
||||
this.widget = new UserFieldsDialogWidget(
|
||||
this.close.bind(this),
|
||||
this.accept.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
set value(userFields: BoardUserField[]) {
|
||||
this.widget.currentUserFields = userFields;
|
||||
}
|
||||
|
||||
get value(): BoardUserField[] {
|
||||
return this.widget.currentUserFields;
|
||||
return this._currentUserFields;
|
||||
}
|
||||
|
||||
set value(userFields: BoardUserField[]) {
|
||||
this._currentUserFields = userFields;
|
||||
}
|
||||
|
||||
protected override render(): React.ReactNode {
|
||||
return (
|
||||
<div>
|
||||
<form>
|
||||
<UserFieldsComponent
|
||||
initialBoardUserFields={this.value}
|
||||
updateUserFields={this.doUpdateUserFields}
|
||||
cancel={this.doCancel}
|
||||
accept={this.doAccept}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
protected override onAfterAttach(msg: Message): void {
|
||||
if (this.widget.isAttached) {
|
||||
Widget.detach(this.widget);
|
||||
}
|
||||
Widget.attach(this.widget, this.contentNode);
|
||||
super.onAfterAttach(msg);
|
||||
this.update();
|
||||
}
|
||||
|
||||
protected override onUpdateRequest(msg: Message): void {
|
||||
super.onUpdateRequest(msg);
|
||||
this.widget.update();
|
||||
}
|
||||
|
||||
protected override onActivateRequest(msg: Message): void {
|
||||
super.onActivateRequest(msg);
|
||||
this.widget.activate();
|
||||
}
|
||||
|
||||
protected override async accept(): Promise<void> {
|
||||
// If the user presses enter and at least
|
||||
// a field is empty don't accept the input
|
||||
@@ -114,8 +66,21 @@ export class UserFieldsDialog extends AbstractDialog<BoardUserField[]> {
|
||||
}
|
||||
|
||||
override close(): void {
|
||||
this.widget.resetUserFieldsValue();
|
||||
this.widget.close();
|
||||
this.resetUserFieldsValue();
|
||||
super.close();
|
||||
}
|
||||
|
||||
private resetUserFieldsValue(): void {
|
||||
this.value = this.value.map((field) => {
|
||||
field.value = '';
|
||||
return field;
|
||||
});
|
||||
}
|
||||
|
||||
private readonly doCancel: () => void = () => this.close();
|
||||
private readonly doAccept: () => Promise<void> = () => this.accept();
|
||||
private readonly doUpdateUserFields: (userFields: BoardUserField[]) => void =
|
||||
(userFields: BoardUserField[]) => {
|
||||
this.value = userFields;
|
||||
};
|
||||
}
|
||||
|
6
arduino-ide-extension/src/browser/icons/loading-dark.svg
Normal file
6
arduino-ide-extension/src/browser/icons/loading-dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<!--Copyright (c) Microsoft Corporation. All rights reserved.-->
|
||||
<!--Copyright (C) 2020 TypeFox and others.-->
|
||||
<!--Copied from https://raw.githubusercontent.com/microsoft/vscode-icons/9c90ce81b1f3c309000b80da0763aa09975a85f0/icons/dark/loading.svg -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 0.75C8.17188 0.75 8.33333 0.783854 8.48438 0.851562C8.63542 0.914062 8.76823 1.0026 8.88281 1.11719C8.9974 1.23177 9.08594 1.36458 9.14844 1.51562C9.21615 1.66667 9.25 1.82812 9.25 2C9.25 2.17188 9.21615 2.33333 9.14844 2.48438C9.08594 2.63542 8.9974 2.76823 8.88281 2.88281C8.76823 2.9974 8.63542 3.08854 8.48438 3.15625C8.33333 3.21875 8.17188 3.25 8 3.25C7.82812 3.25 7.66667 3.21875 7.51562 3.15625C7.36458 3.08854 7.23177 2.9974 7.11719 2.88281C7.0026 2.76823 6.91146 2.63542 6.84375 2.48438C6.78125 2.33333 6.75 2.17188 6.75 2C6.75 1.82812 6.78125 1.66667 6.84375 1.51562C6.91146 1.36458 7.0026 1.23177 7.11719 1.11719C7.23177 1.0026 7.36458 0.914062 7.51562 0.851562C7.66667 0.783854 7.82812 0.75 8 0.75ZM2.63281 3.75781C2.63281 3.60156 2.66146 3.45573 2.71875 3.32031C2.77604 3.1849 2.85417 3.06771 2.95312 2.96875C3.05729 2.86458 3.17708 2.78385 3.3125 2.72656C3.45312 2.66406 3.60156 2.63281 3.75781 2.63281C3.91406 2.63281 4.0599 2.66406 4.19531 2.72656C4.33073 2.78385 4.44792 2.86458 4.54688 2.96875C4.65104 3.06771 4.73177 3.1849 4.78906 3.32031C4.85156 3.45573 4.88281 3.60156 4.88281 3.75781C4.88281 3.91406 4.85156 4.0625 4.78906 4.20312C4.73177 4.33854 4.65104 4.45833 4.54688 4.5625C4.44792 4.66146 4.33073 4.73958 4.19531 4.79688C4.0599 4.85417 3.91406 4.88281 3.75781 4.88281C3.60156 4.88281 3.45312 4.85417 3.3125 4.79688C3.17708 4.73958 3.05729 4.66146 2.95312 4.5625C2.85417 4.45833 2.77604 4.33854 2.71875 4.20312C2.66146 4.0625 2.63281 3.91406 2.63281 3.75781ZM2 7C2.14062 7 2.27083 7.02604 2.39062 7.07812C2.51042 7.13021 2.61458 7.20312 2.70312 7.29688C2.79688 7.38542 2.86979 7.48958 2.92188 7.60938C2.97396 7.72917 3 7.85938 3 8C3 8.14062 2.97396 8.27083 2.92188 8.39062C2.86979 8.51042 2.79688 8.61719 2.70312 8.71094C2.61458 8.79948 2.51042 8.86979 2.39062 8.92188C2.27083 8.97396 2.14062 9 2 9C1.85938 9 1.72917 8.97396 1.60938 8.92188C1.48958 8.86979 1.38281 8.79948 1.28906 8.71094C1.20052 8.61719 1.13021 8.51042 1.07812 8.39062C1.02604 8.27083 1 8.14062 1 8C1 7.85938 1.02604 7.72917 1.07812 7.60938C1.13021 7.48958 1.20052 7.38542 1.28906 7.29688C1.38281 7.20312 1.48958 7.13021 1.60938 7.07812C1.72917 7.02604 1.85938 7 2 7ZM2.88281 12.2422C2.88281 12.1224 2.90625 12.0104 2.95312 11.9062C3 11.7969 3.0625 11.7031 3.14062 11.625C3.21875 11.5469 3.3099 11.4844 3.41406 11.4375C3.52344 11.3906 3.63802 11.3672 3.75781 11.3672C3.8776 11.3672 3.98958 11.3906 4.09375 11.4375C4.20312 11.4844 4.29688 11.5469 4.375 11.625C4.45312 11.7031 4.51562 11.7969 4.5625 11.9062C4.60938 12.0104 4.63281 12.1224 4.63281 12.2422C4.63281 12.362 4.60938 12.4766 4.5625 12.5859C4.51562 12.6901 4.45312 12.7812 4.375 12.8594C4.29688 12.9375 4.20312 13 4.09375 13.0469C3.98958 13.0938 3.8776 13.1172 3.75781 13.1172C3.63802 13.1172 3.52344 13.0938 3.41406 13.0469C3.3099 13 3.21875 12.9375 3.14062 12.8594C3.0625 12.7812 3 12.6901 2.95312 12.5859C2.90625 12.4766 2.88281 12.362 2.88281 12.2422ZM8 13.25C8.20833 13.25 8.38542 13.3229 8.53125 13.4688C8.67708 13.6146 8.75 13.7917 8.75 14C8.75 14.2083 8.67708 14.3854 8.53125 14.5312C8.38542 14.6771 8.20833 14.75 8 14.75C7.79167 14.75 7.61458 14.6771 7.46875 14.5312C7.32292 14.3854 7.25 14.2083 7.25 14C7.25 13.7917 7.32292 13.6146 7.46875 13.4688C7.61458 13.3229 7.79167 13.25 8 13.25ZM11.6172 12.2422C11.6172 12.0651 11.6771 11.9167 11.7969 11.7969C11.9167 11.6771 12.0651 11.6172 12.2422 11.6172C12.4193 11.6172 12.5677 11.6771 12.6875 11.7969C12.8073 11.9167 12.8672 12.0651 12.8672 12.2422C12.8672 12.4193 12.8073 12.5677 12.6875 12.6875C12.5677 12.8073 12.4193 12.8672 12.2422 12.8672C12.0651 12.8672 11.9167 12.8073 11.7969 12.6875C11.6771 12.5677 11.6172 12.4193 11.6172 12.2422ZM14 7.5C14.1354 7.5 14.2526 7.54948 14.3516 7.64844C14.4505 7.7474 14.5 7.86458 14.5 8C14.5 8.13542 14.4505 8.2526 14.3516 8.35156C14.2526 8.45052 14.1354 8.5 14 8.5C13.8646 8.5 13.7474 8.45052 13.6484 8.35156C13.5495 8.2526 13.5 8.13542 13.5 8C13.5 7.86458 13.5495 7.7474 13.6484 7.64844C13.7474 7.54948 13.8646 7.5 14 7.5ZM12.2422 2.38281C12.4297 2.38281 12.6068 2.41927 12.7734 2.49219C12.9401 2.5651 13.0859 2.66406 13.2109 2.78906C13.3359 2.91406 13.4349 3.0599 13.5078 3.22656C13.5807 3.39323 13.6172 3.57031 13.6172 3.75781C13.6172 3.94531 13.5807 4.1224 13.5078 4.28906C13.4349 4.45573 13.3359 4.60156 13.2109 4.72656C13.0859 4.85156 12.9401 4.95052 12.7734 5.02344C12.6068 5.09635 12.4297 5.13281 12.2422 5.13281C12.0547 5.13281 11.8776 5.09635 11.7109 5.02344C11.5443 4.95052 11.3984 4.85156 11.2734 4.72656C11.1484 4.60156 11.0495 4.45573 10.9766 4.28906C10.9036 4.1224 10.8672 3.94531 10.8672 3.75781C10.8672 3.57031 10.9036 3.39323 10.9766 3.22656C11.0495 3.0599 11.1484 2.91406 11.2734 2.78906C11.3984 2.66406 11.5443 2.5651 11.7109 2.49219C11.8776 2.41927 12.0547 2.38281 12.2422 2.38281Z" fill="#C5C5C5" />
|
||||
</svg>
|
After Width: | Height: | Size: 5.0 KiB |
@@ -0,0 +1,6 @@
|
||||
<!--Copyright (c) Microsoft Corporation. All rights reserved.-->
|
||||
<!--Copyright (C) 2020 TypeFox and others.-->
|
||||
<!--Copied from https://raw.githubusercontent.com/microsoft/vscode-icons/9c90ce81b1f3c309000b80da0763aa09975a85f0/icons/light/loading.svg -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 0.75C8.17188 0.75 8.33333 0.783854 8.48438 0.851562C8.63542 0.914062 8.76823 1.0026 8.88281 1.11719C8.9974 1.23177 9.08594 1.36458 9.14844 1.51562C9.21615 1.66667 9.25 1.82812 9.25 2C9.25 2.17188 9.21615 2.33333 9.14844 2.48438C9.08594 2.63542 8.9974 2.76823 8.88281 2.88281C8.76823 2.9974 8.63542 3.08854 8.48438 3.15625C8.33333 3.21875 8.17188 3.25 8 3.25C7.82812 3.25 7.66667 3.21875 7.51562 3.15625C7.36458 3.08854 7.23177 2.9974 7.11719 2.88281C7.0026 2.76823 6.91146 2.63542 6.84375 2.48438C6.78125 2.33333 6.75 2.17188 6.75 2C6.75 1.82812 6.78125 1.66667 6.84375 1.51562C6.91146 1.36458 7.0026 1.23177 7.11719 1.11719C7.23177 1.0026 7.36458 0.914062 7.51562 0.851562C7.66667 0.783854 7.82812 0.75 8 0.75ZM2.63281 3.75781C2.63281 3.60156 2.66146 3.45573 2.71875 3.32031C2.77604 3.1849 2.85417 3.06771 2.95312 2.96875C3.05729 2.86458 3.17708 2.78385 3.3125 2.72656C3.45312 2.66406 3.60156 2.63281 3.75781 2.63281C3.91406 2.63281 4.0599 2.66406 4.19531 2.72656C4.33073 2.78385 4.44792 2.86458 4.54688 2.96875C4.65104 3.06771 4.73177 3.1849 4.78906 3.32031C4.85156 3.45573 4.88281 3.60156 4.88281 3.75781C4.88281 3.91406 4.85156 4.0625 4.78906 4.20312C4.73177 4.33854 4.65104 4.45833 4.54688 4.5625C4.44792 4.66146 4.33073 4.73958 4.19531 4.79688C4.0599 4.85417 3.91406 4.88281 3.75781 4.88281C3.60156 4.88281 3.45312 4.85417 3.3125 4.79688C3.17708 4.73958 3.05729 4.66146 2.95312 4.5625C2.85417 4.45833 2.77604 4.33854 2.71875 4.20312C2.66146 4.0625 2.63281 3.91406 2.63281 3.75781ZM2 7C2.14062 7 2.27083 7.02604 2.39062 7.07812C2.51042 7.13021 2.61458 7.20312 2.70312 7.29688C2.79688 7.38542 2.86979 7.48958 2.92188 7.60938C2.97396 7.72917 3 7.85938 3 8C3 8.14062 2.97396 8.27083 2.92188 8.39062C2.86979 8.51042 2.79688 8.61719 2.70312 8.71094C2.61458 8.79948 2.51042 8.86979 2.39062 8.92188C2.27083 8.97396 2.14062 9 2 9C1.85938 9 1.72917 8.97396 1.60938 8.92188C1.48958 8.86979 1.38281 8.79948 1.28906 8.71094C1.20052 8.61719 1.13021 8.51042 1.07812 8.39062C1.02604 8.27083 1 8.14062 1 8C1 7.85938 1.02604 7.72917 1.07812 7.60938C1.13021 7.48958 1.20052 7.38542 1.28906 7.29688C1.38281 7.20312 1.48958 7.13021 1.60938 7.07812C1.72917 7.02604 1.85938 7 2 7ZM2.88281 12.2422C2.88281 12.1224 2.90625 12.0104 2.95312 11.9062C3 11.7969 3.0625 11.7031 3.14062 11.625C3.21875 11.5469 3.3099 11.4844 3.41406 11.4375C3.52344 11.3906 3.63802 11.3672 3.75781 11.3672C3.8776 11.3672 3.98958 11.3906 4.09375 11.4375C4.20312 11.4844 4.29688 11.5469 4.375 11.625C4.45312 11.7031 4.51562 11.7969 4.5625 11.9062C4.60938 12.0104 4.63281 12.1224 4.63281 12.2422C4.63281 12.362 4.60938 12.4766 4.5625 12.5859C4.51562 12.6901 4.45312 12.7812 4.375 12.8594C4.29688 12.9375 4.20312 13 4.09375 13.0469C3.98958 13.0938 3.8776 13.1172 3.75781 13.1172C3.63802 13.1172 3.52344 13.0938 3.41406 13.0469C3.3099 13 3.21875 12.9375 3.14062 12.8594C3.0625 12.7812 3 12.6901 2.95312 12.5859C2.90625 12.4766 2.88281 12.362 2.88281 12.2422ZM8 13.25C8.20833 13.25 8.38542 13.3229 8.53125 13.4688C8.67708 13.6146 8.75 13.7917 8.75 14C8.75 14.2083 8.67708 14.3854 8.53125 14.5312C8.38542 14.6771 8.20833 14.75 8 14.75C7.79167 14.75 7.61458 14.6771 7.46875 14.5312C7.32292 14.3854 7.25 14.2083 7.25 14C7.25 13.7917 7.32292 13.6146 7.46875 13.4688C7.61458 13.3229 7.79167 13.25 8 13.25ZM11.6172 12.2422C11.6172 12.0651 11.6771 11.9167 11.7969 11.7969C11.9167 11.6771 12.0651 11.6172 12.2422 11.6172C12.4193 11.6172 12.5677 11.6771 12.6875 11.7969C12.8073 11.9167 12.8672 12.0651 12.8672 12.2422C12.8672 12.4193 12.8073 12.5677 12.6875 12.6875C12.5677 12.8073 12.4193 12.8672 12.2422 12.8672C12.0651 12.8672 11.9167 12.8073 11.7969 12.6875C11.6771 12.5677 11.6172 12.4193 11.6172 12.2422ZM14 7.5C14.1354 7.5 14.2526 7.54948 14.3516 7.64844C14.4505 7.7474 14.5 7.86458 14.5 8C14.5 8.13542 14.4505 8.2526 14.3516 8.35156C14.2526 8.45052 14.1354 8.5 14 8.5C13.8646 8.5 13.7474 8.45052 13.6484 8.35156C13.5495 8.2526 13.5 8.13542 13.5 8C13.5 7.86458 13.5495 7.7474 13.6484 7.64844C13.7474 7.54948 13.8646 7.5 14 7.5ZM12.2422 2.38281C12.4297 2.38281 12.6068 2.41927 12.7734 2.49219C12.9401 2.5651 13.0859 2.66406 13.2109 2.78906C13.3359 2.91406 13.4349 3.0599 13.5078 3.22656C13.5807 3.39323 13.6172 3.57031 13.6172 3.75781C13.6172 3.94531 13.5807 4.1224 13.5078 4.28906C13.4349 4.45573 13.3359 4.60156 13.2109 4.72656C13.0859 4.85156 12.9401 4.95052 12.7734 5.02344C12.6068 5.09635 12.4297 5.13281 12.2422 5.13281C12.0547 5.13281 11.8776 5.09635 11.7109 5.02344C11.5443 4.95052 11.3984 4.85156 11.2734 4.72656C11.1484 4.60156 11.0495 4.45573 10.9766 4.28906C10.9036 4.1224 10.8672 3.94531 10.8672 3.75781C10.8672 3.57031 10.9036 3.39323 10.9766 3.22656C11.0495 3.0599 11.1484 2.91406 11.2734 2.78906C11.3984 2.66406 11.5443 2.5651 11.7109 2.49219C11.8776 2.41927 12.0547 2.38281 12.2422 2.38281Z" fill="#424242" />
|
||||
</svg>
|
After Width: | Height: | Size: 5.0 KiB |
@@ -1,5 +1,5 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { URI as Uri } from 'vscode-uri';
|
||||
import { URI as Uri } from '@theia/core/shared/vscode-uri';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import {
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { injectable, inject } from '@theia/core/shared/inversify';
|
||||
import { OptionsType } from 'react-select/src/types';
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { Disposable } from '@theia/core/lib/common/disposable';
|
||||
import {
|
||||
@@ -128,9 +127,7 @@ export class MonitorWidget extends ReactWidget {
|
||||
);
|
||||
};
|
||||
|
||||
protected get lineEndings(): OptionsType<
|
||||
SerialMonitorOutput.SelectOption<MonitorModel.EOL>
|
||||
> {
|
||||
protected get lineEndings(): SerialMonitorOutput.SelectOption<MonitorModel.EOL>[] {
|
||||
return [
|
||||
{
|
||||
label: nls.localize('arduino/serial/noLineEndings', 'No Line Ending'),
|
||||
|
@@ -20,6 +20,16 @@
|
||||
@import './progress-bar.css';
|
||||
@import './settings-step-input.css';
|
||||
|
||||
/* Revive of the `--theia-icon-loading`. The variable has been removed from Theia while IDE2 still uses is. */
|
||||
/* The SVG icons are still part of Theia (1.31.1) */
|
||||
/* https://github.com/arduino/arduino-ide/pull/1662#issuecomment-1324997134 */
|
||||
body {
|
||||
--theia-icon-loading: url(../icons/loading-light.svg);
|
||||
}
|
||||
body.theia-dark {
|
||||
--theia-icon-loading: url(../icons/loading-dark.svg);
|
||||
}
|
||||
|
||||
.theia-input.warning:focus {
|
||||
outline-width: 1px;
|
||||
outline-style: solid;
|
||||
@@ -166,3 +176,13 @@ button.theia-button.message-box-dialog-button {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.debug-toolbar .debug-action>div {
|
||||
font-family: var(--theia-ui-font-family);
|
||||
font-size: var(--theia-ui-font-size0);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
min-height: inherit;
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@ import {
|
||||
} from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application';
|
||||
import { KeybindingRegistry } from '@theia/core/lib/browser';
|
||||
import { isOSX } from '@theia/core';
|
||||
|
||||
@injectable()
|
||||
export class CommonFrontendContribution extends TheiaCommonFrontendContribution {
|
||||
@@ -22,7 +24,7 @@ export class CommonFrontendContribution extends TheiaCommonFrontendContribution
|
||||
CommonCommands.TOGGLE_MAXIMIZED,
|
||||
CommonCommands.PIN_TAB,
|
||||
CommonCommands.UNPIN_TAB,
|
||||
CommonCommands.NEW_FILE,
|
||||
CommonCommands.NEW_UNTITLED_FILE,
|
||||
]) {
|
||||
commandRegistry.unregisterCommand(command);
|
||||
}
|
||||
@@ -50,6 +52,36 @@ export class CommonFrontendContribution extends TheiaCommonFrontendContribution
|
||||
}
|
||||
}
|
||||
|
||||
override registerKeybindings(registry: KeybindingRegistry): void {
|
||||
super.registerKeybindings(registry);
|
||||
// Workaround for https://github.com/eclipse-theia/theia/issues/11875
|
||||
if (isOSX) {
|
||||
registry.unregisterKeybinding('ctrlcmd+tab');
|
||||
registry.unregisterKeybinding('ctrlcmd+alt+d');
|
||||
registry.unregisterKeybinding('ctrlcmd+shift+tab');
|
||||
registry.unregisterKeybinding('ctrlcmd+alt+a');
|
||||
|
||||
registry.registerKeybindings(
|
||||
{
|
||||
command: CommonCommands.NEXT_TAB.id,
|
||||
keybinding: 'ctrl+tab',
|
||||
},
|
||||
{
|
||||
command: CommonCommands.NEXT_TAB.id,
|
||||
keybinding: 'ctrl+alt+d',
|
||||
},
|
||||
{
|
||||
command: CommonCommands.PREVIOUS_TAB.id,
|
||||
keybinding: 'ctrl+shift+tab',
|
||||
},
|
||||
{
|
||||
command: CommonCommands.PREVIOUS_TAB.id,
|
||||
keybinding: 'ctrl+alt+a',
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
override onWillStop(): OnWillStopAction | undefined {
|
||||
// This is NOOP here. All window close and app quit requests are handled in the `Close` contribution.
|
||||
return undefined;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { injectable, inject } from '@theia/core/shared/inversify';
|
||||
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
||||
import { CommandService } from '@theia/core/lib/common/command';
|
||||
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
||||
import { FrontendApplication as TheiaFrontendApplication } from '@theia/core/lib/browser/frontend-application';
|
||||
@@ -8,17 +7,16 @@ import { OpenSketchFiles } from '../../contributions/open-sketch-files';
|
||||
|
||||
@injectable()
|
||||
export class FrontendApplication extends TheiaFrontendApplication {
|
||||
@inject(FileService)
|
||||
protected readonly fileService: FileService;
|
||||
|
||||
@inject(WorkspaceService)
|
||||
protected readonly workspaceService: WorkspaceService;
|
||||
private readonly workspaceService: WorkspaceService;
|
||||
|
||||
@inject(CommandService)
|
||||
protected readonly commandService: CommandService;
|
||||
private readonly commandService: CommandService;
|
||||
|
||||
@inject(SketchesService)
|
||||
protected readonly sketchesService: SketchesService;
|
||||
private readonly sketchesService: SketchesService;
|
||||
|
||||
private layoutWasRestored = false;
|
||||
|
||||
protected override async initializeLayout(): Promise<void> {
|
||||
await super.initializeLayout();
|
||||
@@ -26,10 +24,16 @@ export class FrontendApplication extends TheiaFrontendApplication {
|
||||
for (const root of roots) {
|
||||
await this.commandService.executeCommand(
|
||||
OpenSketchFiles.Commands.OPEN_SKETCH_FILES.id,
|
||||
root.resource
|
||||
root.resource,
|
||||
!this.layoutWasRestored
|
||||
);
|
||||
this.sketchesService.markAsRecentlyOpened(root.resource.toString()); // no await, will get the notification later and rebuild the menu
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override async restoreLayout(): Promise<boolean> {
|
||||
this.layoutWasRestored = await super.restoreLayout();
|
||||
return this.layoutWasRestored;
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +0,0 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { StatusBarImpl as TheiaStatusBarImpl } from '@theia/core/lib/browser';
|
||||
|
||||
@injectable()
|
||||
export class StatusBarImpl extends TheiaStatusBarImpl {
|
||||
override async removeElement(id: string): Promise<void> {
|
||||
await this.ready;
|
||||
if (this.entries.delete(id)) {
|
||||
// Unlike Theia, IDE2 updates the status bar only if the element to remove was among the entries. Otherwise, it's a NOOP.
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { LabelIcon } from '@theia/core/lib/browser/label-parser';
|
||||
import {
|
||||
TabBarToolbar as TheiaTabBarToolbar,
|
||||
TabBarToolbarItem,
|
||||
} from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
|
||||
@injectable()
|
||||
export class TabBarToolbar extends TheiaTabBarToolbar {
|
||||
/**
|
||||
* Copied over from Theia. Added an ID to the parent of the toolbar item (`--container`).
|
||||
* CSS3 does not support parent selectors but we want to style the parent of the toolbar item.
|
||||
*/
|
||||
protected override renderItem(item: TabBarToolbarItem): React.ReactNode {
|
||||
let innerText = '';
|
||||
const classNames = [];
|
||||
if (item.text) {
|
||||
for (const labelPart of this.labelParser.parse(item.text)) {
|
||||
if (typeof labelPart !== 'string' && LabelIcon.is(labelPart)) {
|
||||
const className = `fa fa-${labelPart.name}${
|
||||
labelPart.animation ? ' fa-' + labelPart.animation : ''
|
||||
}`;
|
||||
classNames.push(...className.split(' '));
|
||||
} else {
|
||||
innerText = labelPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
const command = this.commands.getCommand(item.command);
|
||||
const iconClass =
|
||||
(typeof item.icon === 'function' && item.icon()) ||
|
||||
item.icon ||
|
||||
(command && command.iconClass);
|
||||
if (iconClass) {
|
||||
classNames.push(iconClass);
|
||||
}
|
||||
const tooltip = item.tooltip || (command && command.label);
|
||||
return (
|
||||
<div
|
||||
id={`${item.id}--container`}
|
||||
key={item.id}
|
||||
className={`${TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM}${
|
||||
command && this.commandIsEnabled(command.id) ? ' enabled' : ''
|
||||
}`}
|
||||
onMouseDown={this.onMouseDownEvent}
|
||||
onMouseUp={this.onMouseUpEvent}
|
||||
onMouseOut={this.onMouseUpEvent}
|
||||
>
|
||||
<div
|
||||
id={item.id}
|
||||
className={classNames.join(' ')}
|
||||
onClick={this.executeCommand}
|
||||
title={tooltip}
|
||||
>
|
||||
{innerText}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
26
arduino-ide-extension/src/browser/theia/core/theming.ts
Normal file
26
arduino-ide-extension/src/browser/theia/core/theming.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { ThemeService as TheiaThemeService } from '@theia/core/lib/browser/theming';
|
||||
import type { Theme } from '@theia/core/lib/common/theme';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
|
||||
export namespace ArduinoThemes {
|
||||
export const Light: Theme = {
|
||||
id: 'arduino-theme',
|
||||
type: 'light',
|
||||
label: 'Light (Arduino)',
|
||||
editorTheme: 'arduino-theme',
|
||||
};
|
||||
export const Dark: Theme = {
|
||||
id: 'arduino-theme-dark',
|
||||
type: 'dark',
|
||||
label: 'Dark (Arduino)',
|
||||
editorTheme: 'arduino-theme-dark',
|
||||
};
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class ThemeService extends TheiaThemeService {
|
||||
protected override init(): void {
|
||||
this.register(ArduinoThemes.Light, ArduinoThemes.Dark);
|
||||
super.init();
|
||||
}
|
||||
}
|
@@ -1,4 +1,3 @@
|
||||
import type { MaybePromise } from '@theia/core';
|
||||
import type { Widget } from '@theia/core/lib/browser';
|
||||
import { WidgetManager as TheiaWidgetManager } from '@theia/core/lib/browser/widget-manager';
|
||||
import {
|
||||
@@ -8,7 +7,6 @@ import {
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { EditorWidget } from '@theia/editor/lib/browser';
|
||||
import { OutputWidget } from '@theia/output/lib/browser/output-widget';
|
||||
import deepEqual = require('deep-equal');
|
||||
import {
|
||||
CurrentSketch,
|
||||
SketchesServiceClientImpl,
|
||||
@@ -72,44 +70,4 @@ export class WidgetManager extends TheiaWidgetManager {
|
||||
title.className += title.className + ` ${uncloseableClass}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized to find any existing widget based on `options` deepEquals instead of string equals.
|
||||
* See https://github.com/eclipse-theia/theia/issues/11309.
|
||||
*/
|
||||
protected override doGetWidget<T extends Widget>(
|
||||
key: string
|
||||
): MaybePromise<T> | undefined {
|
||||
const pendingWidget = this.findExistingWidget<T>(key);
|
||||
if (pendingWidget) {
|
||||
return pendingWidget as MaybePromise<T>;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private findExistingWidget<T extends Widget>(
|
||||
key: string
|
||||
): MaybePromise<T> | undefined {
|
||||
const parsed = this.parseJson(key);
|
||||
for (const [candidateKey, widget] of [
|
||||
...this.widgetPromises.entries(),
|
||||
...this.pendingWidgetPromises.entries(),
|
||||
]) {
|
||||
const candidate = this.parseJson(candidateKey);
|
||||
if (deepEqual(candidate, parsed)) {
|
||||
return widget as MaybePromise<T>;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private parseJson(json: string): any {
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch (err) {
|
||||
console.log(`Failed to parse JSON: <${json}>.`, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,87 @@
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
||||
import { NavigatableWidget } from '@theia/core/lib/browser/navigatable-types';
|
||||
import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
|
||||
import { Widget } from '@theia/core/lib/browser/widgets/widget';
|
||||
import { WindowTitleUpdater as TheiaWindowTitleUpdater } from '@theia/core/lib/browser/window/window-title-updater';
|
||||
import { ApplicationServer } from '@theia/core/lib/common/application-protocol';
|
||||
import { isOSX } from '@theia/core/lib/common/os';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { EditorWidget } from '@theia/editor/lib/browser/editor-widget';
|
||||
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
||||
|
||||
@injectable()
|
||||
export class WindowTitleUpdater extends TheiaWindowTitleUpdater {
|
||||
@inject(ApplicationServer)
|
||||
private readonly applicationServer: ApplicationServer;
|
||||
@inject(ApplicationShell)
|
||||
private readonly applicationShell: ApplicationShell;
|
||||
@inject(WorkspaceService)
|
||||
private readonly workspaceService: WorkspaceService;
|
||||
|
||||
private _previousRepresentedFilename: string | undefined;
|
||||
|
||||
private readonly applicationName =
|
||||
FrontendApplicationConfigProvider.get().applicationName;
|
||||
private applicationVersion: string | undefined;
|
||||
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
setTimeout(
|
||||
() =>
|
||||
this.applicationServer.getApplicationInfo().then((info) => {
|
||||
this.applicationVersion = info?.version;
|
||||
if (this.applicationVersion) {
|
||||
this.handleWidgetChange(this.applicationShell.currentWidget);
|
||||
}
|
||||
}),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
protected override handleWidgetChange(widget?: Widget | undefined): void {
|
||||
if (isOSX) {
|
||||
this.maybeUpdateRepresentedFilename(widget);
|
||||
}
|
||||
// Unlike Theia, IDE2 does not want to show in the window title if the current widget is dirty or not.
|
||||
// Hence, IDE2 does not track widgets but updates the window title on current widget change.
|
||||
this.updateTitleWidget(widget);
|
||||
}
|
||||
|
||||
protected override updateTitleWidget(widget?: Widget | undefined): void {
|
||||
let activeEditorShort = '';
|
||||
const rootName = this.workspaceService.workspace?.name ?? '';
|
||||
let appName = `${this.applicationName}${
|
||||
this.applicationVersion ? ` ${this.applicationVersion}` : ''
|
||||
}`;
|
||||
if (rootName) {
|
||||
appName = ` | ${appName}`;
|
||||
}
|
||||
const uri = NavigatableWidget.getUri(widget);
|
||||
if (uri) {
|
||||
const base = uri.path.base;
|
||||
// Do not show the basename of the main sketch file. Only other sketch file names are visible in the title.
|
||||
if (`${rootName}.ino` !== base) {
|
||||
activeEditorShort = ` - ${base} `;
|
||||
}
|
||||
}
|
||||
this.windowTitleService.update({ rootName, appName, activeEditorShort });
|
||||
}
|
||||
|
||||
private maybeUpdateRepresentedFilename(widget?: Widget | undefined): void {
|
||||
if (widget instanceof EditorWidget) {
|
||||
const { uri } = widget.editor;
|
||||
const filename = uri.path.toString();
|
||||
// Do not necessarily require the current window if not needed. It's a synchronous, blocking call.
|
||||
if (this._previousRepresentedFilename !== filename) {
|
||||
const currentWindow = remote.getCurrentWindow();
|
||||
currentWindow.setRepresentedFilename(uri.path.toString());
|
||||
this._previousRepresentedFilename = filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { DebugAction as TheiaDebugAction } from '@theia/debug/lib/browser/view/debug-action';
|
||||
import {
|
||||
codiconArray,
|
||||
DISABLED_CLASS,
|
||||
} from '@theia/core/lib/browser/widgets/widget';
|
||||
|
||||
// customized debug action to show the contributed command's label when there is no icon
|
||||
export class DebugAction extends TheiaDebugAction {
|
||||
override render(): React.ReactNode {
|
||||
const { enabled, label, iconClass } = this.props;
|
||||
const classNames = ['debug-action', ...codiconArray(iconClass, true)];
|
||||
if (enabled === false) {
|
||||
classNames.push(DISABLED_CLASS);
|
||||
}
|
||||
return (
|
||||
<span
|
||||
tabIndex={0}
|
||||
className={classNames.join(' ')}
|
||||
title={label}
|
||||
onClick={this.props.run}
|
||||
ref={this.setRef}
|
||||
>
|
||||
{!iconClass ||
|
||||
(iconClass.match(/plugin-icon-\d+/) && <div>{label}</div>)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,5 +1,9 @@
|
||||
import debounce = require('p-debounce');
|
||||
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { Event, Emitter } from '@theia/core/lib/common/event';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
@@ -126,7 +130,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
const uri = tempFolderUri.resolve('launch.json');
|
||||
const { value } = await this.fileService.read(uri);
|
||||
const configurations = DebugConfigurationModel.parse(JSON.parse(value));
|
||||
return { uri, configurations };
|
||||
return { uri, configurations, compounds: [] };
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof FileOperationError &&
|
||||
|
@@ -29,6 +29,7 @@ export class DebugConfigurationModel extends TheiaDebugConfigurationModel {
|
||||
return {
|
||||
uri: this.configUri,
|
||||
configurations: this.config,
|
||||
compounds: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,49 @@
|
||||
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 { DebugConfigurationSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
|
||||
import {
|
||||
DebugAdapterPath,
|
||||
DebugChannel,
|
||||
ForwardingDebugChannel,
|
||||
} from '@theia/debug/lib/common/debug-service';
|
||||
import { DebugSession } from './debug-session';
|
||||
|
||||
@injectable()
|
||||
export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory {
|
||||
override get(
|
||||
sessionId: string,
|
||||
options: DebugConfigurationSessionOptions,
|
||||
parentSession?: DebugSession
|
||||
): DebugSession {
|
||||
const connection = new DebugSessionConnection(
|
||||
sessionId,
|
||||
() =>
|
||||
new Promise<DebugChannel>((resolve) =>
|
||||
this.connectionProvider.openChannel(
|
||||
`${DebugAdapterPath}/${sessionId}`,
|
||||
(wsChannel) => {
|
||||
resolve(new ForwardingDebugChannel(wsChannel));
|
||||
},
|
||||
{ reconnecting: false }
|
||||
)
|
||||
),
|
||||
this.getTraceOutputChannel()
|
||||
);
|
||||
// patched debug session
|
||||
return new DebugSession(
|
||||
sessionId,
|
||||
options,
|
||||
parentSession,
|
||||
connection,
|
||||
this.terminalService,
|
||||
this.editorManager,
|
||||
this.breakpoints,
|
||||
this.labelProvider,
|
||||
this.messages,
|
||||
this.fileService,
|
||||
this.debugContributionProvider,
|
||||
this.workspaceService
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,90 +1,120 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { DebugError } from '@theia/debug/lib/common/debug-service';
|
||||
import { DebugSession } from '@theia/debug/lib/browser/debug-session';
|
||||
import { DebugSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
|
||||
import type { ContextKey } from '@theia/core/lib/browser/context-key-service';
|
||||
import { injectable, postConstruct } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
DebugSession,
|
||||
DebugState,
|
||||
} from '@theia/debug/lib/browser/debug-session';
|
||||
import { DebugSessionManager as TheiaDebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import type { DebugConfigurationSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
|
||||
|
||||
function debugStateLabel(state: DebugState): string {
|
||||
switch (state) {
|
||||
case DebugState.Initializing:
|
||||
return 'initializing';
|
||||
case DebugState.Stopped:
|
||||
return 'stopped';
|
||||
case DebugState.Running:
|
||||
return 'running';
|
||||
default:
|
||||
return 'inactive';
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class DebugSessionManager extends TheiaDebugSessionManager {
|
||||
override async start(options: DebugSessionOptions): Promise<DebugSession | undefined> {
|
||||
return this.progressService.withProgress(
|
||||
nls.localize('theia/debug/start', 'Start...'),
|
||||
'debug',
|
||||
async () => {
|
||||
try {
|
||||
// Only save when dirty. To avoid saving temporary sketches.
|
||||
// This is a quick fix for not saving the editor when there are no dirty editors.
|
||||
// // https://github.com/bcmi-labs/arduino-editor/pull/172#issuecomment-741831888
|
||||
if (this.shell.canSaveAll()) {
|
||||
await this.shell.saveAll();
|
||||
}
|
||||
await this.fireWillStartDebugSession();
|
||||
const resolved = await this.resolveConfiguration(options);
|
||||
protected debugStateKey: ContextKey<string>;
|
||||
|
||||
//#region "cherry-picked" from here: https://github.com/eclipse-theia/theia/commit/e6b57ba4edabf797f3b4e67bc2968cdb8cc25b1e#diff-08e04edb57cd2af199382337aaf1dbdb31171b37ae4ab38a38d36cd77bc656c7R196-R207
|
||||
if (!resolved) {
|
||||
// As per vscode API: https://code.visualstudio.com/api/references/vscode-api#DebugConfigurationProvider
|
||||
// "Returning the value 'undefined' prevents the debug session from starting.
|
||||
// Returning the value 'null' prevents the debug session from starting and opens the
|
||||
// underlying debug configuration instead."
|
||||
@postConstruct()
|
||||
protected override init(): void {
|
||||
this.debugStateKey = this.contextKeyService.createKey<string>(
|
||||
'debugState',
|
||||
debugStateLabel(this.state)
|
||||
);
|
||||
super.init();
|
||||
}
|
||||
|
||||
if (resolved === null) {
|
||||
this.debugConfigurationManager.openConfiguration();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
//#endregion end of cherry-pick
|
||||
protected override fireDidChange(current: DebugSession | undefined): void {
|
||||
this.debugTypeKey.set(current?.configuration.type);
|
||||
this.inDebugModeKey.set(this.inDebugMode);
|
||||
this.debugStateKey.set(debugStateLabel(this.state));
|
||||
this.onDidChangeEmitter.fire(current);
|
||||
}
|
||||
|
||||
// preLaunchTask isn't run in case of auto restart as well as postDebugTask
|
||||
if (!options.configuration.__restart) {
|
||||
const taskRun = await this.runTask(
|
||||
options.workspaceFolderUri,
|
||||
resolved.configuration.preLaunchTask,
|
||||
true
|
||||
);
|
||||
if (!taskRun) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
protected override async doStart(
|
||||
sessionId: string,
|
||||
options: DebugConfigurationSessionOptions
|
||||
): Promise<DebugSession> {
|
||||
const parentSession =
|
||||
options.configuration.parentSession &&
|
||||
this._sessions.get(options.configuration.parentSession.id);
|
||||
const contrib = this.sessionContributionRegistry.get(
|
||||
options.configuration.type
|
||||
);
|
||||
const sessionFactory = contrib
|
||||
? contrib.debugSessionFactory()
|
||||
: this.debugSessionFactory;
|
||||
const session = sessionFactory.get(sessionId, options, parentSession);
|
||||
this._sessions.set(sessionId, session);
|
||||
|
||||
const sessionId = await this.debug.createDebugSession(
|
||||
resolved.configuration
|
||||
);
|
||||
return this.doStart(sessionId, resolved);
|
||||
} catch (e) {
|
||||
if (DebugError.NotFound.is(e)) {
|
||||
this.messageService.error(
|
||||
nls.localize(
|
||||
'theia/debug/typeNotSupported',
|
||||
'The debug session type "{0}" is not supported.',
|
||||
e.data.type
|
||||
)
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
this.debugTypeKey.set(session.configuration.type);
|
||||
// this.onDidCreateDebugSessionEmitter.fire(session); // defer the didCreate event after start https://github.com/eclipse-theia/theia/issues/11916
|
||||
|
||||
this.messageService.error(
|
||||
nls.localize(
|
||||
'theia/debug/startError',
|
||||
'There was an error starting the debug session, check the logs for more details.'
|
||||
)
|
||||
);
|
||||
console.error('Error starting the debug session', e);
|
||||
throw e;
|
||||
let state = DebugState.Inactive;
|
||||
session.onDidChange(() => {
|
||||
if (state !== session.state) {
|
||||
state = session.state;
|
||||
if (state === DebugState.Stopped) {
|
||||
this.onDidStopDebugSessionEmitter.fire(session);
|
||||
}
|
||||
}
|
||||
this.updateCurrentSession(session);
|
||||
});
|
||||
session.onDidChangeBreakpoints((uri) =>
|
||||
this.fireDidChangeBreakpoints({ session, uri })
|
||||
);
|
||||
}
|
||||
override async terminateSession(session?: DebugSession): Promise<void> {
|
||||
if (!session) {
|
||||
this.updateCurrentSession(this._currentSession);
|
||||
session = this._currentSession;
|
||||
}
|
||||
// The cortex-debug extension does not respond to close requests
|
||||
// So we simply terminate the debug session immediately
|
||||
// Alternatively the `super.terminateSession` call will terminate it after 5 seconds without a response
|
||||
await this.debug.terminateDebugSession(session!.id);
|
||||
await super.terminateSession(session);
|
||||
session.on('terminated', async (event) => {
|
||||
const restart = event.body && event.body.restart;
|
||||
if (restart) {
|
||||
// postDebugTask isn't run in case of auto restart as well as preLaunchTask
|
||||
this.doRestart(session, !!restart);
|
||||
} else {
|
||||
await session.disconnect(false, () =>
|
||||
this.debug.terminateDebugSession(session.id)
|
||||
);
|
||||
await this.runTask(
|
||||
session.options.workspaceFolderUri,
|
||||
session.configuration.postDebugTask
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
session.on('exited', async (event) => {
|
||||
await session.disconnect(false, () =>
|
||||
this.debug.terminateDebugSession(session.id)
|
||||
);
|
||||
});
|
||||
|
||||
session.onDispose(() => this.cleanup(session));
|
||||
session
|
||||
.start()
|
||||
.then(() => {
|
||||
this.onDidCreateDebugSessionEmitter.fire(session); // now fire the didCreate event
|
||||
this.onDidStartDebugSessionEmitter.fire(session);
|
||||
})
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
.catch((e) => {
|
||||
session.stop(false, () => {
|
||||
this.debug.terminateDebugSession(session.id);
|
||||
});
|
||||
});
|
||||
session.onDidCustomEvent(({ event, body }) =>
|
||||
this.onDidReceiveDebugSessionCustomEventEmitter.fire({
|
||||
event,
|
||||
body,
|
||||
session,
|
||||
})
|
||||
);
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
231
arduino-ide-extension/src/browser/theia/debug/debug-session.ts
Normal file
231
arduino-ide-extension/src/browser/theia/debug/debug-session.ts
Normal file
@@ -0,0 +1,231 @@
|
||||
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { Mutable } from '@theia/core/lib/common/types';
|
||||
import { URI } from '@theia/core/lib/common/uri';
|
||||
import { DebugSession as TheiaDebugSession } from '@theia/debug/lib/browser/debug-session';
|
||||
import { DebugFunctionBreakpoint } from '@theia/debug/lib/browser/model/debug-function-breakpoint';
|
||||
import { DebugSourceBreakpoint } from '@theia/debug/lib/browser/model/debug-source-breakpoint';
|
||||
import {
|
||||
DebugThreadData,
|
||||
StoppedDetails,
|
||||
} from '@theia/debug/lib/browser/model/debug-thread';
|
||||
import { DebugProtocol } from '@vscode/debugprotocol';
|
||||
import { DebugThread } from './debug-thread';
|
||||
|
||||
export class DebugSession extends TheiaDebugSession {
|
||||
/**
|
||||
* The `send('initialize')` request resolves later than `on('initialized')` emits the event.
|
||||
* Hence, the `configure` would use the empty object `capabilities`.
|
||||
* Using the empty `capabilities` could result in missing exception breakpoint filters, as
|
||||
* always `capabilities.exceptionBreakpointFilters` is falsy. This deferred promise works
|
||||
* around this timing issue.
|
||||
* See: https://github.com/eclipse-theia/theia/issues/11886.
|
||||
*/
|
||||
protected didReceiveCapabilities = new Deferred();
|
||||
|
||||
protected override async initialize(): Promise<void> {
|
||||
const clientName = FrontendApplicationConfigProvider.get().applicationName;
|
||||
try {
|
||||
const response = await this.connection.sendRequest('initialize', {
|
||||
clientID: clientName.toLocaleLowerCase().replace(/ /g, '_'),
|
||||
clientName,
|
||||
adapterID: this.configuration.type,
|
||||
locale: 'en-US',
|
||||
linesStartAt1: true,
|
||||
columnsStartAt1: true,
|
||||
pathFormat: 'path',
|
||||
supportsVariableType: false,
|
||||
supportsVariablePaging: false,
|
||||
supportsRunInTerminalRequest: true,
|
||||
});
|
||||
this.updateCapabilities(response?.body || {});
|
||||
this.didReceiveCapabilities.resolve();
|
||||
} catch (err) {
|
||||
this.didReceiveCapabilities.reject(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
protected override async configure(): Promise<void> {
|
||||
await this.didReceiveCapabilities.promise;
|
||||
return super.configure();
|
||||
}
|
||||
|
||||
override async stop(isRestart: boolean, callback: () => void): Promise<void> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const _this = this as any;
|
||||
if (!_this.isStopping) {
|
||||
_this.isStopping = true;
|
||||
if (this.configuration.lifecycleManagedByParent && this.parentSession) {
|
||||
await this.parentSession.stop(isRestart, callback);
|
||||
} else {
|
||||
if (this.canTerminate()) {
|
||||
const terminated = this.waitFor('terminated', 5000);
|
||||
try {
|
||||
await this.connection.sendRequest(
|
||||
'terminate',
|
||||
{ restart: isRestart },
|
||||
5000
|
||||
);
|
||||
await terminated;
|
||||
} catch (e) {
|
||||
console.error('Did not receive terminated event in time', e);
|
||||
}
|
||||
} else {
|
||||
const terminateDebuggee =
|
||||
this.initialized && this.capabilities.supportTerminateDebuggee;
|
||||
// Related https://github.com/microsoft/vscode/issues/165138
|
||||
try {
|
||||
await this.sendRequest(
|
||||
'disconnect',
|
||||
{ restart: isRestart, terminateDebuggee },
|
||||
2000
|
||||
);
|
||||
} catch (err) {
|
||||
if (
|
||||
'message' in err &&
|
||||
typeof err.message === 'string' &&
|
||||
err.message.test(err.message)
|
||||
) {
|
||||
// VS Code ignores errors when sending the `disconnect` request.
|
||||
// Debug adapter might not send the `disconnected` event as a response.
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override async sendFunctionBreakpoints(
|
||||
affectedUri: URI
|
||||
): Promise<void> {
|
||||
const all = this.breakpoints
|
||||
.getFunctionBreakpoints()
|
||||
.map(
|
||||
(origin) =>
|
||||
new DebugFunctionBreakpoint(origin, this.asDebugBreakpointOptions())
|
||||
);
|
||||
const enabled = all.filter((b) => b.enabled);
|
||||
if (this.capabilities.supportsFunctionBreakpoints) {
|
||||
try {
|
||||
const response = await this.sendRequest('setFunctionBreakpoints', {
|
||||
breakpoints: enabled.map((b) => b.origin.raw),
|
||||
});
|
||||
// Apparently, `body` and `breakpoints` can be missing.
|
||||
// https://github.com/eclipse-theia/theia/issues/11885
|
||||
// https://github.com/microsoft/vscode/blob/80004351ccf0884b58359f7c8c801c91bb827d83/src/vs/workbench/contrib/debug/browser/debugSession.ts#L448-L449
|
||||
if (response && response.body) {
|
||||
response.body.breakpoints.forEach((raw, index) => {
|
||||
// node debug adapter returns more breakpoints sometimes
|
||||
if (enabled[index]) {
|
||||
enabled[index].update({ raw });
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// could be error or promise rejection of DebugProtocol.SetFunctionBreakpoints
|
||||
if (error instanceof Error) {
|
||||
console.error(`Error setting breakpoints: ${error.message}`);
|
||||
} else {
|
||||
// handle adapters that send failed DebugProtocol.SetFunctionBreakpoints for invalid breakpoints
|
||||
const genericMessage =
|
||||
'Function breakpoint not valid for current debug session';
|
||||
const message = error.message ? `${error.message}` : genericMessage;
|
||||
console.warn(
|
||||
`Could not handle function breakpoints: ${message}, disabling...`
|
||||
);
|
||||
enabled.forEach((b) =>
|
||||
b.update({
|
||||
raw: {
|
||||
verified: false,
|
||||
message,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setBreakpoints(affectedUri, all);
|
||||
}
|
||||
|
||||
protected override async sendSourceBreakpoints(
|
||||
affectedUri: URI,
|
||||
sourceModified?: boolean
|
||||
): Promise<void> {
|
||||
const source = await this.toSource(affectedUri);
|
||||
const all = this.breakpoints
|
||||
.findMarkers({ uri: affectedUri })
|
||||
.map(
|
||||
({ data }) =>
|
||||
new DebugSourceBreakpoint(data, this.asDebugBreakpointOptions())
|
||||
);
|
||||
const enabled = all.filter((b) => b.enabled);
|
||||
try {
|
||||
const breakpoints = enabled.map(({ origin }) => origin.raw);
|
||||
const response = await this.sendRequest('setBreakpoints', {
|
||||
source: source.raw,
|
||||
sourceModified,
|
||||
breakpoints,
|
||||
lines: breakpoints.map(({ line }) => line),
|
||||
});
|
||||
response.body.breakpoints.forEach((raw, index) => {
|
||||
// node debug adapter returns more breakpoints sometimes
|
||||
if (enabled[index]) {
|
||||
enabled[index].update({ raw });
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
// could be error or promise rejection of DebugProtocol.SetBreakpointsResponse
|
||||
if (error instanceof Error) {
|
||||
console.error(`Error setting breakpoints: ${error.message}`);
|
||||
} else {
|
||||
// handle adapters that send failed DebugProtocol.SetBreakpointsResponse for invalid breakpoints
|
||||
const genericMessage = 'Breakpoint not valid for current debug session';
|
||||
const message = error.message ? `${error.message}` : genericMessage;
|
||||
console.warn(
|
||||
`Could not handle breakpoints for ${affectedUri}: ${message}, disabling...`
|
||||
);
|
||||
enabled.forEach((b) =>
|
||||
b.update({
|
||||
raw: {
|
||||
verified: false,
|
||||
message,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
this.setSourceBreakpoints(affectedUri, all);
|
||||
}
|
||||
|
||||
protected override doUpdateThreads(
|
||||
threads: DebugProtocol.Thread[],
|
||||
stoppedDetails?: StoppedDetails
|
||||
): void {
|
||||
const existing = this._threads;
|
||||
this._threads = new Map();
|
||||
for (const raw of threads) {
|
||||
const id = raw.id;
|
||||
const thread = existing.get(id) || new DebugThread(this); // patched debug thread
|
||||
this._threads.set(id, thread);
|
||||
const data: Partial<Mutable<DebugThreadData>> = { raw };
|
||||
if (stoppedDetails) {
|
||||
if (stoppedDetails.threadId === id) {
|
||||
data.stoppedDetails = stoppedDetails;
|
||||
} else if (stoppedDetails.allThreadsStopped) {
|
||||
data.stoppedDetails = {
|
||||
// When a debug adapter notifies us that all threads are stopped,
|
||||
// we do not know why the others are stopped, so we should default
|
||||
// to something generic.
|
||||
reason: '',
|
||||
};
|
||||
}
|
||||
}
|
||||
thread.update(data);
|
||||
}
|
||||
this.updateCurrentThread(stoppedDetails);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
import { WidgetOpenerOptions } from '@theia/core/lib/browser/widget-open-handler';
|
||||
import { Range } from '@theia/core/shared/vscode-languageserver-types';
|
||||
import { DebugStackFrame as TheiaDebugStackFrame } from '@theia/debug/lib/browser/model/debug-stack-frame';
|
||||
import { EditorWidget } from '@theia/editor/lib/browser/editor-widget';
|
||||
|
||||
export class DebugStackFrame extends TheiaDebugStackFrame {
|
||||
override async open(
|
||||
options: WidgetOpenerOptions = {
|
||||
mode: 'reveal',
|
||||
}
|
||||
): Promise<EditorWidget | undefined> {
|
||||
if (!this.source) {
|
||||
return undefined;
|
||||
}
|
||||
const { line, column, endLine, endColumn, source } = this.raw;
|
||||
if (!source) {
|
||||
return undefined;
|
||||
}
|
||||
// create selection based on VS Code
|
||||
// https://github.com/eclipse-theia/theia/issues/11880
|
||||
const selection = Range.create(
|
||||
line,
|
||||
column,
|
||||
endLine || line,
|
||||
endColumn || column
|
||||
);
|
||||
this.source.open({
|
||||
...options,
|
||||
selection,
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
import { DebugStackFrame as TheiaDebugStackFrame } from '@theia/debug/lib/browser/model/debug-stack-frame';
|
||||
import { DebugThread as TheiaDebugThread } from '@theia/debug/lib/browser/model/debug-thread';
|
||||
import { DebugProtocol } from '@vscode/debugprotocol';
|
||||
import { DebugStackFrame } from './debug-stack-frame';
|
||||
|
||||
export class DebugThread extends TheiaDebugThread {
|
||||
protected override doUpdateFrames(
|
||||
frames: DebugProtocol.StackFrame[]
|
||||
): TheiaDebugStackFrame[] {
|
||||
const result = new Set<TheiaDebugStackFrame>();
|
||||
for (const raw of frames) {
|
||||
const id = raw.id;
|
||||
const frame =
|
||||
this._frames.get(id) || new DebugStackFrame(this, this.session); // patched debug stack frame
|
||||
this._frames.set(id, frame);
|
||||
frame.update({ raw });
|
||||
result.add(frame);
|
||||
}
|
||||
this.updateCurrentFrame();
|
||||
return [...result.values()];
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import {
|
||||
ActionMenuNode,
|
||||
CompositeMenuNode,
|
||||
MenuModelRegistry,
|
||||
} from '@theia/core/lib/common/menu';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { DebugState } from '@theia/debug/lib/browser/debug-session';
|
||||
import { DebugAction } from './debug-action';
|
||||
import { DebugToolBar as TheiaDebugToolbar } from '@theia/debug/lib/browser/view/debug-toolbar-widget';
|
||||
|
||||
@injectable()
|
||||
export class DebugToolbar extends TheiaDebugToolbar {
|
||||
@inject(CommandRegistry) private readonly commandRegistry: CommandRegistry;
|
||||
@inject(MenuModelRegistry)
|
||||
private readonly menuModelRegistry: MenuModelRegistry;
|
||||
@inject(ContextKeyService)
|
||||
private readonly contextKeyService: ContextKeyService;
|
||||
|
||||
protected override render(): React.ReactNode {
|
||||
const { state } = this.model;
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.renderContributedCommands()}
|
||||
{this.renderContinue()}
|
||||
<DebugAction
|
||||
enabled={state === DebugState.Stopped}
|
||||
run={this.stepOver}
|
||||
label={nls.localizeByDefault('Step Over')}
|
||||
iconClass="debug-step-over"
|
||||
ref={this.setStepRef}
|
||||
/>
|
||||
<DebugAction
|
||||
enabled={state === DebugState.Stopped}
|
||||
run={this.stepIn}
|
||||
label={nls.localizeByDefault('Step Into')}
|
||||
iconClass="debug-step-into"
|
||||
/>
|
||||
<DebugAction
|
||||
enabled={state === DebugState.Stopped}
|
||||
run={this.stepOut}
|
||||
label={nls.localizeByDefault('Step Out')}
|
||||
iconClass="debug-step-out"
|
||||
/>
|
||||
<DebugAction
|
||||
enabled={state !== DebugState.Inactive}
|
||||
run={this.restart}
|
||||
label={nls.localizeByDefault('Restart')}
|
||||
iconClass="debug-restart"
|
||||
/>
|
||||
{this.renderStart()}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
private renderContributedCommands(): React.ReactNode {
|
||||
return this.menuModelRegistry
|
||||
.getMenu(TheiaDebugToolbar.MENU)
|
||||
.children.filter((node) => node instanceof CompositeMenuNode)
|
||||
.map((node) => (node as CompositeMenuNode).children)
|
||||
.reduce((acc, curr) => acc.concat(curr), [])
|
||||
.filter((node) => node instanceof ActionMenuNode)
|
||||
.map((node) => this.debugAction(node as ActionMenuNode));
|
||||
}
|
||||
|
||||
private debugAction(node: ActionMenuNode): React.ReactNode {
|
||||
const { label, command, when, icon: iconClass = '' } = node;
|
||||
const run = () => this.commandRegistry.executeCommand(command);
|
||||
const enabled = when ? this.contextKeyService.match(when) : true;
|
||||
return (
|
||||
enabled && (
|
||||
<DebugAction
|
||||
key={command}
|
||||
enabled={enabled}
|
||||
label={label}
|
||||
iconClass={iconClass}
|
||||
run={run}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
import { injectable, inject } from '@theia/core/shared/inversify';
|
||||
|
||||
import {
|
||||
AbstractDialog as TheiaAbstractDialog,
|
||||
codiconArray,
|
||||
DialogProps,
|
||||
} from '@theia/core/lib/browser';
|
||||
|
||||
@injectable()
|
||||
export abstract class AbstractDialog<T> extends TheiaAbstractDialog<T> {
|
||||
constructor(@inject(DialogProps) protected override readonly props: DialogProps) {
|
||||
super(props);
|
||||
|
||||
this.closeCrossNode.classList.remove(...codiconArray('close'));
|
||||
this.closeCrossNode.classList.add('fa', 'fa-close');
|
||||
}
|
||||
}
|
63
arduino-ide-extension/src/browser/theia/dialogs/dialogs.tsx
Normal file
63
arduino-ide-extension/src/browser/theia/dialogs/dialogs.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
AbstractDialog as TheiaAbstractDialog,
|
||||
DialogProps,
|
||||
} from '@theia/core/lib/browser/dialogs';
|
||||
import { ReactDialog as TheiaReactDialog } from '@theia/core/lib/browser/dialogs/react-dialog';
|
||||
import { codiconArray, Message } from '@theia/core/lib/browser/widgets/widget';
|
||||
import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { createRoot } from '@theia/core/shared/react-dom/client';
|
||||
|
||||
@injectable()
|
||||
export abstract class AbstractDialog<T> extends TheiaAbstractDialog<T> {
|
||||
constructor(
|
||||
@inject(DialogProps) protected override readonly props: DialogProps
|
||||
) {
|
||||
super(props);
|
||||
|
||||
this.closeCrossNode.classList.remove(...codiconArray('close'));
|
||||
this.closeCrossNode.classList.add('fa', 'fa-close');
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export abstract class ReactDialog<T> extends TheiaReactDialog<T> {
|
||||
protected override onUpdateRequest(msg: Message): void {
|
||||
// This is tricky to bypass the default Theia code.
|
||||
// Otherwise, there is a warning when opening the dialog for the second time.
|
||||
// You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it.
|
||||
const disposables = new DisposableCollection();
|
||||
if (!this.isMounted) {
|
||||
// toggle the `isMounted` logic for the time being of the super call so that the `createRoot` does not run
|
||||
this.isMounted = true;
|
||||
disposables.push(Disposable.create(() => (this.isMounted = false)));
|
||||
}
|
||||
|
||||
// Always unset the `contentNodeRoot` so there is no double update when calling super.
|
||||
const restoreContentNodeRoot = this.contentNodeRoot;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(this.contentNodeRoot as any) = undefined;
|
||||
disposables.push(
|
||||
Disposable.create(() => (this.contentNodeRoot = restoreContentNodeRoot))
|
||||
);
|
||||
|
||||
try {
|
||||
super.onUpdateRequest(msg);
|
||||
} finally {
|
||||
disposables.dispose();
|
||||
}
|
||||
|
||||
// Use the patched rendering.
|
||||
if (!this.isMounted) {
|
||||
this.contentNodeRoot = createRoot(this.contentNode);
|
||||
// Resetting the prop is missing from the Theia code.
|
||||
// https://github.com/eclipse-theia/theia/blob/v1.31.1/packages/core/src/browser/dialogs/react-dialog.tsx#L41-L47
|
||||
this.isMounted = true;
|
||||
}
|
||||
this.contentNodeRoot?.render(<>{this.render()}</>);
|
||||
}
|
||||
}
|
@@ -20,7 +20,7 @@ export class EditorWidgetFactory extends TheiaEditorWidgetFactory {
|
||||
|
||||
protected override async createEditor(
|
||||
uri: URI,
|
||||
options: NavigatableWidgetOptions
|
||||
options?: NavigatableWidgetOptions
|
||||
): Promise<EditorWidget> {
|
||||
const widget = await super.createEditor(uri, options);
|
||||
return this.maybeUpdateCaption(widget);
|
||||
|
@@ -3,7 +3,7 @@ import {
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { Diagnostic } from 'vscode-languageserver-types';
|
||||
import { Diagnostic } from '@theia/core/shared/vscode-languageserver-types';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { ILogger } from '@theia/core';
|
||||
import { Marker } from '@theia/markers/lib/common/marker';
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import * as ReactDOM from '@theia/core/shared/react-dom';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
@@ -25,15 +24,14 @@ export class NotificationsRenderer extends TheiaNotificationsRenderer {
|
||||
}
|
||||
|
||||
protected override render(): void {
|
||||
ReactDOM.render(
|
||||
this.containerRoot.render(
|
||||
<div>
|
||||
<NotificationToastsComponent
|
||||
manager={this.manager}
|
||||
corePreferences={this.corePreferences}
|
||||
/>
|
||||
<NotificationCenterComponent manager={this.manager} />
|
||||
</div>,
|
||||
this.container
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,23 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { MonacoThemingService as TheiaMonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service';
|
||||
import { ArduinoThemes } from '../core/theming';
|
||||
|
||||
@injectable()
|
||||
export class MonacoThemingService extends TheiaMonacoThemingService {
|
||||
override initialize(): void {
|
||||
super.initialize();
|
||||
const { Light, Dark } = ArduinoThemes;
|
||||
this.registerParsedTheme({
|
||||
id: Light.id,
|
||||
label: Light.label,
|
||||
uiTheme: 'vs',
|
||||
json: require('../../../../src/browser/data/default.color-theme.json'),
|
||||
});
|
||||
this.registerParsedTheme({
|
||||
id: Dark.id,
|
||||
label: Dark.label,
|
||||
uiTheme: 'vs-dark',
|
||||
json: require('../../../../src/browser/data/dark.color-theme.json'),
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
Disposable,
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { DebuggerDescription } from '@theia/debug/lib/common/debug-service';
|
||||
import { DebugMainImpl as TheiaDebugMainImpl } from '@theia/plugin-ext/lib/main/browser/debug/debug-main';
|
||||
import { PluginDebugAdapterContribution } from '@theia/plugin-ext/lib/main/browser/debug/plugin-debug-adapter-contribution';
|
||||
import { PluginDebugSessionFactory } from './plugin-debug-session-factory';
|
||||
|
||||
export class DebugMainImpl extends TheiaDebugMainImpl {
|
||||
override async $registerDebuggerContribution(
|
||||
description: DebuggerDescription
|
||||
): Promise<void> {
|
||||
const debugType = description.type;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const _this = <any>this;
|
||||
const terminalOptionsExt = await _this.debugExt.$getTerminalCreationOptions(
|
||||
debugType
|
||||
);
|
||||
|
||||
if (_this.toDispose.disposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const debugSessionFactory = new PluginDebugSessionFactory(
|
||||
_this.terminalService,
|
||||
_this.editorManager,
|
||||
_this.breakpointsManager,
|
||||
_this.labelProvider,
|
||||
_this.messages,
|
||||
_this.outputChannelManager,
|
||||
_this.debugPreferences,
|
||||
async (sessionId: string) => {
|
||||
const connection = await _this.connectionMain.ensureConnection(
|
||||
sessionId
|
||||
);
|
||||
return connection;
|
||||
},
|
||||
_this.fileService,
|
||||
terminalOptionsExt,
|
||||
_this.debugContributionProvider,
|
||||
_this.workspaceService
|
||||
);
|
||||
|
||||
const toDispose = new DisposableCollection(
|
||||
Disposable.create(() => _this.debuggerContributions.delete(debugType))
|
||||
);
|
||||
_this.debuggerContributions.set(debugType, toDispose);
|
||||
toDispose.pushAll([
|
||||
_this.pluginDebugService.registerDebugAdapterContribution(
|
||||
new PluginDebugAdapterContribution(
|
||||
description,
|
||||
_this.debugExt,
|
||||
_this.pluginService
|
||||
)
|
||||
),
|
||||
_this.sessionContributionRegistrator.registerDebugSessionContribution({
|
||||
debugType: description.type,
|
||||
debugSessionFactory: () => debugSessionFactory,
|
||||
}),
|
||||
]);
|
||||
_this.toDispose.push(
|
||||
Disposable.create(() => this.$unregisterDebuggerConfiguration(debugType))
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,7 +1,17 @@
|
||||
import { Emitter, Event, JsonRpcProxy } from '@theia/core';
|
||||
import { injectable, interfaces } from '@theia/core/shared/inversify';
|
||||
import { HostedPluginServer } from '@theia/plugin-ext/lib/common/plugin-protocol';
|
||||
import { HostedPluginSupport as TheiaHostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
|
||||
import { RPCProtocol } from '@theia/plugin-ext/lib/common/rpc-protocol';
|
||||
import {
|
||||
HostedPluginSupport as TheiaHostedPluginSupport,
|
||||
PluginHost,
|
||||
} from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
|
||||
import { PluginWorker } from '@theia/plugin-ext/lib/hosted/browser/plugin-worker';
|
||||
import { setUpPluginApi } from '@theia/plugin-ext/lib/main/browser/main-context';
|
||||
import { PLUGIN_RPC_CONTEXT } from '@theia/plugin-ext/lib/common/plugin-api-rpc';
|
||||
import { DebugMainImpl } from './debug-main';
|
||||
import { ConnectionImpl } from '@theia/plugin-ext/lib/common/connection';
|
||||
|
||||
@injectable()
|
||||
export class HostedPluginSupport extends TheiaHostedPluginSupport {
|
||||
private readonly onDidLoadEmitter = new Emitter<void>();
|
||||
@@ -31,4 +41,26 @@ export class HostedPluginSupport extends TheiaHostedPluginSupport {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return (this as any).server;
|
||||
}
|
||||
|
||||
// to patch the VS Code extension based debugger
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
protected override initRpc(host: PluginHost, pluginId: string): RPCProtocol {
|
||||
const rpc =
|
||||
host === 'frontend' ? new PluginWorker().rpc : this.createServerRpc(host);
|
||||
setUpPluginApi(rpc, this.container);
|
||||
this.patchDebugMain(rpc);
|
||||
this.mainPluginApiProviders
|
||||
.getContributions()
|
||||
.forEach((p) => p.initialize(rpc, this.container));
|
||||
return rpc;
|
||||
}
|
||||
|
||||
private patchDebugMain(rpc: RPCProtocol): void {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const connectionMain = (rpc as any).locals.get(
|
||||
PLUGIN_RPC_CONTEXT.CONNECTION_MAIN.id
|
||||
) as ConnectionImpl;
|
||||
const debugMain = new DebugMainImpl(rpc, connectionMain, this.container);
|
||||
rpc.set(PLUGIN_RPC_CONTEXT.DEBUG_MAIN, debugMain);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
import { DebugSession } from '@theia/debug/lib/browser/debug-session';
|
||||
import { DebugSessionConnection } from '@theia/debug/lib/browser/debug-session-connection';
|
||||
import { DebugConfigurationSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
|
||||
import { PluginDebugSessionFactory as TheiaPluginDebugSessionFactory } from '@theia/plugin-ext/lib/main/browser/debug/plugin-debug-session-factory';
|
||||
import { PluginDebugSession } from './plugin-debug-session';
|
||||
|
||||
export class PluginDebugSessionFactory extends TheiaPluginDebugSessionFactory {
|
||||
override get(
|
||||
sessionId: string,
|
||||
options: DebugConfigurationSessionOptions,
|
||||
parentSession?: DebugSession
|
||||
): DebugSession {
|
||||
const connection = new DebugSessionConnection(
|
||||
sessionId,
|
||||
this.connectionFactory,
|
||||
this.getTraceOutputChannel()
|
||||
);
|
||||
|
||||
return new PluginDebugSession(
|
||||
sessionId,
|
||||
options,
|
||||
parentSession,
|
||||
connection,
|
||||
this.terminalService,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.editorManager as any,
|
||||
this.breakpoints,
|
||||
this.labelProvider,
|
||||
this.messages,
|
||||
this.fileService,
|
||||
this.terminalOptionsExt,
|
||||
this.debugContributionProvider,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.workspaceService as any
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
import { ContributionProvider, MessageClient } from '@theia/core';
|
||||
import { LabelProvider } from '@theia/core/lib/browser';
|
||||
import { BreakpointManager } from '@theia/debug/lib/browser/breakpoint/breakpoint-manager';
|
||||
import { DebugContribution } from '@theia/debug/lib/browser/debug-contribution';
|
||||
import { DebugSession as TheiaDebugSession } from '@theia/debug/lib/browser/debug-session';
|
||||
import { DebugSessionConnection } from '@theia/debug/lib/browser/debug-session-connection';
|
||||
import { DebugConfigurationSessionOptions } from '@theia/debug/lib/browser/debug-session-options';
|
||||
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
||||
import { TerminalOptionsExt } from '@theia/plugin-ext';
|
||||
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
|
||||
import {
|
||||
TerminalWidget,
|
||||
TerminalWidgetOptions,
|
||||
} from '@theia/terminal/lib/browser/base/terminal-widget';
|
||||
import { DebugSession } from '../debug/debug-session';
|
||||
import { EditorManager } from '../editor/editor-manager';
|
||||
import { WorkspaceService } from '../workspace/workspace-service';
|
||||
|
||||
// This class extends the patched debug session, and not the default debug session from Theia
|
||||
export class PluginDebugSession extends DebugSession {
|
||||
constructor(
|
||||
override readonly id: string,
|
||||
override readonly options: DebugConfigurationSessionOptions,
|
||||
override readonly parentSession: TheiaDebugSession | undefined,
|
||||
protected override readonly connection: DebugSessionConnection,
|
||||
protected override readonly terminalServer: TerminalService,
|
||||
protected override readonly editorManager: EditorManager,
|
||||
protected override readonly breakpoints: BreakpointManager,
|
||||
protected override readonly labelProvider: LabelProvider,
|
||||
protected override readonly messages: MessageClient,
|
||||
protected override readonly fileService: FileService,
|
||||
protected readonly terminalOptionsExt: TerminalOptionsExt | undefined,
|
||||
protected override readonly debugContributionProvider: ContributionProvider<DebugContribution>,
|
||||
protected override readonly workspaceService: WorkspaceService
|
||||
) {
|
||||
super(
|
||||
id,
|
||||
options,
|
||||
parentSession,
|
||||
connection,
|
||||
terminalServer,
|
||||
editorManager,
|
||||
breakpoints,
|
||||
labelProvider,
|
||||
messages,
|
||||
fileService,
|
||||
debugContributionProvider,
|
||||
workspaceService
|
||||
);
|
||||
}
|
||||
|
||||
protected override async doCreateTerminal(
|
||||
terminalWidgetOptions: TerminalWidgetOptions
|
||||
): Promise<TerminalWidget> {
|
||||
terminalWidgetOptions = Object.assign(
|
||||
{},
|
||||
terminalWidgetOptions,
|
||||
this.terminalOptionsExt
|
||||
);
|
||||
return super.doCreateTerminal(terminalWidgetOptions);
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
import { MenuPath } from '@theia/core';
|
||||
import { TAB_BAR_TOOLBAR_CONTEXT_MENU } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { injectable, postConstruct } from '@theia/core/shared/inversify';
|
||||
import { DebugToolBar } from '@theia/debug/lib/browser/view/debug-toolbar-widget';
|
||||
import { DebugVariablesWidget } from '@theia/debug/lib/browser/view/debug-variables-widget';
|
||||
import {
|
||||
ArgumentAdapter,
|
||||
PluginMenuCommandAdapter as TheiaPluginMenuCommandAdapter,
|
||||
} from '@theia/plugin-ext/lib/main/browser/menus/plugin-menu-command-adapter';
|
||||
import {
|
||||
codeToTheiaMappings,
|
||||
ContributionPoint,
|
||||
} from '@theia/plugin-ext/lib/main/browser/menus/vscode-theia-menu-mappings';
|
||||
|
||||
function patch(
|
||||
toPatch: typeof codeToTheiaMappings,
|
||||
key: string,
|
||||
value: MenuPath[]
|
||||
): void {
|
||||
const loose = toPatch as Map<string, MenuPath[]>;
|
||||
if (!loose.has(key)) {
|
||||
loose.set(key, value);
|
||||
}
|
||||
}
|
||||
// mappings is a const and cannot be customized with DI
|
||||
patch(codeToTheiaMappings, 'debug/variables/context', [
|
||||
DebugVariablesWidget.CONTEXT_MENU,
|
||||
]);
|
||||
patch(codeToTheiaMappings, 'debug/toolBar', [DebugToolBar.MENU]);
|
||||
|
||||
@injectable()
|
||||
export class PluginMenuCommandAdapter extends TheiaPluginMenuCommandAdapter {
|
||||
@postConstruct()
|
||||
protected override init(): void {
|
||||
const toCommentArgs: ArgumentAdapter = (...args) =>
|
||||
this.toCommentArgs(...args);
|
||||
const firstArgOnly: ArgumentAdapter = (...args) => [args[0]];
|
||||
const noArgs: ArgumentAdapter = () => [];
|
||||
const toScmArgs: ArgumentAdapter = (...args) => this.toScmArgs(...args);
|
||||
const selectedResource = () => this.getSelectedResources();
|
||||
const widgetURI: ArgumentAdapter = (widget) =>
|
||||
this.codeEditorUtil.is(widget)
|
||||
? [this.codeEditorUtil.getResourceUri(widget)]
|
||||
: [];
|
||||
(<Array<[ContributionPoint, ArgumentAdapter | undefined]>>[
|
||||
['comments/comment/context', toCommentArgs],
|
||||
['comments/comment/title', toCommentArgs],
|
||||
['comments/commentThread/context', toCommentArgs],
|
||||
['debug/callstack/context', firstArgOnly],
|
||||
['debug/variables/context', firstArgOnly],
|
||||
['debug/toolBar', noArgs],
|
||||
['editor/context', selectedResource],
|
||||
['editor/title', widgetURI],
|
||||
['editor/title/context', selectedResource],
|
||||
['explorer/context', selectedResource],
|
||||
['scm/resourceFolder/context', toScmArgs],
|
||||
['scm/resourceGroup/context', toScmArgs],
|
||||
['scm/resourceState/context', toScmArgs],
|
||||
['scm/title', () => this.toScmArg(this.scmService.selectedRepository)],
|
||||
['timeline/item/context', (...args) => this.toTimelineArgs(...args)],
|
||||
['view/item/context', (...args) => this.toTreeArgs(...args)],
|
||||
['view/title', noArgs],
|
||||
]).forEach(([contributionPoint, adapter]) => {
|
||||
if (adapter) {
|
||||
const paths = codeToTheiaMappings.get(contributionPoint);
|
||||
if (paths) {
|
||||
paths.forEach((path) => this.addArgumentAdapter(path, adapter));
|
||||
}
|
||||
}
|
||||
});
|
||||
this.addArgumentAdapter(TAB_BAR_TOOLBAR_CONTEXT_MENU, widgetURI);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
TypeHierarchyCommands,
|
||||
TypeHierarchyContribution as TheiaTypeHierarchyContribution,
|
||||
} from '@theia/typehierarchy/lib/browser/typehierarchy-contribution';
|
||||
|
||||
@injectable()
|
||||
export class TypeHierarchyContribution extends TheiaTypeHierarchyContribution {
|
||||
protected override init(): void {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
super.registerCommands(registry);
|
||||
registry.unregisterCommand(TypeHierarchyCommands.OPEN_SUBTYPE.id);
|
||||
registry.unregisterCommand(TypeHierarchyCommands.OPEN_SUPERTYPE.id);
|
||||
}
|
||||
|
||||
override registerMenus(registry: MenuModelRegistry): void {
|
||||
super.registerMenus(registry);
|
||||
registry.unregisterMenuAction(TypeHierarchyCommands.OPEN_SUBTYPE.id);
|
||||
registry.unregisterMenuAction(TypeHierarchyCommands.OPEN_SUPERTYPE.id);
|
||||
}
|
||||
|
||||
override registerKeybindings(registry: KeybindingRegistry): void {
|
||||
super.registerKeybindings(registry);
|
||||
registry.unregisterKeybinding(TypeHierarchyCommands.OPEN_SUBTYPE.id);
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { TypeHierarchyServiceProvider as TheiaTypeHierarchyServiceProvider } from '@theia/typehierarchy/lib/browser/typehierarchy-service';
|
||||
|
||||
@injectable()
|
||||
export class TypeHierarchyServiceProvider extends TheiaTypeHierarchyServiceProvider {
|
||||
override init(): void {
|
||||
// NOOP
|
||||
}
|
||||
}
|
@@ -1,58 +1,37 @@
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import { injectable, inject, named } from '@theia/core/shared/inversify';
|
||||
import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { EditorWidget } from '@theia/editor/lib/browser';
|
||||
import { ApplicationServer } from '@theia/core/lib/common/application-protocol';
|
||||
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FocusTracker, Widget } from '@theia/core/lib/browser';
|
||||
import {
|
||||
DEFAULT_WINDOW_HASH,
|
||||
NewWindowOptions,
|
||||
} from '@theia/core/lib/common/window';
|
||||
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
||||
import { FileStat } from '@theia/filesystem/lib/common/files';
|
||||
import {
|
||||
WorkspaceInput,
|
||||
WorkspaceService as TheiaWorkspaceService,
|
||||
} from '@theia/workspace/lib/browser/workspace-service';
|
||||
import {
|
||||
SketchesService,
|
||||
Sketch,
|
||||
SketchesError,
|
||||
SketchesService,
|
||||
} from '../../../common/protocol/sketches-service';
|
||||
import { FileStat } from '@theia/filesystem/lib/common/files';
|
||||
import {
|
||||
StartupTask,
|
||||
StartupTaskProvider,
|
||||
} from '../../../electron-common/startup-task';
|
||||
import { WindowServiceExt } from '../core/window-service-ext';
|
||||
import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
||||
|
||||
@injectable()
|
||||
export class WorkspaceService extends TheiaWorkspaceService {
|
||||
@inject(SketchesService)
|
||||
private readonly sketchService: SketchesService;
|
||||
@inject(ApplicationServer)
|
||||
private readonly applicationServer: ApplicationServer;
|
||||
@inject(WindowServiceExt)
|
||||
private readonly windowServiceExt: WindowServiceExt;
|
||||
@inject(ContributionProvider)
|
||||
@named(StartupTaskProvider)
|
||||
private readonly providers: ContributionProvider<StartupTaskProvider>;
|
||||
|
||||
private version?: string;
|
||||
private _workspaceError: Error | undefined;
|
||||
|
||||
async onStart(application: FrontendApplication): Promise<void> {
|
||||
const info = await this.applicationServer.getApplicationInfo();
|
||||
this.version = info?.version;
|
||||
application.shell.onDidChangeCurrentWidget(
|
||||
this.onCurrentWidgetChange.bind(this)
|
||||
);
|
||||
const newValue = application.shell.currentWidget
|
||||
? application.shell.currentWidget
|
||||
: null;
|
||||
this.onCurrentWidgetChange({ newValue, oldValue: null });
|
||||
}
|
||||
|
||||
get workspaceError(): Error | undefined {
|
||||
return this._workspaceError;
|
||||
}
|
||||
@@ -121,58 +100,6 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from Theia as-is to be able to pass the original `options` down.
|
||||
*/
|
||||
protected override async doOpen(
|
||||
uri: URI,
|
||||
options?: WorkspaceInput
|
||||
): Promise<URI | undefined> {
|
||||
const stat = await this.toFileStat(uri);
|
||||
if (stat) {
|
||||
if (!stat.isDirectory && !this.isWorkspaceFile(stat)) {
|
||||
const message = `Not a valid workspace: ${uri.path.toString()}`;
|
||||
this.messageService.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
// The same window has to be preserved too (instead of opening a new one), if the workspace root is not yet available and we are setting it for the first time.
|
||||
// Option passed as parameter has the highest priority (for api developers), then the preference, then the default.
|
||||
await this.roots;
|
||||
const { preserveWindow } = {
|
||||
preserveWindow:
|
||||
this.preferences['workspace.preserveWindow'] || !this.opened,
|
||||
...options,
|
||||
};
|
||||
await this.server.setMostRecentlyUsedWorkspace(uri.toString());
|
||||
if (preserveWindow) {
|
||||
this._workspace = stat;
|
||||
}
|
||||
this.openWindow(stat, Object.assign(options ?? {}, { preserveWindow })); // Unlike Theia, IDE2 passes the whole `input` downstream and not only { preserveWindow }
|
||||
return;
|
||||
}
|
||||
throw new Error(
|
||||
'Invalid workspace root URI. Expected an existing directory or workspace file.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from Theia. Can pass the `options` further down the chain.
|
||||
*/
|
||||
protected override openWindow(uri: FileStat, options?: WorkspaceInput): void {
|
||||
const workspacePath = uri.resource.path.toString();
|
||||
if (this.shouldPreserveWindow(options)) {
|
||||
this.reloadWindow(options); // Unlike Theia, IDE2 passes the `input` downstream.
|
||||
} else {
|
||||
try {
|
||||
this.openNewWindow(workspacePath, options); // Unlike Theia, IDE2 passes the `input` downstream.
|
||||
} catch (error) {
|
||||
// Fall back to reloading the current window in case the browser has blocked the new window
|
||||
this._workspace = uri;
|
||||
this.logger.error(error.toString()).then(() => this.reloadWindow());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override reloadWindow(options?: WorkspaceInput): void {
|
||||
const tasks = this.tasks(options);
|
||||
this.setURLFragment(this._workspace?.resource.path.toString() || '');
|
||||
@@ -192,6 +119,10 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
);
|
||||
}
|
||||
|
||||
protected override updateTitle(): void {
|
||||
// NOOP. IDE2 handles the `window.title` updates solely via the customized `WindowTitleUpdater`.
|
||||
}
|
||||
|
||||
private tasks(options?: WorkspaceInput): StartupTask[] {
|
||||
const tasks = this.providers
|
||||
.getContributions()
|
||||
@@ -202,37 +133,4 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
protected onCurrentWidgetChange({
|
||||
newValue,
|
||||
}: FocusTracker.IChangedArgs<Widget>): void {
|
||||
if (newValue instanceof EditorWidget) {
|
||||
const { uri } = newValue.editor;
|
||||
const currentWindow = remote.getCurrentWindow();
|
||||
currentWindow.setRepresentedFilename(uri.path.toString());
|
||||
if (Sketch.isSketchFile(uri.toString())) {
|
||||
this.updateTitle();
|
||||
} else {
|
||||
const title = this.workspaceTitle;
|
||||
const fileName = this.labelProvider.getName(uri);
|
||||
document.title = this.formatTitle(
|
||||
title ? `${title} - ${fileName}` : fileName
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.updateTitle();
|
||||
}
|
||||
}
|
||||
|
||||
protected override formatTitle(title?: string): string {
|
||||
const version = this.version ? ` ${this.version}` : '';
|
||||
const name = `${this.applicationName} ${version}`;
|
||||
return title ? `${title} | ${name}` : name;
|
||||
}
|
||||
|
||||
protected get workspaceTitle(): string | undefined {
|
||||
if (this.workspace) {
|
||||
return this.labelProvider.getName(this.workspace.resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,22 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import Select from 'react-select';
|
||||
import { Styles } from 'react-select/src/styles';
|
||||
import { Props } from 'react-select/src/components';
|
||||
import { ThemeConfig } from 'react-select/src/theme';
|
||||
import type { StylesConfig } from 'react-select/dist/declarations/src/styles';
|
||||
import type { ThemeConfig } from 'react-select/dist/declarations/src/theme';
|
||||
import type { GroupBase } from 'react-select/dist/declarations/src/types';
|
||||
import type { StateManagerProps } from 'react-select/dist/declarations/src/useStateManager';
|
||||
|
||||
export class ArduinoSelect<T> extends Select<T> {
|
||||
constructor(props: Readonly<Props<T, false>>) {
|
||||
export class ArduinoSelect<
|
||||
Option,
|
||||
IsMulti extends boolean = false,
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
> extends React.Component<StateManagerProps<Option, IsMulti, Group>> {
|
||||
constructor(props: StateManagerProps<Option, IsMulti, Group>) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
override render(): React.ReactNode {
|
||||
const controlHeight = 27; // from `monitor.css` -> `.serial-monitor-container .head` (`height: 27px;`)
|
||||
const styles: Styles<T, false> = {
|
||||
const styles: StylesConfig = {
|
||||
control: (styles) => ({
|
||||
...styles,
|
||||
minWidth: 120,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import * as ReactDOM from '@theia/core/shared/react-dom';
|
||||
import type { Root } from '@theia/core/shared/react-dom/client';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
@@ -49,8 +49,8 @@ export class CloudSketchbookCompositeWidget extends BaseSketchbookCompositeWidge
|
||||
return this.cloudSketchbookTreeWidget;
|
||||
}
|
||||
|
||||
protected renderFooter(footerNode: HTMLElement): void {
|
||||
ReactDOM.render(
|
||||
protected renderFooter(footerRoot: Root): void {
|
||||
footerRoot.render(
|
||||
<>
|
||||
{this._session && (
|
||||
<CreateNew
|
||||
@@ -67,8 +67,7 @@ export class CloudSketchbookCompositeWidget extends BaseSketchbookCompositeWidge
|
||||
}
|
||||
authenticationService={this.authenticationService}
|
||||
/>
|
||||
</>,
|
||||
footerNode
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import * as ReactDOM from '@theia/core/shared/react-dom';
|
||||
import { createRoot, Root } from '@theia/core/shared/react-dom/client';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
@@ -18,29 +18,30 @@ export abstract class BaseSketchbookCompositeWidget<
|
||||
protected readonly commandService: CommandService;
|
||||
|
||||
private readonly compositeNode: HTMLElement;
|
||||
private readonly footerNode: HTMLElement;
|
||||
private readonly footerRoot: Root;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.compositeNode = document.createElement('div');
|
||||
this.compositeNode.classList.add('composite-node');
|
||||
this.footerNode = document.createElement('div');
|
||||
this.footerNode.classList.add('footer-node');
|
||||
this.compositeNode.appendChild(this.footerNode);
|
||||
const footerNode = document.createElement('div');
|
||||
footerNode.classList.add('footer-node');
|
||||
this.compositeNode.appendChild(footerNode);
|
||||
this.footerRoot = createRoot(footerNode);
|
||||
this.node.appendChild(this.compositeNode);
|
||||
this.title.closable = false;
|
||||
}
|
||||
|
||||
abstract get treeWidget(): TW;
|
||||
protected abstract renderFooter(footerNode: HTMLElement): void;
|
||||
protected abstract renderFooter(footerRoot: Root): void;
|
||||
protected updateFooter(): void {
|
||||
this.renderFooter(this.footerNode);
|
||||
this.renderFooter(this.footerRoot);
|
||||
}
|
||||
|
||||
protected override onAfterAttach(message: Message): void {
|
||||
super.onAfterAttach(message);
|
||||
Widget.attach(this.treeWidget, this.compositeNode);
|
||||
this.renderFooter(this.footerNode);
|
||||
this.renderFooter(this.footerRoot);
|
||||
this.toDisposeOnDetach.push(
|
||||
Disposable.create(() => Widget.detach(this.treeWidget))
|
||||
);
|
||||
@@ -77,13 +78,12 @@ export class SketchbookCompositeWidget extends BaseSketchbookCompositeWidget<Ske
|
||||
return this.sketchbookTreeWidget;
|
||||
}
|
||||
|
||||
protected renderFooter(footerNode: HTMLElement): void {
|
||||
ReactDOM.render(
|
||||
protected renderFooter(footerRoot: Root): void {
|
||||
footerRoot.render(
|
||||
<CreateNew
|
||||
label={nls.localize('arduino/sketchbook/newSketch', 'New Sketch')}
|
||||
onClick={this.onDidClickCreateNew}
|
||||
/>,
|
||||
footerNode
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -53,10 +53,28 @@ export class SketchbookWidget extends BaseWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The currently selected sketchbook tree widget inside the view.
|
||||
*/
|
||||
getTreeWidget(): SketchbookTreeWidget {
|
||||
return this.sketchbookCompositeWidget.treeWidget;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of all sketchbook tree widgets managed by the view.
|
||||
*/
|
||||
getTreeWidgets(): SketchbookTreeWidget[] {
|
||||
return toArray(this.sketchbookTreesContainer.widgets()).reduce(
|
||||
(acc, curr) => {
|
||||
if (curr instanceof BaseSketchbookCompositeWidget) {
|
||||
acc.push(curr.treeWidget);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[] as SketchbookTreeWidget[]
|
||||
);
|
||||
}
|
||||
|
||||
activeTreeWidgetId(): string | undefined {
|
||||
const selectedTreeWidgets = toArray(
|
||||
this.sketchbookTreesContainer.selectedWidgets()
|
||||
|
@@ -1,23 +1,25 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import { isOSX } from '@theia/core/lib/common/os';
|
||||
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import {
|
||||
ActionMenuNode,
|
||||
CompositeMenuNode,
|
||||
CommandMenuNode,
|
||||
CompoundMenuNode,
|
||||
CompoundMenuNodeRole,
|
||||
MAIN_MENU_BAR,
|
||||
MenuNode,
|
||||
MenuPath,
|
||||
} from '@theia/core/lib/common/menu';
|
||||
import { isOSX } from '@theia/core/lib/common/os';
|
||||
import {
|
||||
ElectronMainMenuFactory as TheiaElectronMainMenuFactory,
|
||||
ElectronMenuItemRole,
|
||||
ElectronMenuOptions,
|
||||
} from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
ArduinoMenus,
|
||||
PlaceholderMenuNode,
|
||||
} from '../../../browser/menu/arduino-menus';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
|
||||
@injectable()
|
||||
export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
@@ -40,7 +42,9 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
override createElectronMenuBar(): Electron.Menu {
|
||||
this._toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977
|
||||
const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR);
|
||||
const template = this.fillMenuTemplate([], menuModel);
|
||||
const template = this.fillMenuTemplate([], menuModel, [], {
|
||||
rootMenuPath: MAIN_MENU_BAR,
|
||||
});
|
||||
if (isOSX) {
|
||||
template.unshift(this.createOSXMenu());
|
||||
}
|
||||
@@ -68,11 +72,15 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
|
||||
override createElectronContextMenu(
|
||||
menuPath: MenuPath,
|
||||
args?: any[]
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args?: any[],
|
||||
context?: HTMLElement
|
||||
): Electron.Menu {
|
||||
const menuModel = this.menuProvider.getMenu(menuPath);
|
||||
const template = this.fillMenuTemplate([], menuModel, args, {
|
||||
showDisabled: false,
|
||||
context,
|
||||
rootMenuPath: menuPath,
|
||||
});
|
||||
return remote.Menu.buildFromTemplate(this.escapeAmpersand(template));
|
||||
}
|
||||
@@ -96,20 +104,26 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
|
||||
protected override createOSXMenu(): Electron.MenuItemConstructorOptions {
|
||||
const { submenu } = super.createOSXMenu();
|
||||
const label = 'Arduino IDE';
|
||||
const label = FrontendApplicationConfigProvider.get().applicationName;
|
||||
if (!!submenu && Array.isArray(submenu)) {
|
||||
const [, , /* about */ /* preferences */ ...rest] = submenu;
|
||||
const about = this.fillMenuTemplate(
|
||||
[],
|
||||
this.menuProvider.getMenu(ArduinoMenus.HELP__ABOUT_GROUP)
|
||||
this.menuProvider.getMenu(ArduinoMenus.HELP__ABOUT_GROUP),
|
||||
[],
|
||||
{ rootMenuPath: ArduinoMenus.HELP__ABOUT_GROUP }
|
||||
);
|
||||
const preferences = this.fillMenuTemplate(
|
||||
[],
|
||||
this.menuProvider.getMenu(ArduinoMenus.FILE__PREFERENCES_GROUP)
|
||||
this.menuProvider.getMenu(ArduinoMenus.FILE__PREFERENCES_GROUP),
|
||||
[],
|
||||
{ rootMenuPath: ArduinoMenus.FILE__PREFERENCES_GROUP }
|
||||
);
|
||||
const advanced = this.fillMenuTemplate(
|
||||
[],
|
||||
this.menuProvider.getMenu(ArduinoMenus.FILE__ADVANCED_GROUP)
|
||||
this.menuProvider.getMenu(ArduinoMenus.FILE__ADVANCED_GROUP),
|
||||
[],
|
||||
{ rootMenuPath: ArduinoMenus.FILE__ADVANCED_GROUP }
|
||||
);
|
||||
return {
|
||||
label,
|
||||
@@ -126,7 +140,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
return { label, submenu };
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
|
||||
protected override roleFor(id: string): ElectronMenuItemRole | undefined {
|
||||
// MenuItem `roles` are completely broken on macOS:
|
||||
// - https://github.com/eclipse-theia/theia/issues/11217,
|
||||
@@ -135,135 +149,133 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected override handleElectronDefault(
|
||||
menuNode: MenuNode,
|
||||
args: any[] = [],
|
||||
options?: ElectronMenuOptions
|
||||
protected override fillMenuTemplate(
|
||||
parentItems: Electron.MenuItemConstructorOptions[],
|
||||
menuModel: MenuNode,
|
||||
args: unknown[] | undefined,
|
||||
options: ElectronMenuOptions
|
||||
): Electron.MenuItemConstructorOptions[] {
|
||||
if (menuNode instanceof PlaceholderMenuNode) {
|
||||
return [
|
||||
{
|
||||
label: menuNode.label,
|
||||
enabled: false,
|
||||
visible: true,
|
||||
},
|
||||
];
|
||||
if (menuModel instanceof PlaceholderMenuNode) {
|
||||
parentItems.push({
|
||||
label: menuModel.label,
|
||||
enabled: false,
|
||||
visible: true,
|
||||
});
|
||||
} else {
|
||||
this.superFillMenuTemplate(parentItems, menuModel, args, options);
|
||||
}
|
||||
return [];
|
||||
return parentItems;
|
||||
}
|
||||
|
||||
// Copied from 1.25.0 Theia as is to customize the enablement of the menu items.
|
||||
// Source: https://github.com/eclipse-theia/theia/blob/ca417a31e402bd35717d3314bf6254049d1dae44/packages/core/src/electron-browser/menu/electron-main-menu-factory.ts#L125-L220
|
||||
// Copied from 1.31.1 Theia as is to customize the enablement of the menu items.
|
||||
// Source: https://github.com/eclipse-theia/theia/blob/5e641750af83383f2ce0cb3432ec333df70778a8/packages/core/src/electron-browser/menu/electron-main-menu-factory.ts#L132-L203
|
||||
// See https://github.com/arduino/arduino-ide/issues/1533
|
||||
protected override fillMenuTemplate(
|
||||
items: Electron.MenuItemConstructorOptions[],
|
||||
menuModel: CompositeMenuNode,
|
||||
args: any[] = [],
|
||||
options?: ElectronMenuOptions
|
||||
private superFillMenuTemplate(
|
||||
parentItems: Electron.MenuItemConstructorOptions[],
|
||||
menu: MenuNode,
|
||||
args: unknown[] = [],
|
||||
options: ElectronMenuOptions
|
||||
): Electron.MenuItemConstructorOptions[] {
|
||||
const showDisabled =
|
||||
options?.showDisabled === undefined ? true : options?.showDisabled;
|
||||
for (const menu of menuModel.children) {
|
||||
if (menu instanceof CompositeMenuNode) {
|
||||
if (menu.children.length > 0) {
|
||||
// do not render empty nodes
|
||||
|
||||
if (menu.isSubmenu) {
|
||||
// submenu node
|
||||
|
||||
const submenu = this.fillMenuTemplate([], menu, args, options);
|
||||
if (submenu.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
items.push({
|
||||
label: menu.label,
|
||||
submenu,
|
||||
});
|
||||
} else {
|
||||
// group node
|
||||
|
||||
// process children
|
||||
const submenu = this.fillMenuTemplate([], menu, args, options);
|
||||
if (submenu.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (items.length > 0) {
|
||||
// do not put a separator above the first group
|
||||
|
||||
items.push({
|
||||
type: 'separator',
|
||||
});
|
||||
}
|
||||
|
||||
// render children
|
||||
items.push(...submenu);
|
||||
}
|
||||
}
|
||||
} else if (menu instanceof ActionMenuNode) {
|
||||
const node =
|
||||
menu.altNode && this.context.altPressed ? menu.altNode : menu;
|
||||
const commandId = node.action.commandId;
|
||||
|
||||
// That is only a sanity check at application startup.
|
||||
if (!this.commandRegistry.getCommand(commandId)) {
|
||||
console.debug(
|
||||
`Skipping menu item with missing command: "${commandId}".`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const showDisabled = options?.showDisabled !== false;
|
||||
|
||||
if (
|
||||
CompoundMenuNode.is(menu) &&
|
||||
menu.children.length &&
|
||||
this.undefinedOrMatch(menu.when, options.context)
|
||||
) {
|
||||
const role = CompoundMenuNode.getRole(menu);
|
||||
if (role === CompoundMenuNodeRole.Group && menu.id === 'inline') {
|
||||
return parentItems;
|
||||
}
|
||||
const children = CompoundMenuNode.getFlatChildren(menu.children);
|
||||
const myItems: Electron.MenuItemConstructorOptions[] = [];
|
||||
children.forEach((child) =>
|
||||
this.fillMenuTemplate(myItems, child, args, options)
|
||||
);
|
||||
if (myItems.length === 0) {
|
||||
return parentItems;
|
||||
}
|
||||
if (role === CompoundMenuNodeRole.Submenu) {
|
||||
parentItems.push({ label: menu.label, submenu: myItems });
|
||||
} else if (role === CompoundMenuNodeRole.Group && menu.id !== 'inline') {
|
||||
if (
|
||||
!this.commandRegistry.isVisible(commandId, ...args) ||
|
||||
(!!node.action.when &&
|
||||
!this.contextKeyService.match(node.action.when))
|
||||
parentItems.length &&
|
||||
parentItems[parentItems.length - 1].type !== 'separator'
|
||||
) {
|
||||
continue;
|
||||
parentItems.push({ type: 'separator' });
|
||||
}
|
||||
parentItems.push(...myItems);
|
||||
parentItems.push({ type: 'separator' });
|
||||
}
|
||||
} else if (menu.command) {
|
||||
const node =
|
||||
menu.altNode && this.context.altPressed
|
||||
? menu.altNode
|
||||
: (menu as MenuNode & CommandMenuNode);
|
||||
const commandId = node.command;
|
||||
|
||||
// We should omit rendering context-menu items which are disabled.
|
||||
if (
|
||||
!showDisabled &&
|
||||
!this.commandRegistry.isEnabled(commandId, ...args)
|
||||
) {
|
||||
continue;
|
||||
// That is only a sanity check at application startup.
|
||||
if (!this.commandRegistry.getCommand(commandId)) {
|
||||
console.debug(
|
||||
`Skipping menu item with missing command: "${commandId}".`
|
||||
);
|
||||
return parentItems;
|
||||
}
|
||||
|
||||
if (
|
||||
!this.menuCommandExecutor.isVisible(
|
||||
options.rootMenuPath,
|
||||
commandId,
|
||||
...args
|
||||
) ||
|
||||
!this.undefinedOrMatch(node.when, options.context)
|
||||
) {
|
||||
return parentItems;
|
||||
}
|
||||
|
||||
// We should omit rendering context-menu items which are disabled.
|
||||
if (
|
||||
!showDisabled &&
|
||||
!this.menuCommandExecutor.isEnabled(
|
||||
options.rootMenuPath,
|
||||
commandId,
|
||||
...args
|
||||
)
|
||||
) {
|
||||
return parentItems;
|
||||
}
|
||||
|
||||
const bindings =
|
||||
this.keybindingRegistry.getKeybindingsForCommand(commandId);
|
||||
|
||||
const accelerator = bindings[0] && this.acceleratorFor(bindings[0]);
|
||||
|
||||
const menuItem: Electron.MenuItemConstructorOptions = {
|
||||
id: node.id,
|
||||
label: node.label,
|
||||
type: this.commandRegistry.getToggledHandler(commandId, ...args)
|
||||
? 'checkbox'
|
||||
: 'normal',
|
||||
checked: this.commandRegistry.isToggled(commandId, ...args),
|
||||
enabled: this.commandRegistry.isEnabled(commandId, ...args), // Unlike Theia https://github.com/eclipse-theia/theia/blob/v1.31.1/packages/core/src/electron-browser/menu/electron-main-menu-factory.ts#L183
|
||||
visible: true,
|
||||
accelerator,
|
||||
click: () => this.execute(commandId, args, options.rootMenuPath),
|
||||
};
|
||||
|
||||
if (isOSX) {
|
||||
const role = this.roleFor(node.id);
|
||||
if (role) {
|
||||
menuItem.role = role;
|
||||
delete menuItem.click;
|
||||
}
|
||||
}
|
||||
parentItems.push(menuItem);
|
||||
|
||||
const bindings =
|
||||
this.keybindingRegistry.getKeybindingsForCommand(commandId);
|
||||
|
||||
const accelerator = bindings[0] && this.acceleratorFor(bindings[0]);
|
||||
|
||||
const menuItem: Electron.MenuItemConstructorOptions = {
|
||||
id: node.id,
|
||||
label: node.label,
|
||||
type: this.commandRegistry.getToggledHandler(commandId, ...args)
|
||||
? 'checkbox'
|
||||
: 'normal',
|
||||
checked: this.commandRegistry.isToggled(commandId, ...args),
|
||||
enabled: this.commandRegistry.isEnabled(commandId, ...args), // Unlike Theia https://github.com/eclipse-theia/theia/blob/ca417a31e402bd35717d3314bf6254049d1dae44/packages/core/src/electron-browser/menu/electron-main-menu-factory.ts#L197
|
||||
visible: true,
|
||||
accelerator,
|
||||
click: () => this.execute(commandId, args),
|
||||
};
|
||||
|
||||
if (isOSX) {
|
||||
const role = this.roleFor(node.id);
|
||||
if (role) {
|
||||
menuItem.role = role;
|
||||
delete menuItem.click;
|
||||
}
|
||||
}
|
||||
items.push(menuItem);
|
||||
|
||||
if (this.commandRegistry.getToggledHandler(commandId, ...args)) {
|
||||
this._toggledCommands.add(commandId);
|
||||
}
|
||||
} else {
|
||||
items.push(...this.handleElectronDefault(menu, args, options));
|
||||
if (this.commandRegistry.getToggledHandler(commandId, ...args)) {
|
||||
this._toggledCommands.add(commandId);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
return parentItems;
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import {
|
||||
ElectronMainApplication as TheiaElectronMainApplication,
|
||||
ElectronMainApplicationContribution,
|
||||
} from '@theia/core/lib/electron-main/electron-main-application';
|
||||
import { ElectronMessagingContribution as TheiaElectronMessagingContribution } from '@theia/core/lib/electron-main/messaging/electron-messaging-contribution';
|
||||
import { TheiaElectronWindow as DefaultTheiaElectronWindow } from '@theia/core/lib/electron-main/theia-electron-window';
|
||||
import { ContainerModule } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
@@ -17,8 +18,8 @@ import { IsTempSketch } from '../node/is-temp-sketch';
|
||||
import { IDEUpdaterImpl } from './ide-updater/ide-updater-impl';
|
||||
import { ElectronMainApplication } from './theia/electron-main-application';
|
||||
import { ElectronMainWindowServiceImpl } from './theia/electron-main-window-service';
|
||||
import { ElectronMessagingContribution } from './theia/electron-messaging-contribution';
|
||||
import { TheiaElectronWindow } from './theia/theia-electron-window';
|
||||
import { ElectronNativeKeymap } from '@theia/core/lib/electron-main/electron-native-keymap';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(ElectronMainApplication).toSelf().inSingletonScope();
|
||||
@@ -60,7 +61,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
|
||||
bind(IsTempSketch).toSelf().inSingletonScope();
|
||||
|
||||
// https://github.com/eclipse-theia/theia/issues/11688
|
||||
bind(ElectronNativeKeymap).toSelf().inSingletonScope();
|
||||
bind(ElectronMainApplicationContribution).toService(ElectronNativeKeymap);
|
||||
// Fix for cannot reload window: https://github.com/eclipse-theia/theia/issues/11600
|
||||
bind(ElectronMessagingContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaElectronMessagingContribution).toService(
|
||||
ElectronMessagingContribution
|
||||
);
|
||||
});
|
||||
|
@@ -0,0 +1,44 @@
|
||||
import { ChannelMultiplexer } from '@theia/core/lib/common/message-rpc/channel';
|
||||
import {
|
||||
ElectronMessagingContribution as TheiaElectronMessagingContribution,
|
||||
ElectronWebContentChannel,
|
||||
} from '@theia/core/lib/electron-main/messaging/electron-messaging-contribution';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
|
||||
// Electron window cannot reload: https://github.com/eclipse-theia/theia/issues/11600
|
||||
// This patch fixes it by removing the channel multiplexer from the cache.
|
||||
// A related PR in Theia: https://github.com/eclipse-theia/theia/pull/11810
|
||||
@injectable()
|
||||
export class ElectronMessagingContribution extends TheiaElectronMessagingContribution {
|
||||
// Based on: https://github.com/kittaakos/theia/commit/12dd318df589f1c48de2b58545912d8385919b22
|
||||
protected override createWindowChannelData(sender: Electron.WebContents): {
|
||||
channel: ElectronWebContentChannel;
|
||||
multiplexer: ChannelMultiplexer;
|
||||
} {
|
||||
const mainChannel = this.createWindowMainChannel(sender);
|
||||
const multiplexer = new ChannelMultiplexer(mainChannel);
|
||||
multiplexer.onDidOpenChannel((openEvent) => {
|
||||
const { channel, id } = openEvent;
|
||||
if (this.channelHandlers.route(id, channel)) {
|
||||
console.debug(`Opening channel for service path '${id}'.`);
|
||||
channel.onClose(() =>
|
||||
console.debug(`Closing channel on service path '${id}'.`)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// When refreshing the browser window.
|
||||
sender.once('did-navigate', () => {
|
||||
multiplexer.onUnderlyingChannelClose({ reason: 'Window was refreshed' });
|
||||
this.windowChannelMultiplexer.delete(sender.id);
|
||||
});
|
||||
// When closing the browser window.
|
||||
sender.once('destroyed', () => {
|
||||
multiplexer.onUnderlyingChannelClose({ reason: 'Window was closed' });
|
||||
this.windowChannelMultiplexer.delete(sender.id);
|
||||
});
|
||||
const data = { channel: mainChannel, multiplexer };
|
||||
this.windowChannelMultiplexer.set(sender.id, data);
|
||||
return data;
|
||||
}
|
||||
}
|
@@ -1,46 +1,16 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { ipcMain, IpcMainEvent } from '@theia/electron/shared/electron';
|
||||
import {
|
||||
RELOAD_REQUESTED_SIGNAL,
|
||||
StopReason,
|
||||
} from '@theia/core/lib/electron-common/messaging/electron-messages';
|
||||
import { TheiaElectronWindow as DefaultTheiaElectronWindow } from '@theia/core/lib/electron-main/theia-electron-window';
|
||||
import { FileUri } from '@theia/core/lib/node';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { createDisposableListener } from '@theia/core/lib/electron-main/event-utils';
|
||||
import { TheiaElectronWindow as DefaultTheiaElectronWindow } from '@theia/core/lib/electron-main/theia-electron-window';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { ipcMain, IpcMainEvent } from '@theia/electron/shared/electron';
|
||||
import { StartupTask } from '../../electron-common/startup-task';
|
||||
import { load } from './window';
|
||||
|
||||
@injectable()
|
||||
export class TheiaElectronWindow extends DefaultTheiaElectronWindow {
|
||||
protected override async handleStopRequest(
|
||||
onSafeCallback: () => unknown,
|
||||
reason: StopReason
|
||||
): Promise<boolean> {
|
||||
// Only confirm close to windows that have loaded our frontend.
|
||||
// Both the windows's URL and the FS path of the `index.html` should be converted to the "same" format to be able to compare them. (#11226)
|
||||
// Notes:
|
||||
// - Windows: file:///C:/path/to/somewhere vs file:///c%3A/path/to/somewhere
|
||||
// - macOS: file:///Applications/App%20Name.app/Contents vs /Applications/App Name.app/Contents
|
||||
// This URL string comes from electron, we can expect that this is properly encoded URL. For example, a space is `%20`
|
||||
const currentUrl = new URI(this.window.webContents.getURL()).toString();
|
||||
// THEIA_FRONTEND_HTML_PATH is an FS path, we have to covert to an encoded URI string.
|
||||
const frontendUri = FileUri.create(
|
||||
this.globals.THEIA_FRONTEND_HTML_PATH
|
||||
).toString();
|
||||
const safeToClose =
|
||||
!currentUrl.includes(frontendUri) || (await this.checkSafeToStop(reason));
|
||||
if (safeToClose) {
|
||||
try {
|
||||
await onSafeCallback();
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.warn(`Request ${StopReason[reason]} failed.`, e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override reload(tasks?: StartupTask[]): void {
|
||||
this.handleStopRequest(() => {
|
||||
this.applicationState = 'init';
|
||||
|
@@ -100,8 +100,8 @@ import WebSocketProviderImpl from './web-socket/web-socket-provider-impl';
|
||||
import { WebSocketProvider } from './web-socket/web-socket-provider';
|
||||
import { ClangFormatter } from './clang-formatter';
|
||||
import { FormatterPath } from '../common/protocol/formatter';
|
||||
import { LocalizationBackendContribution } from './i18n/localization-backend-contribution';
|
||||
import { LocalizationBackendContribution as TheiaLocalizationBackendContribution } from '@theia/core/lib/node/i18n/localization-backend-contribution';
|
||||
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,
|
||||
@@ -109,6 +109,10 @@ import {
|
||||
} from '../common/protocol/survey-service';
|
||||
import { IsTempSketch } from './is-temp-sketch';
|
||||
import { rebindNsfwFileSystemWatcher } from './theia/filesystem/nsfw-watcher/nsfw-bindings';
|
||||
import { MessagingContribution } from './theia/core/messaging-contribution';
|
||||
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';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(BackendApplication).toSelf().inSingletonScope();
|
||||
@@ -360,9 +364,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(BackendApplicationContribution).toService(PlotterBackendContribution);
|
||||
bind(ArduinoLocalizationContribution).toSelf().inSingletonScope();
|
||||
bind(LocalizationContribution).toService(ArduinoLocalizationContribution);
|
||||
bind(LocalizationBackendContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaLocalizationBackendContribution).toService(
|
||||
LocalizationBackendContribution
|
||||
bind(HostedPluginLocalizationService).toSelf().inSingletonScope();
|
||||
rebind(TheiaHostedPluginLocalizationService).toService(
|
||||
HostedPluginLocalizationService
|
||||
);
|
||||
|
||||
// Survey notification bindings
|
||||
@@ -379,6 +383,15 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
.inSingletonScope();
|
||||
|
||||
bind(IsTempSketch).toSelf().inSingletonScope();
|
||||
rebind(MessagingService.Identifier)
|
||||
.to(MessagingContribution)
|
||||
.inSingletonScope();
|
||||
|
||||
// Removed undesired contributions from VS Code extensions
|
||||
// Such as the RTOS view from the `cortex-debug` extension
|
||||
// https://github.com/arduino/arduino-ide/pull/1706#pullrequestreview-1195595080
|
||||
bind(HostedPluginReader).toSelf().inSingletonScope();
|
||||
rebind(TheiaHostedPluginReader).toService(HostedPluginReader);
|
||||
});
|
||||
|
||||
function bindChildLogger(bind: interfaces.Bind, name: string): void {
|
||||
|
@@ -1,45 +0,0 @@
|
||||
import * as express from 'express';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { LocalizationBackendContribution as TheiaLocalizationBackendContribution } from '@theia/core/lib/node/i18n/localization-backend-contribution';
|
||||
import { PluginDeployer } from '@theia/plugin-ext/lib/common/plugin-protocol';
|
||||
import { PluginDeployerImpl } from '@theia/plugin-ext/lib/main/node/plugin-deployer-impl';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
|
||||
@injectable()
|
||||
export class LocalizationBackendContribution extends TheiaLocalizationBackendContribution {
|
||||
@inject(PluginDeployer)
|
||||
private readonly pluginDeployer: PluginDeployerImpl;
|
||||
|
||||
private readonly initialized = new Deferred<void>();
|
||||
|
||||
override async initialize(): Promise<void> {
|
||||
this.pluginDeployer.onDidDeploy(() => {
|
||||
this.initialized.resolve();
|
||||
});
|
||||
return super.initialize();
|
||||
}
|
||||
|
||||
override configure(app: express.Application): void {
|
||||
app.get('/i18n/:locale', async (req, res) => {
|
||||
let locale = req.params.locale;
|
||||
/*
|
||||
Waiting for the deploy of the language plugins is necessary to avoid checking the available
|
||||
languages before they're finished to be loaded: https://github.com/eclipse-theia/theia/issues/11471
|
||||
*/
|
||||
const start = performance.now();
|
||||
await this.initialized.promise;
|
||||
console.info(
|
||||
'Waiting for the deploy of the language plugins took: ' +
|
||||
(performance.now() - start) +
|
||||
' ms.'
|
||||
);
|
||||
locale = this.localizationProvider
|
||||
.getAvailableLanguages()
|
||||
.some((e) => e.languageId === locale)
|
||||
? locale
|
||||
: 'en';
|
||||
this.localizationProvider.setCurrentLanguage(locale);
|
||||
res.send(this.localizationProvider.loadLocalization(locale));
|
||||
});
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
import { ClientDuplexStream } from '@grpc/grpc-js';
|
||||
import { Disposable, Emitter, ILogger } from '@theia/core';
|
||||
import { inject, named, postConstruct } from '@theia/core/shared/inversify';
|
||||
import { diff, Operation } from 'just-diff';
|
||||
import { Board, Port, Status, Monitor } from '../common/protocol';
|
||||
import {
|
||||
EnumerateMonitorPortSettingsRequest,
|
||||
@@ -12,7 +13,7 @@ import {
|
||||
} from './cli-protocol/cc/arduino/cli/commands/v1/monitor_pb';
|
||||
import { CoreClientAware } from './core-client-provider';
|
||||
import { WebSocketProvider } from './web-socket/web-socket-provider';
|
||||
import { Port as RpcPort } from 'arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/port_pb';
|
||||
import { Port as RpcPort } from './cli-protocol/cc/arduino/cli/commands/v1/port_pb';
|
||||
import {
|
||||
MonitorSettings,
|
||||
PluggableMonitorSettings,
|
||||
@@ -80,6 +81,15 @@ export class MonitorService extends CoreClientAware implements Disposable {
|
||||
private readonly port: Port;
|
||||
private readonly monitorID: string;
|
||||
|
||||
/**
|
||||
* The lightweight representation of the port configuration currently in use for the running monitor.
|
||||
* IDE2 stores this object after starting the monitor. On every monitor settings change request, IDE2 compares
|
||||
* the current config with the new settings, and only sends the diff as the new config to overcome https://github.com/arduino/arduino-ide/issues/375.
|
||||
*/
|
||||
private currentPortConfigSnapshot:
|
||||
| MonitorPortConfiguration.AsObject
|
||||
| undefined;
|
||||
|
||||
constructor(
|
||||
@inject(MonitorServiceFactoryOptions) options: MonitorServiceFactoryOptions
|
||||
) {
|
||||
@@ -211,6 +221,16 @@ export class MonitorService extends CoreClientAware implements Disposable {
|
||||
monitorRequest
|
||||
);
|
||||
if (wroteToStreamSuccessfully) {
|
||||
// Only store the config, if the monitor has successfully started.
|
||||
this.currentPortConfigSnapshot = MonitorPortConfiguration.toObject(
|
||||
false,
|
||||
config
|
||||
);
|
||||
this.logger.info(
|
||||
`Using port configuration for ${this.port.protocol}:${
|
||||
this.port.address
|
||||
}: ${JSON.stringify(this.currentPortConfigSnapshot)}`
|
||||
);
|
||||
this.startMessagesHandlers();
|
||||
this.logger.info(
|
||||
`started monitor to ${this.port?.address} using ${this.port?.protocol}`
|
||||
@@ -518,16 +538,120 @@ export class MonitorService extends CoreClientAware implements Disposable {
|
||||
if (!this.duplex) {
|
||||
return Status.NOT_CONNECTED;
|
||||
}
|
||||
|
||||
const diffConfig = this.maybeUpdatePortConfigSnapshot(config);
|
||||
if (!diffConfig) {
|
||||
this.logger.info(
|
||||
`No port configuration changes have been detected. No need to send configure commands to the running monitor ${this.port.protocol}:${this.port.address}.`
|
||||
);
|
||||
return Status.OK;
|
||||
}
|
||||
|
||||
const coreClient = await this.coreClient;
|
||||
const { instance } = coreClient;
|
||||
|
||||
this.logger.info(
|
||||
`Sending monitor request with new port configuration: ${JSON.stringify(
|
||||
MonitorPortConfiguration.toObject(false, diffConfig)
|
||||
)}`
|
||||
);
|
||||
const req = new MonitorRequest();
|
||||
req.setInstance(instance);
|
||||
req.setPortConfiguration(config);
|
||||
req.setPortConfiguration(diffConfig);
|
||||
this.duplex.write(req);
|
||||
return Status.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to calculate a diff between the `otherPortConfig` argument and the `currentPortConfigSnapshot`.
|
||||
*
|
||||
* If the current config snapshot and the snapshot derived from `otherPortConfig` are the same, no snapshot update happens,
|
||||
* and the function returns with undefined. Otherwise, the current snapshot config value will be updated from the snapshot
|
||||
* derived from the `otherPortConfig` argument, and this function returns with a `MonitorPortConfiguration` instance
|
||||
* representing only the difference between the two snapshot configs to avoid sending unnecessary monitor to configure commands to the CLI.
|
||||
* See [#1703 (comment)](https://github.com/arduino/arduino-ide/pull/1703#issuecomment-1327913005) for more details.
|
||||
*/
|
||||
private maybeUpdatePortConfigSnapshot(
|
||||
otherPortConfig: MonitorPortConfiguration
|
||||
): MonitorPortConfiguration | undefined {
|
||||
const otherPortConfigSnapshot = MonitorPortConfiguration.toObject(
|
||||
false,
|
||||
otherPortConfig
|
||||
);
|
||||
if (!this.currentPortConfigSnapshot) {
|
||||
throw new Error(
|
||||
`The current port configuration object was undefined when tried to merge in ${JSON.stringify(
|
||||
otherPortConfigSnapshot
|
||||
)}.`
|
||||
);
|
||||
}
|
||||
|
||||
const snapshotDiff = diff(
|
||||
this.currentPortConfigSnapshot,
|
||||
otherPortConfigSnapshot
|
||||
);
|
||||
if (!snapshotDiff.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const diffConfig = snapshotDiff.reduce((acc, curr) => {
|
||||
if (!this.isValidMonitorPortSettingChange(curr)) {
|
||||
throw new Error(
|
||||
`Expected only 'replace' operation: a 'value' change in the 'settingsList'. Calculated diff a ${JSON.stringify(
|
||||
snapshotDiff
|
||||
)} between ${JSON.stringify(
|
||||
this.currentPortConfigSnapshot
|
||||
)} and ${JSON.stringify(
|
||||
otherPortConfigSnapshot
|
||||
)} snapshots. Current JSON-patch entry was ${JSON.stringify(curr)}.`
|
||||
);
|
||||
}
|
||||
const { path, value } = curr;
|
||||
const [, index] = path;
|
||||
if (!this.currentPortConfigSnapshot?.settingsList) {
|
||||
throw new Error(
|
||||
`'settingsList' is missing from current port config snapshot: ${JSON.stringify(
|
||||
this.currentPortConfigSnapshot
|
||||
)}`
|
||||
);
|
||||
}
|
||||
const changedSetting = this.currentPortConfigSnapshot.settingsList[index];
|
||||
const setting = new MonitorPortSetting();
|
||||
setting.setValue(value);
|
||||
setting.setSettingId(changedSetting.settingId);
|
||||
acc.addSettings(setting);
|
||||
return acc;
|
||||
}, new MonitorPortConfiguration());
|
||||
|
||||
this.currentPortConfigSnapshot = otherPortConfigSnapshot;
|
||||
this.logger.info(
|
||||
`Updated the port configuration for ${this.port.protocol}:${
|
||||
this.port.address
|
||||
}: ${JSON.stringify(this.currentPortConfigSnapshot)}`
|
||||
);
|
||||
return diffConfig;
|
||||
}
|
||||
|
||||
private isValidMonitorPortSettingChange(entry: {
|
||||
op: Operation;
|
||||
path: (string | number)[];
|
||||
value: unknown;
|
||||
}): entry is {
|
||||
op: 'replace';
|
||||
path: ['settingsList', number, string];
|
||||
value: string;
|
||||
} {
|
||||
const { op, path, value } = entry;
|
||||
return (
|
||||
op === 'replace' &&
|
||||
path.length === 3 &&
|
||||
path[0] === 'settingsList' &&
|
||||
typeof path[1] === 'number' &&
|
||||
path[2] === 'value' &&
|
||||
typeof value === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the necessary handlers to send and receive
|
||||
* messages to and from the frontend and the running monitor
|
||||
|
@@ -1,6 +1,10 @@
|
||||
import * as fs from 'fs';
|
||||
import { join } from 'path';
|
||||
import { injectable, inject, postConstruct } from 'inversify';
|
||||
import {
|
||||
injectable,
|
||||
inject,
|
||||
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 { promisify } from 'util';
|
||||
@@ -95,7 +99,7 @@ export class MonitorSettingsProviderImpl implements MonitorSettingsProvider {
|
||||
const rawJson = await promisify(fs.readFile)(
|
||||
this.pluggableMonitorSettingsPath,
|
||||
{
|
||||
encoding: 'utf-8',
|
||||
encoding: 'utf8',
|
||||
flag: 'a+', // a+ = append and read, creating the file if it doesn't exist
|
||||
}
|
||||
);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as path from 'path';
|
||||
import * as express from 'express';
|
||||
import * as express from '@theia/core/shared/express';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
|
||||
|
||||
|
@@ -0,0 +1,11 @@
|
||||
import { MessagingContribution as TheiaMessagingContribution } from '@theia/core/lib/node/messaging/messaging-contribution';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
@injectable()
|
||||
export class MessagingContribution extends TheiaMessagingContribution {
|
||||
// https://github.com/eclipse-theia/theia/discussions/11543
|
||||
protected override checkAliveTimeout = process.argv.includes(
|
||||
'--no-ping-timeout'
|
||||
)
|
||||
? 24 * 60 * 60 * 1_000 // one day
|
||||
: 30_000;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
import * as fs from '@theia/core/shared/fs-extra';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { HostedPluginLocalizationService as TheiaHostedPluginLocalizationService } from '@theia/plugin-ext/lib/hosted/node/hosted-plugin-localization-service';
|
||||
|
||||
@injectable()
|
||||
export class HostedPluginLocalizationService extends TheiaHostedPluginLocalizationService {
|
||||
// Remove when https://github.com/eclipse-theia/theia/pull/11853 is available from Theia.
|
||||
override async initialize(): Promise<void> {
|
||||
this.getLocalizationCacheDir()
|
||||
.then((cacheDir) => fs.emptyDir(cacheDir))
|
||||
.then(() => this._ready.resolve());
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import type {
|
||||
PluginContribution,
|
||||
PluginPackage,
|
||||
} from '@theia/plugin-ext/lib/common/plugin-protocol';
|
||||
import { HostedPluginReader as TheiaHostedPluginReader } from '@theia/plugin-ext/lib/hosted/node/plugin-reader';
|
||||
|
||||
@injectable()
|
||||
export class HostedPluginReader extends TheiaHostedPluginReader {
|
||||
override readContribution(
|
||||
plugin: PluginPackage
|
||||
): PluginContribution | undefined {
|
||||
const scanner = this.scanner.getScanner(plugin);
|
||||
const contributions = scanner.getContribution(plugin);
|
||||
return this.filterContribution(plugin.name, contributions);
|
||||
}
|
||||
private filterContribution(
|
||||
pluginName: string,
|
||||
contributions: PluginContribution | undefined
|
||||
): PluginContribution | undefined {
|
||||
if (!contributions) {
|
||||
return contributions;
|
||||
}
|
||||
const filter = pluginFilters.get(pluginName);
|
||||
return filter ? filter(contributions) : contributions;
|
||||
}
|
||||
}
|
||||
|
||||
type PluginContributionFilter = (
|
||||
contribution: PluginContribution
|
||||
) => PluginContribution | undefined;
|
||||
const cortexDebugFilter: PluginContributionFilter = (
|
||||
contribution: PluginContribution
|
||||
) => {
|
||||
if (contribution.viewsContainers) {
|
||||
for (const location of Object.keys(contribution.viewsContainers)) {
|
||||
const viewContainers = contribution.viewsContainers[location];
|
||||
for (let i = 0; i < viewContainers.length; i++) {
|
||||
const viewContainer = viewContainers[i];
|
||||
if (
|
||||
viewContainer.id === 'cortex-debug' &&
|
||||
viewContainer.title === 'RTOS'
|
||||
) {
|
||||
viewContainers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (contribution.views) {
|
||||
for (const location of Object.keys(contribution.views)) {
|
||||
if (location === 'cortex-debug') {
|
||||
const views = contribution.views[location];
|
||||
for (let i = 0; i < views.length; i++) {
|
||||
const view = views[i];
|
||||
if (view.id === 'cortex-debug.rtos') {
|
||||
views.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (contribution.menus) {
|
||||
for (const location of Object.keys(contribution.menus)) {
|
||||
if (location === 'commandPalette') {
|
||||
const menus = contribution.menus[location];
|
||||
for (let i = 0; i < menus.length; i++) {
|
||||
const menu = menus[i];
|
||||
if (menu.command === 'cortex-debug.rtos.toggleRTOSPanel') {
|
||||
menu.when = 'false';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return contribution;
|
||||
};
|
||||
|
||||
const pluginFilters = new Map<string, PluginContributionFilter>([
|
||||
['cortex-debug', cortexDebugFilter],
|
||||
]);
|
@@ -71,7 +71,7 @@ namespace Chunks {
|
||||
if (current && current.buffers) {
|
||||
result.push([
|
||||
current.severity,
|
||||
Buffer.concat(current.buffers).toString('utf-8'),
|
||||
Buffer.concat(current.buffers).toString('utf8'),
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Emitter } from '@theia/core';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import * as WebSocket from 'ws';
|
||||
import * as WebSocket from '@theia/core/shared/ws';
|
||||
import { WebSocketProvider } from './web-socket-provider';
|
||||
|
||||
@injectable()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Event } from '@theia/core/lib/common/event';
|
||||
import * as WebSocket from 'ws';
|
||||
import * as WebSocket from '@theia/core/shared/ws';
|
||||
|
||||
export const WebSocketProvider = Symbol('WebSocketProvider');
|
||||
export interface WebSocketProvider {
|
||||
|
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"noImplicitAny": true,
|
||||
"noEmitOnError": true,
|
||||
"noImplicitThis": true,
|
||||
|
@@ -1,30 +1,30 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "electron-app",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"main": "src-gen/frontend/electron-main.js",
|
||||
"dependencies": {
|
||||
"@theia/core": "1.25.0",
|
||||
"@theia/debug": "1.25.0",
|
||||
"@theia/editor": "1.25.0",
|
||||
"@theia/electron": "1.25.0",
|
||||
"@theia/file-search": "1.25.0",
|
||||
"@theia/filesystem": "1.25.0",
|
||||
"@theia/keymaps": "1.25.0",
|
||||
"@theia/messages": "1.25.0",
|
||||
"@theia/monaco": "1.25.0",
|
||||
"@theia/navigator": "1.25.0",
|
||||
"@theia/plugin-ext": "1.25.0",
|
||||
"@theia/plugin-ext-vscode": "1.25.0",
|
||||
"@theia/preferences": "1.25.0",
|
||||
"@theia/process": "1.25.0",
|
||||
"@theia/terminal": "1.25.0",
|
||||
"@theia/workspace": "1.25.0",
|
||||
"arduino-ide-extension": "2.0.2"
|
||||
"@theia/core": "1.31.1",
|
||||
"@theia/debug": "1.31.1",
|
||||
"@theia/editor": "1.31.1",
|
||||
"@theia/electron": "1.31.1",
|
||||
"@theia/file-search": "1.31.1",
|
||||
"@theia/filesystem": "1.31.1",
|
||||
"@theia/keymaps": "1.31.1",
|
||||
"@theia/messages": "1.31.1",
|
||||
"@theia/monaco": "1.31.1",
|
||||
"@theia/navigator": "1.31.1",
|
||||
"@theia/plugin-ext": "1.31.1",
|
||||
"@theia/plugin-ext-vscode": "1.31.1",
|
||||
"@theia/preferences": "1.31.1",
|
||||
"@theia/process": "1.31.1",
|
||||
"@theia/terminal": "1.31.1",
|
||||
"@theia/workspace": "1.31.1",
|
||||
"arduino-ide-extension": "2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@theia/cli": "1.25.0",
|
||||
"@theia/cli": "1.31.1",
|
||||
"electron": "^15.3.5"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -37,8 +37,13 @@
|
||||
"frontend": {
|
||||
"config": {
|
||||
"applicationName": "Arduino IDE",
|
||||
"defaultTheme": "arduino-theme",
|
||||
"defaultTheme": {
|
||||
"light": "arduino-theme",
|
||||
"dark": "arduino-theme-dark"
|
||||
},
|
||||
"validatePreferencesSchema": false,
|
||||
"preferences": {
|
||||
"window.title": "${rootName}${activeEditorShort}${appName}",
|
||||
"files.autoSave": "afterDelay",
|
||||
"editor.minimap.enabled": false,
|
||||
"editor.tabSize": 2,
|
||||
@@ -49,6 +54,7 @@
|
||||
"strings": false
|
||||
},
|
||||
"editor.maxTokenizationLineLength": 500,
|
||||
"editor.bracketPairColorization.enabled": false,
|
||||
"breadcrumbs.enabled": false,
|
||||
"workbench.tree.renderIndentGuides": "none",
|
||||
"explorer.compactFolders": false
|
||||
|
@@ -1,152 +0,0 @@
|
||||
// Patch for the startup theme. Customizes the `ThemeService.get().defaultTheme();` to dispatch the default IDE2 theme based on the OS' theme.
|
||||
// For all subsequent starts of the IDE the theme applied will be the last one set by the user.
|
||||
|
||||
// With the current version of Theia adopted (1.25) it is not possible to extend the `ThemeService`, it will be possible starting from Theia 1.27.
|
||||
// Once the version of Theia is updated, this patch will be removed and this functionality will be implemented via dependency injection.
|
||||
// Ideally, we should open a PR in Theia and add support for `light` and `dark` default themes in the app config.
|
||||
|
||||
const {
|
||||
ThemeService,
|
||||
ThemeServiceSymbol,
|
||||
BuiltinThemeProvider,
|
||||
} = require('@theia/core/lib/browser/theming');
|
||||
const {
|
||||
ApplicationProps,
|
||||
} = require('@theia/application-package/lib/application-props');
|
||||
const {
|
||||
FrontendApplicationConfigProvider,
|
||||
} = require('@theia/core/lib/browser/frontend-application-config-provider');
|
||||
|
||||
function fetchFrom(path) {
|
||||
const { Endpoint } = require('@theia/core/lib/browser/endpoint');
|
||||
const endpoint = new Endpoint({ path }).getRestUrl().toString();
|
||||
return fetch(endpoint);
|
||||
}
|
||||
|
||||
async function loadTranslations() {
|
||||
const { nls } = require('@theia/core/lib/common/nls');
|
||||
const defaultLocale = typeof window === 'object' && window && window.localStorage.getItem(nls.localeId) || '';
|
||||
if (defaultLocale && !nls.locale) {
|
||||
Object.assign(nls, {
|
||||
locale: defaultLocale
|
||||
});
|
||||
}
|
||||
if (nls.locale) {
|
||||
const response = await fetchFrom(`/i18n/${nls.locale}`);
|
||||
nls.localization = await response.json();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadBackendOS() {
|
||||
const response = await fetchFrom('/os');
|
||||
const osType = await response.text();
|
||||
const isWindows = osType === 'Windows';
|
||||
const isOSX = osType === 'OSX';
|
||||
OS.backend.isOSX = isOSX;
|
||||
OS.backend.isWindows = isWindows;
|
||||
OS.backend.type = () => osType;
|
||||
}
|
||||
|
||||
function customizeMonacoNls() {
|
||||
const MonacoNls = require('@theia/monaco-editor-core/esm/vs/nls');
|
||||
const { nls: TheiaNls } = require('@theia/core/lib/common/nls');
|
||||
const { Localization } = require('@theia/core/lib/common/i18n/localization');
|
||||
Object.assign(MonacoNls, {
|
||||
localize(_, label, ...args) {
|
||||
if (TheiaNls.locale) {
|
||||
const defaultKey = TheiaNls.getDefaultKey(label);
|
||||
if (defaultKey) {
|
||||
return TheiaNls.localize(defaultKey, label, ...args);
|
||||
}
|
||||
}
|
||||
return Localization.format(label, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// It is a mighty hack to support theme updates in the bundled IDE2.
|
||||
// If the custom theme registration happens before the restoration of the existing monaco themes, then any custom theme changes will be ignored.
|
||||
// This patch introduces a static deferred promise in the monaco-theming service that will be resolved when the restoration is ready.
|
||||
// IDE2 cannot require the monaco theme service on the outer module level, as it requires the application config provider to be initialized,
|
||||
// but the initialization happens only in the generated `index.js`.
|
||||
// This patch customizes the monaco theme service behavior before loading the DI containers via the preload.
|
||||
// The preload is called only once before the app loads. The Theia extensions are not loaded at that point, but the app config provider is ready.
|
||||
const preloader = require('@theia/core/lib/browser/preloader');
|
||||
preloader.preload = async function () {
|
||||
// Must require the monaco frontend module to activate the NLS customization for monaco.
|
||||
// Otherwise, the NLS customization would trigger after the monaco UI components with all their translations are already loaded.
|
||||
await Promise.allSettled([
|
||||
loadTranslations(),
|
||||
loadBackendOS(),
|
||||
]);
|
||||
customizeMonacoNls();
|
||||
const { MonacoThemingService } = require('@theia/monaco/lib/browser/monaco-theming-service');
|
||||
const { MonacoThemeServiceIsReady } = require('arduino-ide-extension/lib/browser/utils/window');
|
||||
const { Deferred } = require('@theia/core/lib/common/promise-util');
|
||||
const ready = new Deferred();
|
||||
if (!window[MonacoThemeServiceIsReady]) {
|
||||
window[MonacoThemeServiceIsReady] = ready;
|
||||
console.log('Registered a custom monaco-theme service initialization signal on the window object.');
|
||||
}
|
||||
// Here, it is safe to patch the theme service, app config provider is ready.
|
||||
MonacoThemingService.init = async function () {
|
||||
this.updateBodyUiTheme();
|
||||
ThemeService.get().onDidColorThemeChange(() => this.updateBodyUiTheme());
|
||||
await this.restore();
|
||||
ready.resolve();
|
||||
}.bind(MonacoThemingService);
|
||||
}.bind(preloader);
|
||||
|
||||
const lightTheme = 'arduino-theme';
|
||||
const darkTheme = 'arduino-theme-dark';
|
||||
const defaultTheme =
|
||||
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? darkTheme
|
||||
: lightTheme;
|
||||
|
||||
const originalGet = FrontendApplicationConfigProvider.get;
|
||||
FrontendApplicationConfigProvider.get = function () {
|
||||
const originalProps = originalGet.bind(FrontendApplicationConfigProvider)();
|
||||
return { ...originalProps, defaultTheme };
|
||||
}.bind(FrontendApplicationConfigProvider);
|
||||
|
||||
const arduinoDarkTheme = {
|
||||
id: 'arduino-theme-dark',
|
||||
type: 'dark',
|
||||
label: 'Dark (Arduino)',
|
||||
editorTheme: 'arduino-theme-dark',
|
||||
activate() {},
|
||||
deactivate() {},
|
||||
};
|
||||
|
||||
const arduinoLightTheme = {
|
||||
id: 'arduino-theme',
|
||||
type: 'light',
|
||||
label: 'Light (Arduino)',
|
||||
editorTheme: 'arduino-theme',
|
||||
activate() {},
|
||||
deactivate() {},
|
||||
};
|
||||
|
||||
if (!window[ThemeServiceSymbol]) {
|
||||
const themeService = new ThemeService();
|
||||
Object.defineProperty(themeService, 'defaultTheme', {
|
||||
get: function () {
|
||||
return (
|
||||
this.themes[defaultTheme] ||
|
||||
this.themes[ApplicationProps.DEFAULT.frontend.config.defaultTheme]
|
||||
);
|
||||
},
|
||||
});
|
||||
themeService.register(
|
||||
...BuiltinThemeProvider.themes,
|
||||
arduinoDarkTheme,
|
||||
arduinoLightTheme
|
||||
);
|
||||
themeService.startupTheme();
|
||||
themeService.setCurrentTheme(defaultTheme);
|
||||
window[ThemeServiceSymbol] = themeService;
|
||||
}
|
||||
|
||||
// Require the original, generated `index.js` for `webpack` as the next entry for the `bundle.js`.
|
||||
require('../../src-gen/frontend/index');
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* This file can be edited to customize webpack configuration.
|
||||
* To reset delete this file and rerun theia build again.
|
||||
*/
|
||||
// @ts-check
|
||||
const config = require('./gen-webpack.config.js');
|
||||
|
||||
config.resolve.fallback['http'] = false;
|
||||
config.resolve.fallback['fs'] = false;
|
||||
|
||||
/**
|
||||
* Expose bundled modules on window.theia.moduleName namespace, e.g.
|
||||
* window['theia']['@theia/core/lib/common/uri'].
|
||||
* Such syntax can be used by external code, for instance, for testing.
|
||||
config.module.rules.push({
|
||||
test: /\.js$/,
|
||||
loader: require.resolve('@theia/application-manager/lib/expose-loader')
|
||||
}); */
|
||||
|
||||
|
||||
// Load the patched `index.js` that sets the desired theme in IDE2 based on the OS' theme.
|
||||
// The `patch/frontend/index.js` will require the original, generated `index.js`.
|
||||
// See: https://github.com/arduino/arduino-ide/pull/1160.
|
||||
config.entry.bundle = require('path').resolve(__dirname, 'patch/frontend/index.js');
|
||||
|
||||
module.exports = config;
|
2
electron/.gitignore
vendored
2
electron/.gitignore
vendored
@@ -6,6 +6,7 @@ working-copy/
|
||||
src-gen/
|
||||
node_modules/
|
||||
build/yarn.lock
|
||||
webpack.config.js
|
||||
lib/
|
||||
|
||||
# The electron-builder output.
|
||||
@@ -19,4 +20,3 @@ build/package.json
|
||||
|
||||
# Resources the packager copies from dev to prod
|
||||
build/resources/preload.html
|
||||
build/patch/frontend/index.js
|
||||
|
@@ -9,7 +9,7 @@
|
||||
"node-log-rotate": "^0.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@theia/cli": "1.25.0",
|
||||
"@theia/cli": "1.31.1",
|
||||
"cross-env": "^7.0.2",
|
||||
"electron-builder": "23.3.3",
|
||||
"electron-notarize": "^1.1.1",
|
||||
|
@@ -1,10 +0,0 @@
|
||||
// @ts-check
|
||||
const config = require('./gen-webpack.config.js');
|
||||
const path = require('path');
|
||||
|
||||
// Load the patched `index.js` that sets the desired theme in IDE2 based on the OS' theme.
|
||||
// The `patch/frontend/index.js` will require the original, generated `index.js`.
|
||||
// See: https://github.com/arduino/arduino-ide/pull/1160.
|
||||
config.entry.bundle = path.resolve(__dirname, 'patch/frontend/index.js');
|
||||
|
||||
module.exports = config;
|
@@ -42,251 +42,256 @@
|
||||
);
|
||||
}
|
||||
|
||||
//---------------------------+
|
||||
// Clean the previous state. |
|
||||
//---------------------------+
|
||||
// rm -rf ../working-copy
|
||||
rm('-rf', path('..', workingCopy));
|
||||
// Clean up the `./electron/build` folder.
|
||||
const resourcesToKeep = [
|
||||
'patch',
|
||||
'resources',
|
||||
'scripts',
|
||||
'template-package.json',
|
||||
'webpack.config.js'
|
||||
];
|
||||
fs.readdirSync(path('..', 'build'))
|
||||
.filter((filename) => resourcesToKeep.indexOf(filename) === -1)
|
||||
.forEach((filename) => rm('-rf', path('..', 'build', filename)));
|
||||
try {
|
||||
//---------------------------+
|
||||
// Clean the previous state. |
|
||||
//---------------------------+
|
||||
// rm -rf ../working-copy
|
||||
rm('-rf', path('..', workingCopy));
|
||||
// Clean up the `./electron/build` folder.
|
||||
const resourcesToKeep = [
|
||||
'patch',
|
||||
'resources',
|
||||
'scripts',
|
||||
'template-package.json'
|
||||
];
|
||||
fs.readdirSync(path('..', 'build'))
|
||||
.filter((filename) => resourcesToKeep.indexOf(filename) === -1)
|
||||
.forEach((filename) => rm('-rf', path('..', 'build', filename)));
|
||||
|
||||
// Clean up the `./electron/build/patch` and `./electron/build/resources` folder with Git.
|
||||
// To avoid file duplication between bundled app and dev mode, some files are copied from `./electron-app` to `./electron/build` folder.
|
||||
const foldersToSyncFromDev = ['patch', 'resources'];
|
||||
foldersToSyncFromDev.forEach(filename => shell.exec(`git -C ${path('..', 'build', filename)} clean -ffxdq`, { async: false }));
|
||||
// Clean up the `./electron/build/resources` folder with Git.
|
||||
// To avoid file duplication between bundled app and dev mode, some files are copied from `./electron-app` to `./electron/build` folder.
|
||||
const foldersToSyncFromDev = ['resources'];
|
||||
foldersToSyncFromDev.forEach((filename) =>
|
||||
shell.exec(`git -C ${path('..', 'build', filename)} clean -ffxdq`, {
|
||||
async: false,
|
||||
})
|
||||
);
|
||||
|
||||
const extensions = require('./extensions.json');
|
||||
echo(
|
||||
`Building the application with the following extensions:\n${extensions
|
||||
.map((ext) => ` - ${ext}`)
|
||||
.join(',\n')}`
|
||||
);
|
||||
const allDependencies = [...extensions, 'electron-app'];
|
||||
const extensions = require('./extensions.json');
|
||||
echo(
|
||||
`Building the application with the following extensions:\n${extensions
|
||||
.map((ext) => ` - ${ext}`)
|
||||
.join(',\n')}`
|
||||
);
|
||||
const allDependencies = [...extensions, 'electron-app'];
|
||||
|
||||
//----------------------------------------------------------------------------------------------+
|
||||
// Copy the following items into the `working-copy` folder. Make sure to reuse the `yarn.lock`. |
|
||||
//----------------------------------------------------------------------------------------------+
|
||||
mkdir('-p', path('..', workingCopy));
|
||||
for (const filename of [
|
||||
...allDependencies,
|
||||
'yarn.lock',
|
||||
'package.json',
|
||||
'lerna.json',
|
||||
'i18n'
|
||||
]) {
|
||||
cp('-rf', path(rootPath, filename), path('..', workingCopy));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------+
|
||||
// Copy the following items into the `working-copy` folder. Make sure to reuse the `yarn.lock`. |
|
||||
//----------------------------------------------------------------------------------------------+
|
||||
mkdir('-p', path('..', workingCopy));
|
||||
for (const filename of [
|
||||
...allDependencies,
|
||||
'yarn.lock',
|
||||
'package.json',
|
||||
'lerna.json',
|
||||
'i18n',
|
||||
]) {
|
||||
cp('-rf', path(rootPath, filename), path('..', workingCopy));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------+
|
||||
// Copy the patched `index.js` for the frontend, the Theia preload, etc. from `./electron-app` |
|
||||
//---------------------------------------------------------------------------------------------+
|
||||
for (const filename of foldersToSyncFromDev) {
|
||||
cp('-rf', path('..', workingCopy, 'electron-app', filename), path('..', 'build'));
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------+
|
||||
// Copy the patched `index.js` for the frontend, the Theia preload, etc. from `./electron-app` |
|
||||
//---------------------------------------------------------------------------------------------+
|
||||
for (const filename of foldersToSyncFromDev) {
|
||||
cp(
|
||||
'-rf',
|
||||
path('..', workingCopy, 'electron-app', filename),
|
||||
path('..', 'build')
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------+
|
||||
// Sanity check: all versions must be the same. |
|
||||
//----------------------------------------------+
|
||||
verifyVersions(allDependencies);
|
||||
//----------------------------------------------+
|
||||
// Sanity check: all versions must be the same. |
|
||||
//----------------------------------------------+
|
||||
verifyVersions(allDependencies);
|
||||
|
||||
//----------------------------------------------------------------------+
|
||||
// Use the nightly patch version if not a release but requires publish. |
|
||||
//----------------------------------------------------------------------+
|
||||
if (!isRelease) {
|
||||
for (const dependency of allDependencies) {
|
||||
const pkg = require(`../working-copy/${dependency}/package.json`);
|
||||
pkg.version = version;
|
||||
for (const dependency in pkg.dependencies) {
|
||||
if (allDependencies.indexOf(dependency) !== -1) {
|
||||
pkg.dependencies[dependency] = version;
|
||||
//----------------------------------------------------------------------+
|
||||
// Use the nightly patch version if not a release but requires publish. |
|
||||
//----------------------------------------------------------------------+
|
||||
if (!isRelease) {
|
||||
for (const dependency of allDependencies) {
|
||||
const pkg = require(`../working-copy/${dependency}/package.json`);
|
||||
pkg.version = version;
|
||||
for (const dependency in pkg.dependencies) {
|
||||
if (allDependencies.indexOf(dependency) !== -1) {
|
||||
pkg.dependencies[dependency] = version;
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(
|
||||
path('..', workingCopy, dependency, 'package.json'),
|
||||
JSON.stringify(pkg, null, 2)
|
||||
);
|
||||
}
|
||||
fs.writeFileSync(
|
||||
path('..', workingCopy, dependency, 'package.json'),
|
||||
JSON.stringify(pkg, null, 2)
|
||||
);
|
||||
}
|
||||
}
|
||||
verifyVersions(allDependencies);
|
||||
verifyVersions(allDependencies);
|
||||
|
||||
//---------------------------------------------------------------------------------------------------+
|
||||
// Save some time: no need to build the projects that are not needed in final app. Currently unused. |
|
||||
//---------------------------------------------------------------------------------------------------+
|
||||
//@ts-ignore
|
||||
const rootPackageJson = require('../working-copy/package.json');
|
||||
const workspaces = rootPackageJson.workspaces;
|
||||
// We cannot remove the `electron-app`. Otherwise, there is not way to collect the unused dependencies.
|
||||
const dependenciesToRemove = [];
|
||||
for (const dependencyToRemove of dependenciesToRemove) {
|
||||
const index = workspaces.indexOf(dependencyToRemove);
|
||||
if (index !== -1) {
|
||||
workspaces.splice(index, 1);
|
||||
//---------------------------------------------------------------------------------------------------+
|
||||
// Save some time: no need to build the projects that are not needed in final app. Currently unused. |
|
||||
//---------------------------------------------------------------------------------------------------+
|
||||
//@ts-ignore
|
||||
const rootPackageJson = require('../working-copy/package.json');
|
||||
const workspaces = rootPackageJson.workspaces;
|
||||
// We cannot remove the `electron-app`. Otherwise, there is not way to collect the unused dependencies.
|
||||
const dependenciesToRemove = [];
|
||||
for (const dependencyToRemove of dependenciesToRemove) {
|
||||
const index = workspaces.indexOf(dependencyToRemove);
|
||||
if (index !== -1) {
|
||||
workspaces.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
rootPackageJson.workspaces = workspaces;
|
||||
fs.writeFileSync(
|
||||
path('..', workingCopy, 'package.json'),
|
||||
JSON.stringify(rootPackageJson, null, 2)
|
||||
);
|
||||
rootPackageJson.workspaces = workspaces;
|
||||
fs.writeFileSync(
|
||||
path('..', workingCopy, 'package.json'),
|
||||
JSON.stringify(rootPackageJson, null, 2)
|
||||
);
|
||||
|
||||
//-------------------------------------------------------------------------------------------------+
|
||||
// Rebuild the extension with the copied `yarn.lock`. It is a must to use the same Theia versions. |
|
||||
//-------------------------------------------------------------------------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)}`,
|
||||
`Building the ${productName} application`
|
||||
);
|
||||
//-------------------------------------------------------------------------------------------------+
|
||||
// Rebuild the extension with the copied `yarn.lock`. It is a must to use the same Theia versions. |
|
||||
//-------------------------------------------------------------------------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)}`,
|
||||
`Building the ${productName} application`
|
||||
);
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------+
|
||||
// Test the application. With this approach, we cannot publish test results to GH Actions but save 6-10 minutes per builds |
|
||||
//-------------------------------------------------------------------------------------------------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)} test`,
|
||||
`Testing the ${productName} application`
|
||||
);
|
||||
//-------------------------------------------------------------------------------------------------------------------------+
|
||||
// Test the application. With this approach, we cannot publish test results to GH Actions but save 6-10 minutes per builds |
|
||||
//-------------------------------------------------------------------------------------------------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', workingCopy)} test`,
|
||||
`Testing the ${productName} application`
|
||||
);
|
||||
|
||||
// Collect all unused dependencies by the backend. We have to remove them from the electron app.
|
||||
// The `bundle.js` already contains everything we need for the frontend.
|
||||
// We have to do it before changing the dependencies to `local-path`.
|
||||
const unusedDependencies = await utils.collectUnusedDependencies(
|
||||
'../working-copy/electron-app/'
|
||||
);
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------+
|
||||
// Change the regular NPM dependencies to `local-paths`, so that we can build them without any NPM registries. |
|
||||
//-------------------------------------------------------------------------------------------------------------+
|
||||
for (const extension of extensions) {
|
||||
if (extension !== 'arduino-ide-extension') {
|
||||
// Do not unlink self.
|
||||
// @ts-ignore
|
||||
rootPackageJson = require(`../working-copy/${extension}/package.json`);
|
||||
// @ts-ignore
|
||||
rootPackageJson.dependencies['arduino-ide-extension'] =
|
||||
'file:../arduino-ide-extension';
|
||||
fs.writeFileSync(
|
||||
path('..', workingCopy, extension, 'package.json'),
|
||||
JSON.stringify(rootPackageJson, null, 2)
|
||||
);
|
||||
//-------------------------------------------------------------------------------------------------------------+
|
||||
// Change the regular NPM dependencies to `local-paths`, so that we can build them without any NPM registries. |
|
||||
//-------------------------------------------------------------------------------------------------------------+
|
||||
for (const extension of extensions) {
|
||||
if (extension !== 'arduino-ide-extension') {
|
||||
// Do not unlink self.
|
||||
// @ts-ignore
|
||||
rootPackageJson = require(`../working-copy/${extension}/package.json`);
|
||||
// @ts-ignore
|
||||
rootPackageJson.dependencies['arduino-ide-extension'] =
|
||||
'file:../arduino-ide-extension';
|
||||
fs.writeFileSync(
|
||||
path('..', workingCopy, extension, 'package.json'),
|
||||
JSON.stringify(rootPackageJson, null, 2)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------+
|
||||
// Merge the `working-copy/package.json` with `electron/build/template-package.json`. |
|
||||
//------------------------------------------------------------------------------------+
|
||||
// @ts-ignore
|
||||
const appPackageJson = require('../working-copy/electron-app/package.json');
|
||||
template.build.files = [
|
||||
...template.build.files,
|
||||
...unusedDependencies.map((name) => `!node_modules/${name}`),
|
||||
];
|
||||
|
||||
const dependencies = {};
|
||||
for (const extension of extensions) {
|
||||
dependencies[extension] = `file:../working-copy/${extension}`;
|
||||
}
|
||||
// @ts-ignore
|
||||
appPackageJson.dependencies = { ...appPackageJson.dependencies, ...dependencies };
|
||||
appPackageJson.devDependencies = { ...appPackageJson.devDependencies, ...template.devDependencies };
|
||||
// Deep-merging the Theia application configuration.
|
||||
// @ts-ignore
|
||||
const theia = merge(appPackageJson.theia || {}, template.theia || {});
|
||||
const content = {
|
||||
...appPackageJson,
|
||||
...template,
|
||||
theia,
|
||||
//------------------------------------------------------------------------------------+
|
||||
// Merge the `working-copy/package.json` with `electron/build/template-package.json`. |
|
||||
//------------------------------------------------------------------------------------+
|
||||
// @ts-ignore
|
||||
dependencies: appPackageJson.dependencies,
|
||||
devDependencies: appPackageJson.devDependencies,
|
||||
// VS Code extensions and the plugins folder is defined in the top level `package.json`. The template picks them up.
|
||||
theiaPluginsDir: rootPackageJson.theiaPluginsDir,
|
||||
theiaPlugins: rootPackageJson.theiaPlugins,
|
||||
};
|
||||
fs.writeFileSync(
|
||||
path('..', 'build', 'package.json'),
|
||||
JSON.stringify(
|
||||
merge(content, template, { arrayMerge: (_, sourceArray) => sourceArray }),
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
const appPackageJson = require('../working-copy/electron-app/package.json');
|
||||
const dependencies = {};
|
||||
for (const extension of extensions) {
|
||||
dependencies[extension] = `file:../working-copy/${extension}`;
|
||||
}
|
||||
// @ts-ignore
|
||||
appPackageJson.dependencies = {
|
||||
...appPackageJson.dependencies,
|
||||
...dependencies,
|
||||
};
|
||||
appPackageJson.devDependencies = {
|
||||
...appPackageJson.devDependencies,
|
||||
...template.devDependencies,
|
||||
};
|
||||
// Deep-merging the Theia application configuration.
|
||||
// @ts-ignore
|
||||
const theia = merge(appPackageJson.theia || {}, template.theia || {});
|
||||
const content = {
|
||||
...appPackageJson,
|
||||
...template,
|
||||
theia,
|
||||
// @ts-ignore
|
||||
dependencies: appPackageJson.dependencies,
|
||||
devDependencies: appPackageJson.devDependencies,
|
||||
// VS Code extensions and the plugins folder is defined in the top level `package.json`. The template picks them up.
|
||||
theiaPluginsDir: rootPackageJson.theiaPluginsDir,
|
||||
theiaPlugins: rootPackageJson.theiaPlugins,
|
||||
};
|
||||
fs.writeFileSync(
|
||||
path('..', 'build', 'package.json'),
|
||||
JSON.stringify(
|
||||
merge(content, template, {
|
||||
arrayMerge: (_, sourceArray) => sourceArray,
|
||||
}),
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
|
||||
echo(`📜 Effective 'package.json' for the ${productName} application is:
|
||||
echo(`📜 Effective 'package.json' for the ${productName} application is:
|
||||
-----------------------
|
||||
${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
|
||||
-----------------------
|
||||
`);
|
||||
|
||||
// Make sure the original `yarn.lock` file is used from the electron application.
|
||||
if (fs.existsSync(path('..', 'build', 'yarn.lock'))) {
|
||||
echo(`${path('..', 'build', 'yarn.lock')} must not exist.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
cp('-rf', path(rootPath, 'yarn.lock'), path('..', 'build'));
|
||||
if (!fs.existsSync(path('..', 'build', 'yarn.lock'))) {
|
||||
echo(`${path('..', 'build', 'yarn.lock')} does not exist.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------+
|
||||
// Install all private and public dependencies for the electron application and build Theia. |
|
||||
//-------------------------------------------------------------------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')}`,
|
||||
'Installing dependencies'
|
||||
);
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} build`,
|
||||
`Building the ${productName} application`
|
||||
);
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} rebuild`,
|
||||
'Rebuild native dependencies'
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------------+
|
||||
// Create a throw away dotenv file which we use to feed the builder with input. |
|
||||
//------------------------------------------------------------------------------+
|
||||
const dotenv = 'electron-builder.env';
|
||||
if (fs.existsSync(path('..', 'build', dotenv))) {
|
||||
rm('-rf', path('..', 'build', dotenv));
|
||||
}
|
||||
// For the releases we use the desired tag as is defined by `$(Release.Tag)` from Azure.
|
||||
// For the preview builds we use the version from the `electron/build/package.json` with the short commit hash.
|
||||
fs.writeFileSync(path('..', 'build', dotenv), `ARDUINO_VERSION=${version}`);
|
||||
|
||||
//-----------------------------------+
|
||||
// Package the electron application. |
|
||||
//-----------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`,
|
||||
`Packaging your ${productName} application`
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------+
|
||||
// Recalculate artifacts hash and copy to another folder (because they can change after signing them).
|
||||
// Azure does not support wildcard for `PublishBuildArtifacts@1.pathToPublish` |
|
||||
//-----------------------------------------------------------------------------------------------------+
|
||||
if (isCI) {
|
||||
try {
|
||||
await recalculateArtifactsHash();
|
||||
await copyFilesToBuildArtifacts();
|
||||
} catch (e) {
|
||||
echo(JSON.stringify(e));
|
||||
// Make sure the original `yarn.lock` file is used from the electron application.
|
||||
if (fs.existsSync(path('..', 'build', 'yarn.lock'))) {
|
||||
echo(`${path('..', 'build', 'yarn.lock')} must not exist.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
cp('-rf', path(rootPath, 'yarn.lock'), path('..', 'build'));
|
||||
if (!fs.existsSync(path('..', 'build', 'yarn.lock'))) {
|
||||
echo(`${path('..', 'build', 'yarn.lock')} does not exist.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
}
|
||||
echo(`🎉 Success. Your application is at: ${path('..', 'build', 'dist')}`);
|
||||
|
||||
restore();
|
||||
//-------------------------------------------------------------------------------------------+
|
||||
// Install all private and public dependencies for the electron application and build Theia. |
|
||||
//-------------------------------------------------------------------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')}`,
|
||||
'Installing dependencies'
|
||||
);
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} build`,
|
||||
`Building the ${productName} application`
|
||||
);
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} rebuild`,
|
||||
'Rebuild native dependencies'
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------------+
|
||||
// Create a throw away dotenv file which we use to feed the builder with input. |
|
||||
//------------------------------------------------------------------------------+
|
||||
const dotenv = 'electron-builder.env';
|
||||
if (fs.existsSync(path('..', 'build', dotenv))) {
|
||||
rm('-rf', path('..', 'build', dotenv));
|
||||
}
|
||||
// For the releases we use the desired tag as is defined by `$(Release.Tag)` from Azure.
|
||||
// For the preview builds we use the version from the `electron/build/package.json` with the short commit hash.
|
||||
fs.writeFileSync(path('..', 'build', dotenv), `ARDUINO_VERSION=${version}`);
|
||||
|
||||
//-----------------------------------+
|
||||
// Package the electron application. |
|
||||
//-----------------------------------+
|
||||
exec(
|
||||
`yarn --network-timeout 1000000 --cwd ${path('..', 'build')} package`,
|
||||
`Packaging your ${productName} application`
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------+
|
||||
// Recalculate artifacts hash and copy to another folder (because they can change after signing them).
|
||||
// Azure does not support wildcard for `PublishBuildArtifacts@1.pathToPublish` |
|
||||
//-----------------------------------------------------------------------------------------------------+
|
||||
if (isCI) {
|
||||
try {
|
||||
await recalculateArtifactsHash();
|
||||
await copyFilesToBuildArtifacts();
|
||||
} catch (e) {
|
||||
echo(JSON.stringify(e));
|
||||
shell.exit(1);
|
||||
}
|
||||
}
|
||||
echo(`🎉 Success. Your application is at: ${path('..', 'build', 'dist')}`);
|
||||
} finally {
|
||||
restore();
|
||||
}
|
||||
|
||||
//--------+
|
||||
// Utils. |
|
||||
@@ -514,7 +519,8 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
|
||||
if (expectedVersion) {
|
||||
if (!versions.has(expectedVersion)) {
|
||||
echo(
|
||||
`Mismatching version configuration. Expected version was: '${expectedVersion}' actual was: '${Array.from(versions)[0]
|
||||
`Mismatching version configuration. Expected version was: '${expectedVersion}' actual was: '${
|
||||
Array.from(versions)[0]
|
||||
}'.`
|
||||
);
|
||||
shell.exit(1);
|
||||
|
@@ -20,7 +20,6 @@
|
||||
"crypto": "^1.0.1",
|
||||
"dateformat": "^3.0.3",
|
||||
"deepmerge": "2.01",
|
||||
"depcheck": "^0.9.2",
|
||||
"file-type": "^14.1.4",
|
||||
"glob": "^7.1.6",
|
||||
"is-ci": "^2.0.0",
|
||||
|
@@ -5,51 +5,8 @@ const zip = require('7zip-min');
|
||||
const temp = require('temp');
|
||||
const path = require('path');
|
||||
const shell = require('shelljs');
|
||||
const depcheck = require('depcheck');
|
||||
const fromFile = require('file-type').fromFile;
|
||||
|
||||
/**
|
||||
* Resolves to an array of `npm` package names that are declared in the `package.json` but **not** used by the project.
|
||||
*/
|
||||
function collectUnusedDependencies(pathToProject = process.cwd()) {
|
||||
const p = path.isAbsolute(pathToProject)
|
||||
? pathToProject
|
||||
: path.resolve(process.cwd(), pathToProject);
|
||||
console.log(`⏱️ >>> Collecting unused backend dependencies for ${p}...`);
|
||||
return new Promise((resolve) => {
|
||||
depcheck(
|
||||
p,
|
||||
{
|
||||
ignoreDirs: ['frontend'],
|
||||
parsers: {
|
||||
'*.js': depcheck.parser.es6,
|
||||
'*.jsx': depcheck.parser.jsx,
|
||||
},
|
||||
detectors: [
|
||||
depcheck.detector.requireCallExpression,
|
||||
depcheck.detector.importDeclaration,
|
||||
],
|
||||
specials: [depcheck.special.eslint, depcheck.special.webpack],
|
||||
},
|
||||
(unused) => {
|
||||
const { dependencies } = unused;
|
||||
if (dependencies && dependencies.length > 0) {
|
||||
console.log(
|
||||
`👌 <<< The following unused dependencies have been found: ${JSON.stringify(
|
||||
dependencies,
|
||||
null,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
} else {
|
||||
console.log('👌 <<< No unused dependencies have been found.');
|
||||
}
|
||||
resolve(dependencies);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* `pathToZip` is a `path/to/your/app-name.zip`.
|
||||
* If the `pathToZip` archive does not have a root directory with name `app-name`, it creates one, and move the content from the
|
||||
@@ -127,7 +84,7 @@ function unpack(what, where) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
resolve(undefined);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -139,7 +96,7 @@ function pack(what, where) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
resolve(undefined);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -212,7 +169,6 @@ function getChannelFile(platform) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
collectUnusedDependencies,
|
||||
adjustArchiveStructure,
|
||||
isZip,
|
||||
unpack,
|
||||
|
@@ -14,112 +14,6 @@
|
||||
dependencies:
|
||||
"7zip-bin" "^5.0.3"
|
||||
|
||||
"@babel/code-frame@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
|
||||
integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.8.3"
|
||||
|
||||
"@babel/generator@^7.9.0":
|
||||
version "7.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.3.tgz#7c8b2956c6f68b3ab732bd16305916fbba521d94"
|
||||
integrity sha512-RpxM252EYsz9qLUIq6F7YJyK1sv0wWDBFuztfDGWaQKzHjqDHysxSiRUpA/X9jmfqo+WzkAVKFaUily5h+gDCQ==
|
||||
dependencies:
|
||||
"@babel/types" "^7.9.0"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/helper-function-name@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca"
|
||||
integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==
|
||||
dependencies:
|
||||
"@babel/helper-get-function-arity" "^7.8.3"
|
||||
"@babel/template" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5"
|
||||
integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9"
|
||||
integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.9.0":
|
||||
version "7.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed"
|
||||
integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==
|
||||
|
||||
"@babel/highlight@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
|
||||
integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==
|
||||
dependencies:
|
||||
chalk "^2.0.0"
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.7.7", "@babel/parser@^7.9.0":
|
||||
version "7.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.3.tgz#043a5fc2ad8b7ea9facddc4e802a1f0f25da7255"
|
||||
integrity sha512-E6SpIDJZ0cZAKoCNk+qSDd0ChfTnpiJN9FfNf3RZ20dzwA2vL2oq5IX1XTVT+4vDmRlta2nGk5HGMMskJAR+4A==
|
||||
|
||||
"@babel/parser@^7.8.3":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
|
||||
integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==
|
||||
|
||||
"@babel/template@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8"
|
||||
integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@babel/parser" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/traverse@^7.7.4":
|
||||
version "7.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892"
|
||||
integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@babel/generator" "^7.9.0"
|
||||
"@babel/helper-function-name" "^7.8.3"
|
||||
"@babel/helper-split-export-declaration" "^7.8.3"
|
||||
"@babel/parser" "^7.9.0"
|
||||
"@babel/types" "^7.9.0"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/types@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
|
||||
integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.9.0":
|
||||
version "7.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5"
|
||||
integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.9.0"
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.1.tgz#da5fd19a5f71177a53778073978873964f49acf1"
|
||||
@@ -161,11 +55,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3"
|
||||
integrity sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==
|
||||
|
||||
"@types/color-name@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
|
||||
|
||||
"@types/debug@^4.1.5":
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd"
|
||||
@@ -210,11 +99,6 @@ ansi-regex@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
||||
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
||||
|
||||
ansi-regex@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
|
||||
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
|
||||
|
||||
ansi-styles@^3.2.0, ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
@@ -222,14 +106,6 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
|
||||
dependencies:
|
||||
color-convert "^1.9.0"
|
||||
|
||||
ansi-styles@^4.0.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
|
||||
integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
|
||||
dependencies:
|
||||
"@types/color-name" "^1.1.1"
|
||||
color-convert "^2.0.1"
|
||||
|
||||
anymatch@~3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
|
||||
@@ -280,31 +156,7 @@ browser-stdout@1.3.1:
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
builtin-modules@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
|
||||
integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==
|
||||
|
||||
caller-callsite@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
|
||||
integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
|
||||
dependencies:
|
||||
callsites "^2.0.0"
|
||||
|
||||
caller-path@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
|
||||
integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
|
||||
dependencies:
|
||||
caller-callsite "^2.0.0"
|
||||
|
||||
callsites@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
|
||||
integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
|
||||
|
||||
camelcase@^5.0.0, camelcase@^5.3.1:
|
||||
camelcase@^5.0.0:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
@@ -321,7 +173,7 @@ chai@^4.2.0:
|
||||
pathval "^1.1.0"
|
||||
type-detect "^4.0.5"
|
||||
|
||||
chalk@^2.0.0, chalk@^2.4.2:
|
||||
chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
@@ -373,15 +225,6 @@ cliui@^5.0.0:
|
||||
strip-ansi "^5.2.0"
|
||||
wrap-ansi "^5.1.0"
|
||||
|
||||
cliui@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
@@ -394,38 +237,16 @@ color-convert@^1.9.0:
|
||||
dependencies:
|
||||
color-name "1.1.3"
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
cosmiconfig@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
|
||||
dependencies:
|
||||
import-fresh "^2.0.0"
|
||||
is-directory "^0.3.1"
|
||||
js-yaml "^3.13.1"
|
||||
parse-json "^4.0.0"
|
||||
|
||||
cross-spawn@^6.0.0:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
@@ -447,11 +268,6 @@ dateformat@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
||||
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
|
||||
|
||||
de-indent@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||
integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
|
||||
|
||||
debug@3.2.6:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
@@ -459,7 +275,7 @@ debug@3.2.6:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.1.0, debug@^4.1.1:
|
||||
debug@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
@@ -490,34 +306,6 @@ define-properties@^1.1.2, define-properties@^1.1.3:
|
||||
dependencies:
|
||||
object-keys "^1.0.12"
|
||||
|
||||
depcheck@^0.9.2:
|
||||
version "0.9.2"
|
||||
resolved "https://registry.yarnpkg.com/depcheck/-/depcheck-0.9.2.tgz#9e3198b44a527836914c61ba5395479c62ecbaf4"
|
||||
integrity sha512-w5f+lSZqLJJkk58s44eOd0Vor7hLZot4PlFL0y2JsIX5LuHQ2eAjHlDVeGBD4Mj6ZQSKakvKWRRCcPlvrdU2Sg==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.7.7"
|
||||
"@babel/traverse" "^7.7.4"
|
||||
builtin-modules "^3.0.0"
|
||||
camelcase "^5.3.1"
|
||||
cosmiconfig "^5.2.1"
|
||||
debug "^4.1.1"
|
||||
deps-regex "^0.1.4"
|
||||
js-yaml "^3.4.2"
|
||||
lodash "^4.17.15"
|
||||
minimatch "^3.0.2"
|
||||
node-sass-tilde-importer "^1.0.2"
|
||||
please-upgrade-node "^3.2.0"
|
||||
require-package-name "^2.0.1"
|
||||
resolve "^1.14.1"
|
||||
vue-template-compiler "^2.6.11"
|
||||
walkdir "^0.4.1"
|
||||
yargs "^15.0.2"
|
||||
|
||||
deps-regex@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/deps-regex/-/deps-regex-0.1.4.tgz#518667b7691460a5e7e0a341be76eb7ce8090184"
|
||||
integrity sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ=
|
||||
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
@@ -533,11 +321,6 @@ emoji-regex@^7.0.1:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
end-of-stream@^1.1.0:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
@@ -545,13 +328,6 @@ end-of-stream@^1.1.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-abstract@^1.17.0-next.1:
|
||||
version "1.17.5"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9"
|
||||
@@ -588,11 +364,6 @@ esprima@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
|
||||
esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
@@ -623,11 +394,6 @@ fill-range@^7.0.1:
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
find-parent-dir@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54"
|
||||
integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=
|
||||
|
||||
find-up@3.0.0, find-up@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
|
||||
@@ -635,14 +401,6 @@ find-up@3.0.0, find-up@^3.0.0:
|
||||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
find-up@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||
dependencies:
|
||||
locate-path "^5.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
flat@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
|
||||
@@ -718,11 +476,6 @@ glob@^7.0.0, glob@^7.1.3, glob@^7.1.6:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
||||
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||
@@ -750,7 +503,7 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
he@1.2.0, he@^1.1.0:
|
||||
he@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
@@ -760,14 +513,6 @@ ieee754@^1.1.13:
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
|
||||
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
|
||||
|
||||
import-fresh@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
|
||||
integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
|
||||
dependencies:
|
||||
caller-path "^2.0.0"
|
||||
resolve-from "^3.0.0"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@@ -791,11 +536,6 @@ invert-kv@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
|
||||
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
@@ -825,11 +565,6 @@ is-date-object@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
|
||||
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
|
||||
|
||||
is-directory@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
|
||||
integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
@@ -847,11 +582,6 @@ is-fullwidth-code-point@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-glob@^4.0.1, is-glob@~4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
|
||||
@@ -898,12 +628,7 @@ isexe@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-yaml@3.13.1, js-yaml@^3.13.1, js-yaml@^3.4.2:
|
||||
js-yaml@3.13.1:
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
|
||||
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
|
||||
@@ -911,16 +636,6 @@ js-yaml@3.13.1, js-yaml@^3.13.1, js-yaml@^3.4.2:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
jsesc@^2.5.1:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
|
||||
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
|
||||
|
||||
json-parse-better-errors@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
|
||||
|
||||
just-extend@^4.0.2:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.1.0.tgz#7278a4027d889601640ee0ce0e5a00b992467da4"
|
||||
@@ -941,19 +656,12 @@ locate-path@^3.0.0:
|
||||
p-locate "^3.0.0"
|
||||
path-exists "^3.0.0"
|
||||
|
||||
locate-path@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash.get@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
|
||||
|
||||
lodash@^4.17.13, lodash@^4.17.15:
|
||||
lodash@^4.17.15:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
@@ -986,7 +694,7 @@ mimic-fn@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1069,13 +777,6 @@ node-environment-flags@1.0.6:
|
||||
object.getownpropertydescriptors "^2.0.3"
|
||||
semver "^5.7.0"
|
||||
|
||||
node-sass-tilde-importer@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz#1a15105c153f648323b4347693fdb0f331bad1ce"
|
||||
integrity sha512-Swcmr38Y7uB78itQeBm3mThjxBy9/Ah/ykPIaURY/L6Nec9AyRoL/jJ7ECfMR+oZeCTVQNxVMu/aHU+TLRVbdg==
|
||||
dependencies:
|
||||
find-parent-dir "^0.3.0"
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
@@ -1152,7 +853,7 @@ p-is-promise@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
|
||||
integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
|
||||
|
||||
p-limit@^2.0.0, p-limit@^2.2.0:
|
||||
p-limit@^2.0.0:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
|
||||
integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
|
||||
@@ -1166,36 +867,16 @@ p-locate@^3.0.0:
|
||||
dependencies:
|
||||
p-limit "^2.0.0"
|
||||
|
||||
p-locate@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
|
||||
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
|
||||
dependencies:
|
||||
p-limit "^2.2.0"
|
||||
|
||||
p-try@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
parse-json@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
|
||||
integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
|
||||
dependencies:
|
||||
error-ex "^1.3.1"
|
||||
json-parse-better-errors "^1.0.1"
|
||||
|
||||
path-exists@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
|
||||
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
|
||||
|
||||
path-exists@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
@@ -1233,13 +914,6 @@ picomatch@^2.0.4:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||
|
||||
please-upgrade-node@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
||||
integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==
|
||||
dependencies:
|
||||
semver-compare "^1.0.0"
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
@@ -1282,17 +956,7 @@ require-main-filename@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||
|
||||
require-package-name@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
|
||||
integrity sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=
|
||||
|
||||
resolve-from@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
|
||||
integrity sha1-six699nWiBvItuZTM17rywoYh0g=
|
||||
|
||||
resolve@^1.1.6, resolve@^1.14.1:
|
||||
resolve@^1.1.6:
|
||||
version "1.15.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
|
||||
integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
|
||||
@@ -1306,11 +970,6 @@ rimraf@~2.6.2:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
||||
|
||||
semver@^5.5.0, semver@^5.7.0:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
@@ -1365,11 +1024,6 @@ sinon@^9.0.1:
|
||||
nise "^4.0.1"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
source-map@^0.5.0:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
@@ -1401,15 +1055,6 @@ string-width@^3.0.0, string-width@^3.1.0:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^5.1.0"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
|
||||
integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
string.prototype.trimleft@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74"
|
||||
@@ -1447,13 +1092,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
|
||||
dependencies:
|
||||
ansi-regex "^4.1.0"
|
||||
|
||||
strip-ansi@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
|
||||
integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.0"
|
||||
|
||||
strip-eof@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||
@@ -1502,11 +1140,6 @@ temp@^0.9.1:
|
||||
dependencies:
|
||||
rimraf "~2.6.2"
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
@@ -1534,19 +1167,6 @@ typedarray-to-buffer@^3.1.5:
|
||||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
vue-template-compiler@^2.6.11:
|
||||
version "2.6.11"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080"
|
||||
integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==
|
||||
dependencies:
|
||||
de-indent "^1.0.2"
|
||||
he "^1.1.0"
|
||||
|
||||
walkdir@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39"
|
||||
integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||
@@ -1583,15 +1203,6 @@ wrap-ansi@^5.1.0:
|
||||
string-width "^3.0.0"
|
||||
strip-ansi "^5.0.0"
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
@@ -1623,14 +1234,6 @@ yargs-parser@^11.1.1:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^18.1.1:
|
||||
version "18.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.1.tgz#bf7407b915427fc760fcbbccc6c82b4f0ffcbd37"
|
||||
integrity sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-unparser@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f"
|
||||
@@ -1673,20 +1276,3 @@ yargs@^12.0.5:
|
||||
which-module "^2.0.0"
|
||||
y18n "^3.2.1 || ^4.0.0"
|
||||
yargs-parser "^11.1.1"
|
||||
|
||||
yargs@^15.0.2:
|
||||
version "15.3.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
|
||||
integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==
|
||||
dependencies:
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
find-up "^4.1.0"
|
||||
get-caller-file "^2.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^4.2.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.1"
|
||||
|
13
i18n/af.json
13
i18n/af.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visit Arduino Cloud to create Cloud Sketches."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True for verbose upload output. False by default.",
|
||||
"verifyAfterUpload": "Verifieer kode na oplaai ",
|
||||
"window.autoScale": "True if the user interface automatically scales with the font size.",
|
||||
"window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Aflyn",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Begin...",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "The debug session type \"{0}\" is not supported."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Unsaved – {0}"
|
||||
},
|
||||
|
23
i18n/ar.json
23
i18n/ar.json
@@ -6,9 +6,9 @@
|
||||
},
|
||||
"board": {
|
||||
"board": "اللوحة {0}",
|
||||
"boardConfigDialogTitle": "Select Other Board and Port",
|
||||
"boardConfigDialogTitle": "أختر متحكم و منفذ مختلفين ",
|
||||
"boardInfo": "معلومات اللوحة",
|
||||
"boards": "boards",
|
||||
"boards": "المتحكمات",
|
||||
"configDialog1": "اختر لوحة و منفذ معا اذا اردت ان ترفع السكتش",
|
||||
"configDialog2": "اذا قمت باختيار لوحة فقط ستسطيع ان تترجم لكن بدون ان ترفع المشروع",
|
||||
"couldNotFindPreviouslySelected": "تعذر ايجاد اللوحة '{0}' المختارة مسبقا في المنصة المثبتة '{1}' . الرجاء اعادة اختيار اللوحة التي تريد استعمالها يدويا . هل تريد باعادة الاختيار الان؟",
|
||||
@@ -26,15 +26,15 @@
|
||||
"pleasePickBoard": "من فضلك اختر لوحة متصلة على المنفذ الذي اخترته",
|
||||
"port": "المنفذ {0}",
|
||||
"portLabel": "Port: {0}",
|
||||
"ports": "ports",
|
||||
"ports": "منافذ",
|
||||
"programmer": "المبرمجة",
|
||||
"reselectLater": "اعد الاختيار لاحقا",
|
||||
"searchBoard": "Search board",
|
||||
"searchBoard": "أبحث عن متحكم",
|
||||
"selectBoard": "اختر لوحة",
|
||||
"selectBoardForInfo": "الرجاء اختيار لوحة من احل الحصول على معلومات اللوحة",
|
||||
"selectPortForInfo": "الرجاء اختيار منفذ من اجل الحصول على معلومات اللوحة",
|
||||
"showAllAvailablePorts": "يظهر كل المنافذ المتاحة عند تفعيله",
|
||||
"showAllPorts": "Show all ports",
|
||||
"showAllPorts": "أظهر جميع المنافذ",
|
||||
"succesfullyInstalledPlatform": "تم تثبيت المنصة {0}:{1} بنجاح",
|
||||
"succesfullyUninstalledPlatform": "تم الغاء تثبيت المنصة {0}:{1} بنجاح",
|
||||
"typeOfPorts": "{0} ports"
|
||||
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "قم بزيارة Arduino Cloud من اجل انشاء ملف مشاريع على السحابة"
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True لخرج الرفع المطول . False افتراضيا",
|
||||
"verifyAfterUpload": "التحقق من الكود بعد الرفع",
|
||||
"window.autoScale": "True اذا كان مقياس الواجهة يتزامن تلقائيا مع حجم الخط ",
|
||||
"window.zoomLevel": "تعديل درجة التكبير للنافذة . الحجم الاصلي 0 و كل زيادة فوقه (مثلا 1) او اقل (مثلا -1) تمثل تكبير بدرجة 20% اكبر او اصغر . تستطيع ايضا ادخال فواصل لتعديل درجة التكبير بدقة اكبر"
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "هل تريد استبدال النسخة الحالية من {0} ؟",
|
||||
"selectZip": "اختر ملف .zip يحوي المكتبة التي تريد اضافتها",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "غير متصل",
|
||||
"quitTitle": "هل انت متاكد بانك تريد الخروج؟"
|
||||
},
|
||||
"debug": {
|
||||
"start": "البدء...",
|
||||
"startError": "لقد حصل خطأ اثناء بدأ جلسة التصحيح . تحقق من السجلات للمزيد من المعلومات",
|
||||
"typeNotSupported": "جلسة التصحيح من نوع \"{0}\" غير مدعومة"
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "غير محفوظ – {0}"
|
||||
},
|
||||
|
13
i18n/az.json
13
i18n/az.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visit Arduino Cloud to create Cloud Sketches."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True for verbose upload output. False by default.",
|
||||
"verifyAfterUpload": "Verify code after upload",
|
||||
"window.autoScale": "True if the user interface automatically scales with the font size.",
|
||||
"window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Offlayn",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Başlat",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "The debug session type \"{0}\" is not supported."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Unsaved – {0}"
|
||||
},
|
||||
|
13
i18n/bg.json
13
i18n/bg.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Посетете Arduino Cloud, за да създадете облачни скици."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True за подробен изход за качване. False по подразбиране.",
|
||||
"verifyAfterUpload": "Потвърдете кода след качване",
|
||||
"window.autoScale": "True , ако потребителският интерфейс автоматично се мащабира с размера на шрифта.",
|
||||
"window.zoomLevel": "Регулирайте нивото на увеличение на прозореца. Оригиналният размер е 0 и всяко увеличение над (напр. 1) или под (напр. -1) представлява увеличение с 20% по-голямо или по-малко. Можете също да въведете десетични знаци, за да регулирате нивото на увеличение по-финно."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Да се замени ли съществуващата версия на {0}?",
|
||||
"selectZip": "Изберете zip файл, съдържащ библиотеката, която искате да добавите",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Офлайн",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Започнете...",
|
||||
"startError": "Възникна грешка при стартиране на сесията за отстраняване на грешки, проверете регистрационните файлове за повече подробности.",
|
||||
"typeNotSupported": "Типът на сесията за отстраняване на грешки „{0}“ не се поддържа."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Незапазено – {0}"
|
||||
},
|
||||
|
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visiteu Arduino Cloud per crear programes al núvol."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True per a la sortida detallada de la càrrega. Fals per defecte.",
|
||||
"verifyAfterUpload": "Verifica el codi després de pujar",
|
||||
"window.autoScale": "És cert si la interfície d'usuari escala automàticament amb la mida de la lletra.",
|
||||
"window.zoomLevel": "Ajusteu el nivell de zoom de la finestra. La mida original és 0 i cada increment per sobre (p. ex. 1) o per sota (p. ex. -1) representa un 20% més gran o més petit. També podeu introduir decimals per ajustar el nivell de zoom amb una granularitat més fina."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Substitueix la versió existent de {0}?",
|
||||
"selectZip": "Seleccioneu un fitxer zip que contingui la llibreria que voleu afegir",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Fora de línia",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Començar...",
|
||||
"startError": "S'ha produït un error en iniciar la sessió de depuració, comproveu els registres per obtenir més informació.",
|
||||
"typeNotSupported": "No s'admet el tipus de sessió de depuració \"{0}\"."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "No desat –{0}"
|
||||
},
|
||||
|
13
i18n/cs.json
13
i18n/cs.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Navštivte Arduino Cloud pro vytvoření cloudové sketche"
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "Vše",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Ano pro podrobný výstup při nahrávání. Ne je výchozí hodnota. ",
|
||||
"verifyAfterUpload": "Kontrolovat kód po nahrání",
|
||||
"window.autoScale": "Ano pokud se měřítko uživatelského prostředí automaticky mění s velikostí písma. ",
|
||||
"window.zoomLevel": "Přizpůsobení přiblížení okna. Originální velikost je 0, zvýšení (např. o 1) nebo snížení (např. o -1) znamená 20% přiblížení nebo oddálení. Můžete použít desetinná čísla pro jemnější přizpůsobení."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Vyměnit existující verzi {0}?",
|
||||
"selectZip": "Zvolte ZIP soubor s knihovnou kterou chcete přidat",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Nepřipojen",
|
||||
"quitTitle": "Jste si jisti že chcete odejít"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Start...",
|
||||
"startError": "Vyskytla se chyba při spouštění debugovacího spojení, zkontrolujte prosím log pro více informací. ",
|
||||
"typeNotSupported": "Typ \"{0}\" debugovacího spojení není podporován, "
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Neuloženo – {0}"
|
||||
},
|
||||
|
13
i18n/de.json
13
i18n/de.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Besuche Arduino Cloud um Cloud Sketche zu erstellen."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "Alle",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Wenn aktiviert, werden ausführliche Compiler-Meldungen angezeigt. Standardgemäß deaktiviert.",
|
||||
"verifyAfterUpload": "Code nach Hochladen überprüfen ",
|
||||
"window.autoScale": "Wenn aktiviert: Benutzeroberfläche soll mit Schriftgröße skalieren.",
|
||||
"window.zoomLevel": "Stelle die Zoomstufe des Fensters ein. Der Standardwert ist 0, jede Vergrößerung (z.B.: 1) oder Verringerung (z.B.: -1) um eins steht für 20% Vergrößerung bzw. Verkleinerung des Fensters. Du kannst auch Kommazahlen eingeben, um die Zoomstufe feiner einzustellen.\n "
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Existierende Version von {0} ersetzen?",
|
||||
"selectZip": "Wähle die ZIP-Datei, welche die hinzuzufügende Bibliothek enthält",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Offline",
|
||||
"quitTitle": "Sind Sie sicher, dass das Fenster schließen möchten?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Start...",
|
||||
"startError": "Es gab einen Fehler beim Start der Debug-Session. Überprüfe die Logs für mehr Informationen.",
|
||||
"typeNotSupported": "Die Debug Session vom Typ \"{0}\" wird nicht unterstützt."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Nicht gespeichert – {0}"
|
||||
},
|
||||
|
13
i18n/el.json
13
i18n/el.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Επισκέψου το Arduino Cloud για δημιουργία Σχεδίων Cloud."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Αληθές για λεπτομερή έξοδο ανεβάσματος. Ψευδές απο προεπιλογή.",
|
||||
"verifyAfterUpload": "Επιβεβαίωση κώδικα μετά το ανέβασμα",
|
||||
"window.autoScale": "Αληθές αν η διεπαφή χρήστη κλιμακλωνεται αυτόματα μαζί με το μέγεθος γραμματοσειράς.",
|
||||
"window.zoomLevel": "Ρύθμιση του επιπέδου μεγέθυνσης του παραθύρου. Το αρχικό μέγεθος ειναι 0 και κάθε αύξηση (π.χ. 1) ή μείωση (π.χ. -1) αναπαριστά μεγέθυνση 20% μεγαλύτερη ή μικρότερη. Μπορούν να εισαχθούν και δεκαδικά για προσαρμογή της μεγέθυνσης με μεγαλύτερη λεπτομέρεια."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Εκτός Σύνδεσης",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Έναρξη...",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "The debug session type \"{0}\" is not supported."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Unsaved – {0}"
|
||||
},
|
||||
|
@@ -371,7 +371,9 @@
|
||||
"upload.verbose": "True for verbose upload output. False by default.",
|
||||
"verifyAfterUpload": "Verify code after upload",
|
||||
"window.autoScale": "True if the user interface automatically scales with the font size.",
|
||||
"window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -450,11 +452,6 @@
|
||||
"offline": "Offline",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Start...",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "The debug session type \"{0}\" is not supported."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Unsaved – {0}"
|
||||
},
|
||||
|
13
i18n/es.json
13
i18n/es.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visita Arduino Cloud para crear Cloud Sketches. "
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "Todo",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Verdadero para una salida verbosa de la carga. Falso por defecto.",
|
||||
"verifyAfterUpload": "Verificar el código después de cargarlo",
|
||||
"window.autoScale": "Verdadero si la interfaz de usuario se escala automáticamente con el tamaño de la fuente.",
|
||||
"window.zoomLevel": "Ajusta el nivel de zoom de la ventana. El tamaño original es 0 y cada incremento por encima (p. ej. 1) o por debajo (p. ej. -1) representa un zoom un 20 % más grande o más pequeño. También puedes introducir decimales para ajustar el nivel de zoom con una granularidad más fina."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "¿Sustituir la versión existente de {0}?",
|
||||
"selectZip": "Seleccione un archivo zip que contenga la biblioteca que deseas añadir",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Desconectado",
|
||||
"quitTitle": "Seguro que quiere salir ?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Empezar...",
|
||||
"startError": "Se ha producido un error al iniciar la sesión de depuración, consulte los logs para obtener más detalles.",
|
||||
"typeNotSupported": "El tipo de sesión de depuración \"{0}\" no es compatible."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Sin guardar – {0}"
|
||||
},
|
||||
|
13
i18n/eu.json
13
i18n/eu.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Bisitatu Arduino Cloud hodeiko programak sortzeko."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Egia kargaren irteera xehatua izateko. Lehenetsia Gezurra.",
|
||||
"verifyAfterUpload": "Egiaztatu kodea kargatu ondoren",
|
||||
"window.autoScale": "Egia erabiltzaile interfazea letra-tamainarekin automatikoki eskalatzen bada.",
|
||||
"window.zoomLevel": "Doitu leihoaren zoom maila. Jatorrizko tamaina 0 da eta goraka (1) edo beheraka (-1) egindako aldaketa bakoitzak zooma %20 handitzea edo txikiagotzea eragiten du. Zoom maila zehaztasun handiagoarekin doitzeko zenbaki hamartarrak erabili ditzakezu."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Lehendik dagoen {0} bertsioa ordezkatu?",
|
||||
"selectZip": "Hautatu gehitu nahi duzun liburutegia daukan zip fitxategia",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Lineaz kanpo",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Hasi...",
|
||||
"startError": "Errore bat gertatu da arazketa saioa hastean. Ikusi egunkariak xehetasun gehiagorako.",
|
||||
"typeNotSupported": "\"{0}\" motako arazketa saioak ez du euskarririk."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Gorde gabe – {0}"
|
||||
},
|
||||
|
13
i18n/fa.json
13
i18n/fa.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "بازدید از ابر آردوینو برای ساخت ابر طرح ها"
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "همه",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "برای خروجی آپلود پرمخاطب درست است. به طور پیش فرض نادرست است.",
|
||||
"verifyAfterUpload": "تائید کد بعد از آپلود",
|
||||
"window.autoScale": "اگر رابط کاربری به طور خودکار با اندازه فونت تغییر کند درست است.",
|
||||
"window.zoomLevel": "سطح بزرگنمایی پنجره را تنظیم کنید. اندازه اصلی 0 است و هر افزایش به بالاتر (مثلاً 1) یا پایین تر (مثلاً -1) نشان دهنده بزرگنمایی 20٪ بزرگتر یا کوچکتر است. همچنین می توانید اعداد اعشاری را وارد کنید تا سطح زوم را با دقت دقیق تر تنظیم کنید."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "آیا می خواهید نسخه موجود را با {0} جایگزین کنید؟",
|
||||
"selectZip": "یک فایل فشرده حاوی کتابخانه ای را که می خواهید اضافه کنید انتخاب کنید",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "آفلاین",
|
||||
"quitTitle": "آیا مطمئن هستید که می خواهید خارج شوید؟"
|
||||
},
|
||||
"debug": {
|
||||
"start": "شروع...",
|
||||
"startError": "یک خطا در آغاز جلسه رفع خطا بود، تاریخچه بقیه جزئیات را بررسی کنید.",
|
||||
"typeNotSupported": "جلسه رفع خطا \"{0}\" پشتیبانی نمی شود."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "ذخیره نشده – {0}"
|
||||
},
|
||||
|
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visit Arduino Cloud to create Cloud Sketches."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True para sa verbose upload output. Ito ay naka-false by default.",
|
||||
"verifyAfterUpload": "Verify code after upload",
|
||||
"window.autoScale": "True kung nais mong awtomatikong mag-adjust ang scaling ng user interface depende sa laki ng font o letra sa screen.",
|
||||
"window.zoomLevel": "Baguhin ang lebel ng pagka-zoom ng window. Ang orihinal na laki ay 0 at bawat dagdag (halimbawa +1) o bawas (halimbawa -1) ay katumbas ng 20% na pagtaas o pagbaba sa zoom. Pwede kang mag-enter ng decimals para mas makontrol mo ang pag-adjust ng lebel ng zoom. "
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Offline",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Start...",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "The debug session type \"{0}\" is not supported."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Unsaved – {0}"
|
||||
},
|
||||
|
13
i18n/fr.json
13
i18n/fr.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visitez Arduino Cloud pour créer des croquis sut le cloud."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Vrai si le téléchargement en mode verbose. Faux par défaut.",
|
||||
"verifyAfterUpload": "Vérifier le code après le téléversement",
|
||||
"window.autoScale": "Vrai si l'interface utilisateur s'ajuste avec la taille de la police.",
|
||||
"window.zoomLevel": "Ajuste le zoom de la fenêtre. La taille originale est 0 et chaque augmentation (par exemple 1) ou diminution (par exemple -1) représentent un zoom de plus ou moins 20 %. Vous pouvez également entrer des décimales pour ajuster plus finement le zoom. "
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Remplacer la version existante de {0} ?",
|
||||
"selectZip": "Sélectionnez un fichier zip contenant la bibliothèque que vous souhaitez ajouter",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Hors-ligne",
|
||||
"quitTitle": "Est que-vous sur vous voulez quitter? "
|
||||
},
|
||||
"debug": {
|
||||
"start": "Commencer...",
|
||||
"startError": "Une erreur est survenue lors du démarrage du débogage, consultez les logs pour plus de détails.",
|
||||
"typeNotSupported": "Le type de session de débogage \"{0}\" n'est pas pris en charge."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Non enregistré – {0}"
|
||||
},
|
||||
|
13
i18n/he.json
13
i18n/he.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "כנס.י לענן של ארדואינו ליצור סקיצה בענן"
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "הכל",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True for verbose upload output. False by default.",
|
||||
"verifyAfterUpload": "Verify code after upload",
|
||||
"window.autoScale": "True if the user interface automatically scales with the font size.",
|
||||
"window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "מנותק",
|
||||
"quitTitle": "בטוח.ה שתרצה.י לצאת?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "התחל...",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "הפעלת ניפוי באגים מסוג \"{0}\" אינה נתמכת."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "לא שמור – {0}"
|
||||
},
|
||||
|
21
i18n/hu.json
21
i18n/hu.json
@@ -12,13 +12,13 @@
|
||||
"configDialog1": "Válassz ki egy alaplapot és egy portot is - csak ekkor lehetséges a feltöltés. ",
|
||||
"configDialog2": "If you only select a Board you will be able to compile, but not to upload your sketch.",
|
||||
"couldNotFindPreviouslySelected": "Nem található a korábban kiválasztott '{0}' alaplap a/az '{1}' telepített platformon. Válaszd ki újra a használni kívánt alaplapot. Szeretnéd most újra megadni?",
|
||||
"disconnected": "Disconnected",
|
||||
"disconnected": "Leválasztott",
|
||||
"getBoardInfo": "Alaplap információk beszerzése",
|
||||
"inSketchbook": "(a vázlatfüzetben/sketchbook-ban) ",
|
||||
"installNow": "A \"{0} {1}\" támogatást telepíteni kell az aktuálisan kiválasztott \"{2}\" alaplaphoz. Most szeretnéd telepíteni? ",
|
||||
"noBoardsFound": "No boards found for \"{0}\"",
|
||||
"noFQBN": "Az FQBN nem érhető el a kiválasztott „{0}” alaplapon. A megfelelő mag/core telepítve van? ",
|
||||
"noPortsDiscovered": "No ports discovered",
|
||||
"noPortsDiscovered": "Nincs észlelt port",
|
||||
"noPortsSelected": "Nincsen port kiválasztva a alaplaphoz: '{0}'. ",
|
||||
"noneSelected": "Nincs alaplap kiválasztva",
|
||||
"openBoardsConfig": "Válassz másik alaplapot és portot… ",
|
||||
@@ -69,9 +69,9 @@
|
||||
"uploadingCertificates": "Tanúsítványok feltöltése "
|
||||
},
|
||||
"checkForUpdates": {
|
||||
"checkForUpdates": "Check for Arduino Updates",
|
||||
"checkForUpdates": "Arduino frissítések keresése",
|
||||
"installAll": "Install All",
|
||||
"noUpdates": "There are no recent updates available.",
|
||||
"noUpdates": "Nem állnak rendelkezésre új frissítések.",
|
||||
"promptUpdateBoards": "Updates are available for some of your boards.",
|
||||
"promptUpdateLibraries": "Updates are available for some of your libraries.",
|
||||
"updatingBoards": "Updating boards...",
|
||||
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Látogasd meg az Arduino Cloud webhelyet, hogy a felhőben vázlatokat hozhass létre. "
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "Kipipálva: a részletes feltöltési üzenetek kiírása a képernyőre. Alapértelmezés szerint hamis/nincs kipipálva.",
|
||||
"verifyAfterUpload": "Kód ellenőrzése feltöltés után",
|
||||
"window.autoScale": "Kipipálva, ha a felhasználói felület automatikusan méreteződik a betűmérettel együtt. ",
|
||||
"window.zoomLevel": "Ablak nagyítási szintjének megadása. Az eredeti méret: 0, és minden lépés növelése (pl. 1) vagy csökkentése (pl. -1) 20%-kal nagyobb vagy kisebb nagyítást jelent. Tizedesjegyeket is meg lehet adni a nagyítási szint finomabb beállításához. "
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Lecseréled a/az {0} meglévő verzióját? ",
|
||||
"selectZip": "Válaszd ki a hozzáadni kívánt könyvtárat tartalmazó ZIP-fájlt ",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Offline / nincs hálózat",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Start...",
|
||||
"startError": "Hiba történt a hibakeresési munkamenet indításakor. További részletekért ellenőrizd a naplókat. ",
|
||||
"typeNotSupported": "A {0} hibakeresési munkamenet típusa nem támogatott. "
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Nincs mentve – {0}"
|
||||
},
|
||||
|
13
i18n/id.json
13
i18n/id.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visit Arduino Cloud to create Cloud Sketches."
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creating remote sketch '{0}'...",
|
||||
"new": "New Remote Sketch",
|
||||
"synchronizing": "Synchronizing sketchbook, pulling '{0}'..."
|
||||
},
|
||||
"common": {
|
||||
"all": "All",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": "True for verbose upload output. False by default.",
|
||||
"verifyAfterUpload": "Verify code after upload",
|
||||
"window.autoScale": "True if the user interface automatically scales with the font size.",
|
||||
"window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Deprecated. Use 'window.zoomLevel' instead."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Replace the existing version of {0}?",
|
||||
"selectZip": "Select a zip file containing the library you'd like to add",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Offline",
|
||||
"quitTitle": "Are you sure you want to quit?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Start...",
|
||||
"startError": "There was an error starting the debug session, check the logs for more details.",
|
||||
"typeNotSupported": "The debug session type \"{0}\" is not supported."
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Unsaved – {0}"
|
||||
},
|
||||
|
27
i18n/it.json
27
i18n/it.json
@@ -120,7 +120,9 @@
|
||||
"visitArduinoCloud": "Visita Arduino Cloud per creare Cloud Sketch "
|
||||
},
|
||||
"cloudSketch": {
|
||||
"new": "New Remote Sketch"
|
||||
"creating": "Creando lo sketch remoto{0}",
|
||||
"new": "Nuovo Sketch remoto",
|
||||
"synchronizing": "Sincronizzazione degli sketch, pulling{0}"
|
||||
},
|
||||
"common": {
|
||||
"all": "Tutti",
|
||||
@@ -303,10 +305,10 @@
|
||||
"unableToConnectToWebSocket": "Impossibile connettersi al websocket"
|
||||
},
|
||||
"newCloudSketch": {
|
||||
"invalidSketchName": "The name must consist of basic letters, numbers, or underscores. The maximum length is 36 characters.",
|
||||
"newSketchTitle": "Name of a new Remote Sketch",
|
||||
"notFound": "Could not pull the remote sketch '{0}'. It does not exist.",
|
||||
"sketchAlreadyExists": "Remote sketch '{0}' already exists."
|
||||
"invalidSketchName": "Il nome deve essere composto da lettere, numeri o underscores. La lunghezza massima è di 36 caratteri.",
|
||||
"newSketchTitle": "Nome del nuovo Sketch Remoto",
|
||||
"notFound": "Non posso fare il pull dello sketch '{0}'. Lo sketch non esiste.",
|
||||
"sketchAlreadyExists": "Esiste già lo sketch remoto {0}"
|
||||
},
|
||||
"portProtocol": {
|
||||
"network": "Rete",
|
||||
@@ -369,7 +371,9 @@
|
||||
"upload.verbose": " Seleziona Vero per un rapporto dettagliato durante l'upload. Il valore predefinito è impostato su falso",
|
||||
"verifyAfterUpload": "Verifica il codice dopo il caricamento",
|
||||
"window.autoScale": "Impostato su True l'interfaccia scala automaticamente in base alla dimensione del font .",
|
||||
"window.zoomLevel": "Regola il livello di zoom della finestra. La dimensione originale è 0 e ogni incremento sopra (es. 1) o sotto (es. -1) rappresenta lo zoom del 20% in più o in meno. Puoi anche inserire i decimali per regolare il livello di zoom con una granularità più fine."
|
||||
"window.zoomLevel": {
|
||||
"deprecationMessage": "Non più disponibile. Al suo posto utilizza 'windows.zoomLevel'."
|
||||
}
|
||||
},
|
||||
"replaceMsg": "Sostituisce la versione esistente con la versione 1{0} ?",
|
||||
"selectZip": "Scegli il file zip che contiene la libreria che vuoi aggiungere",
|
||||
@@ -397,7 +401,7 @@
|
||||
"exportBinary": "Esporta sketch compilato",
|
||||
"moving": "Spostando",
|
||||
"movingMsg": "Il file \"{0}\" deve essere all'interno della cartella \"{1}\".\nCreare questa cartella, spostare il file e continuare?",
|
||||
"new": "New Sketch",
|
||||
"new": "Nuovo Sketch",
|
||||
"openFolder": "Apri Cartella",
|
||||
"openRecent": "Apri recenti",
|
||||
"openSketchInNewWindow": "Apri lo sketch in una Nuova Finestra.",
|
||||
@@ -417,8 +421,8 @@
|
||||
"verifyOrCompile": "Verifica/Compila"
|
||||
},
|
||||
"sketchbook": {
|
||||
"newRemoteSketch": "New Remote Sketch",
|
||||
"newSketch": "New Sketch"
|
||||
"newRemoteSketch": "Nuovo Sketch Remoto",
|
||||
"newSketch": "Nuovo Sketch"
|
||||
},
|
||||
"survey": {
|
||||
"answerSurvey": "Rispondi al questionario",
|
||||
@@ -448,11 +452,6 @@
|
||||
"offline": "Disconnesso",
|
||||
"quitTitle": "Sei sicuro di volere chiudere?"
|
||||
},
|
||||
"debug": {
|
||||
"start": "Inizio...",
|
||||
"startError": "Si è verificato un problema all'avvio del debug, per ulteriori controlla i logs",
|
||||
"typeNotSupported": "Il tipo di sessione di debug \" 1 {0} \" non è supportato. "
|
||||
},
|
||||
"editor": {
|
||||
"unsavedTitle": "Non salvato – 1{0}"
|
||||
},
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user