Compare commits
75 Commits
2.0.0-rc8
...
2.0.0-rc9.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d93c9ba654 | ||
![]() |
8a0dc1be7e | ||
![]() |
564862e173 | ||
![]() |
d7f7010bb5 | ||
![]() |
e156dcc213 | ||
![]() |
27a2a6ca03 | ||
![]() |
581379f86f | ||
![]() |
b62f3dec84 | ||
![]() |
90d2950bdd | ||
![]() |
5b7d64c1c1 | ||
![]() |
55927ac3dd | ||
![]() |
40c93bc19a | ||
![]() |
59b8a2d6bb | ||
![]() |
124738d810 | ||
![]() |
19c0334a91 | ||
![]() |
f22be3c587 | ||
![]() |
9373a0bcaf | ||
![]() |
5087ff08f2 | ||
![]() |
71d5a1520a | ||
![]() |
ec160df25e | ||
![]() |
7fbf3dc656 | ||
![]() |
7680194feb | ||
![]() |
2fdb19ea75 | ||
![]() |
8610332afc | ||
![]() |
1f7c2eb52c | ||
![]() |
119dfa78d9 | ||
![]() |
337d22efbd | ||
![]() |
5ff9ce0028 | ||
![]() |
d4833affc6 | ||
![]() |
8ad10b5adf | ||
![]() |
fe31d15b9f | ||
![]() |
99664ee544 | ||
![]() |
57841b3c0a | ||
![]() |
ed41b25889 | ||
![]() |
4f27725b35 | ||
![]() |
73835eced3 | ||
![]() |
46fcc71dd8 | ||
![]() |
453a657172 | ||
![]() |
1514d014a9 | ||
![]() |
e4d9243486 | ||
![]() |
fb690c97e8 | ||
![]() |
a0038315da | ||
![]() |
aea550fe33 | ||
![]() |
813444408e | ||
![]() |
d8be8888ef | ||
![]() |
431c3bdf2b | ||
![]() |
c51b201362 | ||
![]() |
7fed8febf1 | ||
![]() |
f4a68e793e | ||
![]() |
7d961537eb | ||
![]() |
d7a2d83990 | ||
![]() |
a36524e02a | ||
![]() |
1073c3fc7d | ||
![]() |
69d7e8e96c | ||
![]() |
7f2b849963 | ||
![]() |
0ce065e496 | ||
![]() |
0b0958c20e | ||
![]() |
06acd7fcde | ||
![]() |
b1e00e6ff2 | ||
![]() |
ea42dc52fd | ||
![]() |
6586cb37a8 | ||
![]() |
9b7ab14253 | ||
![]() |
d6899af5e7 | ||
![]() |
087cab177b | ||
![]() |
5da558dfd9 | ||
![]() |
953859831c | ||
![]() |
a13a8771d1 | ||
![]() |
5499c25528 | ||
![]() |
1e469627b4 | ||
![]() |
34ef25c4e4 | ||
![]() |
d1aa446c89 | ||
![]() |
e454acba41 | ||
![]() |
75abb70bcd | ||
![]() |
7ba98a212c | ||
![]() |
6ae6ba5b3d |
58
.github/workflows/build.yml
vendored
@@ -4,12 +4,26 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
- '!.github/workflows/build.yml'
|
||||
- '.vscode/**'
|
||||
- 'docs/**'
|
||||
- 'scripts/**'
|
||||
- 'static/**'
|
||||
- '*.md'
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+*'
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
- '!.github/workflows/build.yml'
|
||||
- '.vscode/**'
|
||||
- 'docs/**'
|
||||
- 'scripts/**'
|
||||
- 'static/**'
|
||||
- '*.md'
|
||||
schedule:
|
||||
- cron: '0 3 * * *' # run every day at 3AM (https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule)
|
||||
|
||||
@@ -19,13 +33,21 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository == 'arduino/arduino-ide'
|
||||
name: build (${{ matrix.config.os }})
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- os: windows-2019
|
||||
certificate-secret: WINDOWS_SIGNING_CERTIFICATE_PFX # Name of the secret that contains the certificate.
|
||||
certificate-password-secret: WINDOWS_SIGNING_CERTIFICATE_PASSWORD # Name of the secret that contains the certificate password.
|
||||
certificate-extension: pfx # File extension for the certificate.
|
||||
- os: ubuntu-18.04 # https://github.com/arduino/arduino-ide/issues/259
|
||||
- os: macos-latest
|
||||
# APPLE_SIGNING_CERTIFICATE_P12 secret was produced by following the procedure from:
|
||||
# https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate
|
||||
certificate-secret: APPLE_SIGNING_CERTIFICATE_P12
|
||||
certificate-password-secret: KEYCHAIN_PASSWORD
|
||||
certificate-extension: p12
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
timeout-minutes: 90
|
||||
|
||||
@@ -55,29 +77,20 @@ jobs:
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
IS_NIGHTLY: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') }}
|
||||
IS_RELEASE: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
IS_FORK: ${{ github.event.pull_request.head.repo.fork == true }}
|
||||
CAN_SIGN: ${{ secrets[matrix.config.certificate-secret] != '' }}
|
||||
run: |
|
||||
# See: https://www.electron.build/code-signing
|
||||
if [ $IS_FORK = true ]; then
|
||||
echo "Skipping the app signing: building from a fork."
|
||||
if [ $CAN_SIGN = false ]; then
|
||||
echo "Skipping the app signing: certificate not provided."
|
||||
else
|
||||
if [ "${{ runner.OS }}" = "macOS" ]; then
|
||||
export CSC_LINK="${{ runner.temp }}/signing_certificate.p12"
|
||||
# APPLE_SIGNING_CERTIFICATE_P12 secret was produced by following the procedure from:
|
||||
# https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate
|
||||
echo "${{ secrets.APPLE_SIGNING_CERTIFICATE_P12 }}" | base64 --decode > "$CSC_LINK"
|
||||
|
||||
export CSC_KEY_PASSWORD="${{ secrets.KEYCHAIN_PASSWORD }}"
|
||||
|
||||
elif [ "${{ runner.OS }}" = "Windows" ]; then
|
||||
export CSC_LINK="${{ runner.temp }}/signing_certificate.pfx"
|
||||
npm config set msvs_version 2017 --global
|
||||
echo "${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PFX }}" | base64 --decode > "$CSC_LINK"
|
||||
|
||||
export CSC_KEY_PASSWORD="${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PASSWORD }}"
|
||||
fi
|
||||
export CSC_LINK="${{ runner.temp }}/signing_certificate.${{ matrix.config.certificate-extension }}"
|
||||
echo "${{ secrets[matrix.config.certificate-secret] }}" | base64 --decode > "$CSC_LINK"
|
||||
export CSC_KEY_PASSWORD="${{ secrets[matrix.config.certificate-password-secret] }}"
|
||||
fi
|
||||
|
||||
if [ "${{ runner.OS }}" = "Windows" ]; then
|
||||
npm config set msvs_version 2017 --global
|
||||
fi
|
||||
npx node-gyp install
|
||||
yarn --cwd ./electron/packager/
|
||||
yarn --cwd ./electron/packager/ package
|
||||
@@ -190,7 +203,7 @@ jobs:
|
||||
|
||||
release:
|
||||
needs: changelog
|
||||
if: github.repository == 'arduino/arduino-ide' && startsWith(github.ref, 'refs/tags/')
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download [GitHub Actions]
|
||||
@@ -215,6 +228,7 @@ jobs:
|
||||
body: ${{ needs.changelog.outputs.BODY }}
|
||||
|
||||
- name: Publish Release [S3]
|
||||
if: github.repository == 'arduino/arduino-ide'
|
||||
uses: docker://plugins/s3
|
||||
env:
|
||||
PLUGIN_SOURCE: '${{ env.JOB_TRANSFER_ARTIFACT }}/*'
|
||||
|
@@ -1,15 +1,14 @@
|
||||
{
|
||||
"name": "arduino-ide-extension",
|
||||
"version": "2.0.0-rc8",
|
||||
"version": "2.0.0-rc9.1",
|
||||
"description": "An extension for Theia building the Arduino IDE",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"prepare": "yarn download-cli && yarn download-fwuploader && yarn download-ls && yarn copy-serial-plotter && yarn copy-i18n && yarn clean && yarn download-examples && yarn build && yarn test",
|
||||
"prepare": "yarn download-cli && yarn download-fwuploader && yarn download-ls && yarn copy-i18n && yarn clean && yarn download-examples && yarn build && yarn test",
|
||||
"clean": "rimraf lib",
|
||||
"compose-changelog": "node ./scripts/compose-changelog.js",
|
||||
"download-cli": "node ./scripts/download-cli.js",
|
||||
"download-fwuploader": "node ./scripts/download-fwuploader.js",
|
||||
"copy-serial-plotter": "npx ncp ../node_modules/arduino-serial-plotter-webapp ./build/arduino-serial-plotter-webapp",
|
||||
"copy-i18n": "npx ncp ../i18n ./build/i18n",
|
||||
"download-ls": "node ./scripts/download-ls.js",
|
||||
"download-examples": "node ./scripts/download-examples.js",
|
||||
@@ -62,6 +61,7 @@
|
||||
"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",
|
||||
@@ -156,7 +156,7 @@
|
||||
],
|
||||
"arduino": {
|
||||
"cli": {
|
||||
"version": "0.24.0"
|
||||
"version": "0.25.1"
|
||||
},
|
||||
"fwuploader": {
|
||||
"version": "2.2.0"
|
||||
@@ -165,7 +165,7 @@
|
||||
"version": "14.0.0"
|
||||
},
|
||||
"languageServer": {
|
||||
"version": "0.6.0"
|
||||
"version": "0.7.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,141 +1,87 @@
|
||||
// @ts-check
|
||||
|
||||
(async () => {
|
||||
const path = require('path');
|
||||
const shell = require('shelljs');
|
||||
const semver = require('semver');
|
||||
const moment = require('moment');
|
||||
const downloader = require('./downloader');
|
||||
const { goBuildFromGit } = require('./utils');
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const temp = require('temp');
|
||||
const shell = require('shelljs');
|
||||
const semver = require('semver');
|
||||
const moment = require('moment');
|
||||
const downloader = require('./downloader');
|
||||
const version = (() => {
|
||||
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
||||
if (!pkg) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const version = (() => {
|
||||
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
||||
if (!pkg) {
|
||||
return undefined;
|
||||
const { arduino } = pkg;
|
||||
if (!arduino) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { cli } = arduino;
|
||||
if (!cli) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { version } = cli;
|
||||
return version;
|
||||
})();
|
||||
|
||||
if (!version) {
|
||||
shell.echo(`Could not retrieve CLI version info from the 'package.json'.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const { platform, arch } = process;
|
||||
const buildFolder = path.join(__dirname, '..', 'build');
|
||||
const cliName = `arduino-cli${platform === 'win32' ? '.exe' : ''}`;
|
||||
const destinationPath = path.join(buildFolder, cliName);
|
||||
|
||||
if (typeof version === 'string') {
|
||||
const suffix = (() => {
|
||||
switch (platform) {
|
||||
case 'darwin':
|
||||
return 'macOS_64bit.tar.gz';
|
||||
case 'win32':
|
||||
return 'Windows_64bit.zip';
|
||||
case 'linux': {
|
||||
switch (arch) {
|
||||
case 'arm':
|
||||
return 'Linux_ARMv7.tar.gz';
|
||||
case 'arm64':
|
||||
return 'Linux_ARM64.tar.gz';
|
||||
case 'x64':
|
||||
return 'Linux_64bit.tar.gz';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const { arduino } = pkg;
|
||||
if (!arduino) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { cli } = arduino;
|
||||
if (!cli) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { version } = cli;
|
||||
return version;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
})();
|
||||
|
||||
if (!version) {
|
||||
shell.echo(`Could not retrieve CLI version info from the 'package.json'.`);
|
||||
shell.exit(1);
|
||||
if (!suffix) {
|
||||
shell.echo(`The CLI is not available for ${platform} ${arch}.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const { platform, arch } = process;
|
||||
const buildFolder = path.join(__dirname, '..', 'build');
|
||||
const cliName = `arduino-cli${platform === 'win32' ? '.exe' : ''}`;
|
||||
const destinationPath = path.join(buildFolder, cliName);
|
||||
|
||||
if (typeof version === 'string') {
|
||||
const suffix = (() => {
|
||||
switch (platform) {
|
||||
case 'darwin': return 'macOS_64bit.tar.gz';
|
||||
case 'win32': return 'Windows_64bit.zip';
|
||||
case 'linux': {
|
||||
switch (arch) {
|
||||
case 'arm': return 'Linux_ARMv7.tar.gz';
|
||||
case 'arm64': return 'Linux_ARM64.tar.gz';
|
||||
case 'x64': return 'Linux_64bit.tar.gz';
|
||||
default: return undefined;
|
||||
}
|
||||
}
|
||||
default: return undefined;
|
||||
}
|
||||
})();
|
||||
if (!suffix) {
|
||||
shell.echo(`The CLI is not available for ${platform} ${arch}.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
if (semver.valid(version)) {
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/arduino-cli_${version}_${suffix}`;
|
||||
shell.echo(`📦 Identified released version of the CLI. Downloading version ${version} from '${url}'`);
|
||||
await downloader.downloadUnzipFile(url, destinationPath, 'arduino-cli');
|
||||
} else if (moment(version, 'YYYYMMDD', true).isValid()) {
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-${version}_${suffix}`;
|
||||
shell.echo(`🌙 Identified nightly version of the CLI. Downloading version ${version} from '${url}'`);
|
||||
await downloader.downloadUnzipFile(url, destinationPath, 'arduino-cli');
|
||||
} else {
|
||||
shell.echo(`🔥 Could not interpret 'version': ${version}`);
|
||||
shell.exit(1);
|
||||
}
|
||||
if (semver.valid(version)) {
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/arduino-cli_${version}_${suffix}`;
|
||||
shell.echo(
|
||||
`📦 Identified released version of the CLI. Downloading version ${version} from '${url}'`
|
||||
);
|
||||
await downloader.downloadUnzipFile(url, destinationPath, 'arduino-cli');
|
||||
} else if (moment(version, 'YYYYMMDD', true).isValid()) {
|
||||
const url = `https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-${version}_${suffix}`;
|
||||
shell.echo(
|
||||
`🌙 Identified nightly version of the CLI. Downloading version ${version} from '${url}'`
|
||||
);
|
||||
await downloader.downloadUnzipFile(url, destinationPath, 'arduino-cli');
|
||||
} else {
|
||||
|
||||
// We assume an object with `owner`, `repo`, commitish?` properties.
|
||||
const { owner, repo, commitish } = version;
|
||||
if (!owner) {
|
||||
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
|
||||
shell.exit(1);
|
||||
}
|
||||
if (!repo) {
|
||||
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
|
||||
shell.exit(1);
|
||||
}
|
||||
const url = `https://github.com/${owner}/${repo}.git`;
|
||||
shell.echo(`Building CLI from ${url}. Commitish: ${commitish ? commitish : 'HEAD'}`);
|
||||
|
||||
if (fs.existsSync(destinationPath)) {
|
||||
shell.echo(`Skipping the CLI build because it already exists: ${destinationPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shell.mkdir('-p', buildFolder).code !== 0) {
|
||||
shell.echo('Could not create build folder.');
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const tempRepoPath = temp.mkdirSync();
|
||||
shell.echo(`>>> Cloning CLI source to ${tempRepoPath}...`);
|
||||
if (shell.exec(`git clone ${url} ${tempRepoPath}`).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo('<<< Cloned CLI repo.')
|
||||
|
||||
if (commitish) {
|
||||
shell.echo(`>>> Checking out ${commitish}...`);
|
||||
if (shell.exec(`git -C ${tempRepoPath} checkout ${commitish}`).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`<<< Checked out ${commitish}.`);
|
||||
}
|
||||
|
||||
shell.echo(`>>> Building the CLI...`);
|
||||
if (shell.exec('go build', { cwd: tempRepoPath }).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo('<<< CLI build done.')
|
||||
|
||||
if (!fs.existsSync(path.join(tempRepoPath, cliName))) {
|
||||
shell.echo(`Could not find the CLI at ${path.join(tempRepoPath, cliName)}.`);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const builtCliPath = path.join(tempRepoPath, cliName);
|
||||
shell.echo(`>>> Copying CLI from ${builtCliPath} to ${destinationPath}...`);
|
||||
if (shell.cp(builtCliPath, destinationPath).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`<<< Copied the CLI.`);
|
||||
|
||||
shell.echo('<<< Verifying CLI...');
|
||||
if (!fs.existsSync(destinationPath)) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo('>>> Verified CLI.');
|
||||
|
||||
shell.echo(`🔥 Could not interpret 'version': ${version}`);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
} else {
|
||||
goBuildFromGit(version, destinationPath, 'CLI');
|
||||
}
|
||||
})();
|
||||
|
@@ -7,22 +7,23 @@
|
||||
const path = require('path');
|
||||
const shell = require('shelljs');
|
||||
const downloader = require('./downloader');
|
||||
const { goBuildFromGit } = require('./utils');
|
||||
|
||||
const [DEFAULT_ALS_VERSION, DEFAULT_CLANGD_VERSION] = (() => {
|
||||
const [DEFAULT_LS_VERSION, DEFAULT_CLANGD_VERSION] = (() => {
|
||||
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
||||
if (!pkg) return undefined;
|
||||
if (!pkg) return [undefined, undefined];
|
||||
|
||||
const { arduino } = pkg;
|
||||
if (!arduino) return undefined;
|
||||
if (!arduino) return [undefined, undefined];
|
||||
|
||||
const { languageServer, clangd } = arduino;
|
||||
if (!languageServer) return undefined;
|
||||
if (!clangd) return undefined;
|
||||
if (!languageServer) return [undefined, undefined];
|
||||
if (!clangd) return [undefined, undefined];
|
||||
|
||||
return [languageServer.version, clangd.version];
|
||||
})();
|
||||
|
||||
if (!DEFAULT_ALS_VERSION) {
|
||||
if (!DEFAULT_LS_VERSION) {
|
||||
shell.echo(
|
||||
`Could not retrieve Arduino Language Server version info from the 'package.json'.`
|
||||
);
|
||||
@@ -39,8 +40,8 @@
|
||||
const yargs = require('yargs')
|
||||
.option('ls-version', {
|
||||
alias: 'lv',
|
||||
default: DEFAULT_ALS_VERSION,
|
||||
describe: `The version of the 'arduino-language-server' to download. Defaults to ${DEFAULT_ALS_VERSION}.`,
|
||||
default: DEFAULT_LS_VERSION,
|
||||
describe: `The version of the 'arduino-language-server' to download. Defaults to ${DEFAULT_LS_VERSION}.`,
|
||||
})
|
||||
.option('clangd-version', {
|
||||
alias: 'cv',
|
||||
@@ -56,7 +57,7 @@
|
||||
.version(false)
|
||||
.parse();
|
||||
|
||||
const alsVersion = yargs['ls-version'];
|
||||
const lsVersion = yargs['ls-version'];
|
||||
const clangdVersion = yargs['clangd-version'];
|
||||
const force = yargs['force-download'];
|
||||
const { platform, arch } = process;
|
||||
@@ -87,6 +88,8 @@
|
||||
lsSuffix = 'Windows_64bit.zip';
|
||||
clangdSuffix = 'Windows_64bit';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported platform/arch: ${platformArch}.`);
|
||||
}
|
||||
if (!lsSuffix || !clangdSuffix) {
|
||||
shell.echo(
|
||||
@@ -95,12 +98,16 @@
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const alsUrl = `https://downloads.arduino.cc/arduino-language-server/${
|
||||
alsVersion === 'nightly'
|
||||
? 'nightly/arduino-language-server'
|
||||
: 'arduino-language-server_' + alsVersion
|
||||
}_${lsSuffix}`;
|
||||
downloader.downloadUnzipAll(alsUrl, build, lsExecutablePath, force);
|
||||
if (typeof lsVersion === 'string') {
|
||||
const lsUrl = `https://downloads.arduino.cc/arduino-language-server/${
|
||||
lsVersion === 'nightly'
|
||||
? 'nightly/arduino-language-server'
|
||||
: 'arduino-language-server_' + lsVersion
|
||||
}_${lsSuffix}`;
|
||||
downloader.downloadUnzipAll(lsUrl, build, lsExecutablePath, force);
|
||||
} else {
|
||||
goBuildFromGit(lsVersion, lsExecutablePath, 'language-server');
|
||||
}
|
||||
|
||||
const clangdUrl = `https://downloads.arduino.cc/tools/clangd_${clangdVersion}_${clangdSuffix}.tar.bz2`;
|
||||
downloader.downloadUnzipAll(clangdUrl, build, clangdExecutablePath, force, {
|
||||
|
@@ -86,6 +86,7 @@ exports.downloadUnzipFile = async (
|
||||
* @param targetDir {string} Directory into which to decompress the archive
|
||||
* @param targetFile {string} Path to the main file expected after decompressing
|
||||
* @param force {boolean} Whether to download even if the target file exists
|
||||
* @param decompressOptions {import('decompress').DecompressOptions}
|
||||
*/
|
||||
exports.downloadUnzipAll = async (
|
||||
url,
|
||||
|
92
arduino-ide-extension/scripts/utils.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Clones something from GitHub and builds it with `Golang`.
|
||||
*
|
||||
* @param version {object} the version object.
|
||||
* @param destinationPath {string} the absolute path of the output binary. For example, `C:\\folder\\arduino-cli.exe` or `/path/to/arduino-language-server`
|
||||
* @param taskName {string} for the CLI logging . Can be `'CLI'` or `'language-server'`, etc.
|
||||
*/
|
||||
exports.goBuildFromGit = (version, destinationPath, taskName) => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const temp = require('temp');
|
||||
const shell = require('shelljs');
|
||||
|
||||
// We assume an object with `owner`, `repo`, commitish?` properties.
|
||||
if (typeof version !== 'object') {
|
||||
shell.echo(
|
||||
`Expected a \`{ owner, repo, commitish }\` object. Got <${version}> instead.`
|
||||
);
|
||||
}
|
||||
const { owner, repo, commitish } = version;
|
||||
if (!owner) {
|
||||
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
|
||||
shell.exit(1);
|
||||
}
|
||||
if (!repo) {
|
||||
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
|
||||
shell.exit(1);
|
||||
}
|
||||
const url = `https://github.com/${owner}/${repo}.git`;
|
||||
shell.echo(
|
||||
`Building ${taskName} from ${url}. Commitish: ${
|
||||
commitish ? commitish : 'HEAD'
|
||||
}`
|
||||
);
|
||||
|
||||
if (fs.existsSync(destinationPath)) {
|
||||
shell.echo(
|
||||
`Skipping the ${taskName} build because it already exists: ${destinationPath}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const buildFolder = path.join(__dirname, '..', 'build');
|
||||
if (shell.mkdir('-p', buildFolder).code !== 0) {
|
||||
shell.echo('Could not create build folder.');
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const tempRepoPath = temp.mkdirSync();
|
||||
shell.echo(`>>> Cloning ${taskName} source to ${tempRepoPath}...`);
|
||||
if (shell.exec(`git clone ${url} ${tempRepoPath}`).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`<<< Cloned ${taskName} repo.`);
|
||||
|
||||
if (commitish) {
|
||||
shell.echo(`>>> Checking out ${commitish}...`);
|
||||
if (shell.exec(`git -C ${tempRepoPath} checkout ${commitish}`).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`<<< Checked out ${commitish}.`);
|
||||
}
|
||||
|
||||
shell.echo(`>>> Building the ${taskName}...`);
|
||||
if (shell.exec('go build', { cwd: tempRepoPath }).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`<<< Done ${taskName} build.`);
|
||||
|
||||
const binName = path.basename(destinationPath);
|
||||
if (!fs.existsSync(path.join(tempRepoPath, binName))) {
|
||||
shell.echo(
|
||||
`Could not find the ${taskName} at ${path.join(tempRepoPath, binName)}.`
|
||||
);
|
||||
shell.exit(1);
|
||||
}
|
||||
|
||||
const binPath = path.join(tempRepoPath, binName);
|
||||
shell.echo(
|
||||
`>>> Copying ${taskName} from ${binPath} to ${destinationPath}...`
|
||||
);
|
||||
if (shell.cp(binPath, destinationPath).code !== 0) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`<<< Copied the ${taskName}.`);
|
||||
|
||||
shell.echo(`<<< Verifying ${taskName}...`);
|
||||
if (!fs.existsSync(destinationPath)) {
|
||||
shell.exit(1);
|
||||
}
|
||||
shell.echo(`>>> Verified ${taskName}.`);
|
||||
};
|
@@ -1,21 +0,0 @@
|
||||
import { Command } from '@theia/core/lib/common/command';
|
||||
|
||||
/**
|
||||
* @deprecated all these commands should go under contributions and have their command, menu, keybinding, and toolbar contributions.
|
||||
*/
|
||||
export namespace ArduinoCommands {
|
||||
export const TOGGLE_COMPILE_FOR_DEBUG: Command = {
|
||||
id: 'arduino-toggle-compile-for-debug',
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlike `OPEN_SKETCH`, it opens all files from a sketch folder. (ino, cpp, etc...)
|
||||
*/
|
||||
export const OPEN_SKETCH_FILES: Command = {
|
||||
id: 'arduino-open-sketch-files',
|
||||
};
|
||||
|
||||
export const OPEN_BOARDS_DIALOG: Command = {
|
||||
id: 'arduino-open-boards-dialog',
|
||||
};
|
||||
}
|
@@ -1,37 +1,22 @@
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import {
|
||||
BoardsService,
|
||||
SketchesService,
|
||||
ExecutableService,
|
||||
Sketch,
|
||||
LibraryService,
|
||||
ArduinoDaemon,
|
||||
} from '../common/protocol';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import { SketchesService } from '../common/protocol';
|
||||
import {
|
||||
MAIN_MENU_BAR,
|
||||
MenuContribution,
|
||||
MenuModelRegistry,
|
||||
ILogger,
|
||||
DisposableCollection,
|
||||
} from '@theia/core';
|
||||
import {
|
||||
Dialog,
|
||||
FrontendApplication,
|
||||
FrontendApplicationContribution,
|
||||
LocalStorageService,
|
||||
OnWillStopAction,
|
||||
SaveableWidget,
|
||||
StatusBar,
|
||||
StatusBarAlignment,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
||||
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
|
||||
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
@@ -39,46 +24,29 @@ import {
|
||||
TabBarToolbarContribution,
|
||||
TabBarToolbarRegistry,
|
||||
} from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import {
|
||||
CommandContribution,
|
||||
CommandRegistry,
|
||||
} from '@theia/core/lib/common/command';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import {
|
||||
EditorCommands,
|
||||
EditorMainMenu,
|
||||
EditorManager,
|
||||
EditorOpenerOptions,
|
||||
} from '@theia/editor/lib/browser';
|
||||
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 { FileService } from '@theia/filesystem/lib/browser/file-service';
|
||||
import { FileChangeType } from '@theia/filesystem/lib/browser';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { ArduinoCommands } from './arduino-commands';
|
||||
import { BoardsConfig } from './boards/boards-config';
|
||||
import { BoardsConfigDialog } from './boards/boards-config-dialog';
|
||||
import { BoardsServiceProvider } from './boards/boards-service-provider';
|
||||
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
|
||||
import { EditorMode } from './editor-mode';
|
||||
import { ArduinoMenus } from './menu/arduino-menus';
|
||||
import { MonitorViewContribution } from './serial/monitor/monitor-view-contribution';
|
||||
import { ArduinoToolbar } from './toolbar/arduino-toolbar';
|
||||
import { ArduinoPreferences } from './arduino-preferences';
|
||||
import {
|
||||
CurrentSketch,
|
||||
SketchesServiceClientImpl,
|
||||
} from '../common/protocol/sketches-service-client-impl';
|
||||
import { ArduinoPreferences } from './arduino-preferences';
|
||||
import { BoardsServiceProvider } from './boards/boards-service-provider';
|
||||
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
|
||||
import { SaveAsSketch } from './contributions/save-as-sketch';
|
||||
import { IDEUpdaterDialog } from './dialogs/ide-updater/ide-updater-dialog';
|
||||
import { IDEUpdater } from '../common/protocol/ide-updater';
|
||||
import { FileSystemFrontendContribution } from '@theia/filesystem/lib/browser/filesystem-frontend-contribution';
|
||||
import { HostedPluginEvents } from './hosted-plugin-events';
|
||||
|
||||
const INIT_LIBS_AND_PACKAGES = 'initializedLibsAndPackages';
|
||||
export const SKIP_IDE_VERSION = 'skipIDEVersion';
|
||||
import { ArduinoMenus } from './menu/arduino-menus';
|
||||
import { MonitorViewContribution } from './serial/monitor/monitor-view-contribution';
|
||||
import { ArduinoToolbar } from './toolbar/arduino-toolbar';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { SerialPlotterContribution } from './serial/plotter/plotter-frontend-contribution';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoFrontendContribution
|
||||
@@ -89,48 +57,18 @@ export class ArduinoFrontendContribution
|
||||
MenuContribution,
|
||||
ColorContribution
|
||||
{
|
||||
@inject(ILogger)
|
||||
private readonly logger: ILogger;
|
||||
|
||||
@inject(MessageService)
|
||||
private readonly messageService: MessageService;
|
||||
|
||||
@inject(BoardsService)
|
||||
private readonly boardsService: BoardsService;
|
||||
|
||||
@inject(LibraryService)
|
||||
private readonly libraryService: LibraryService;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
private readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
@inject(EditorManager)
|
||||
private readonly editorManager: EditorManager;
|
||||
|
||||
@inject(FileService)
|
||||
private readonly fileService: FileService;
|
||||
private readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
@inject(SketchesService)
|
||||
private readonly sketchService: SketchesService;
|
||||
|
||||
@inject(BoardsConfigDialog)
|
||||
private readonly boardsConfigDialog: BoardsConfigDialog;
|
||||
|
||||
@inject(CommandRegistry)
|
||||
private readonly commandRegistry: CommandRegistry;
|
||||
|
||||
@inject(StatusBar)
|
||||
private readonly statusBar: StatusBar;
|
||||
|
||||
@inject(EditorMode)
|
||||
private readonly editorMode: EditorMode;
|
||||
|
||||
@inject(HostedPluginEvents)
|
||||
private readonly hostedPluginEvents: HostedPluginEvents;
|
||||
|
||||
@inject(ExecutableService)
|
||||
private readonly executableService: ExecutableService;
|
||||
|
||||
@inject(ArduinoPreferences)
|
||||
private readonly arduinoPreferences: ArduinoPreferences;
|
||||
|
||||
@@ -140,49 +78,8 @@ export class ArduinoFrontendContribution
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
@inject(LocalStorageService)
|
||||
private readonly localStorageService: LocalStorageService;
|
||||
|
||||
@inject(FileSystemFrontendContribution)
|
||||
private readonly fileSystemFrontendContribution: FileSystemFrontendContribution;
|
||||
|
||||
@inject(IDEUpdater)
|
||||
private readonly updater: IDEUpdater;
|
||||
|
||||
@inject(IDEUpdaterDialog)
|
||||
private readonly updaterDialog: IDEUpdaterDialog;
|
||||
|
||||
@inject(ArduinoDaemon)
|
||||
private readonly daemon: ArduinoDaemon;
|
||||
|
||||
protected invalidConfigPopup:
|
||||
| Promise<void | 'No' | 'Yes' | undefined>
|
||||
| undefined;
|
||||
protected toDisposeOnStop = new DisposableCollection();
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
const isFirstStartup = !(await this.localStorageService.getData(
|
||||
INIT_LIBS_AND_PACKAGES
|
||||
));
|
||||
if (isFirstStartup) {
|
||||
await this.localStorageService.setData(INIT_LIBS_AND_PACKAGES, true);
|
||||
const avrPackage = await this.boardsService.getBoardPackage({
|
||||
id: 'arduino:avr',
|
||||
});
|
||||
const builtInLibrary = (
|
||||
await this.libraryService.search({
|
||||
query: 'Arduino_BuiltIn',
|
||||
})
|
||||
)[0];
|
||||
|
||||
!!avrPackage && (await this.boardsService.install({ item: avrPackage }));
|
||||
!!builtInLibrary &&
|
||||
(await this.libraryService.install({
|
||||
item: builtInLibrary,
|
||||
installDependencies: true,
|
||||
}));
|
||||
}
|
||||
if (!window.navigator.onLine) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
this.messageService.warn(
|
||||
@@ -192,241 +89,32 @@ export class ArduinoFrontendContribution
|
||||
)
|
||||
);
|
||||
}
|
||||
const updateStatusBar = ({
|
||||
selectedBoard,
|
||||
selectedPort,
|
||||
}: BoardsConfig.Config) => {
|
||||
this.statusBar.setElement('arduino-selected-board', {
|
||||
alignment: StatusBarAlignment.RIGHT,
|
||||
text: selectedBoard
|
||||
? `$(microchip) ${selectedBoard.name}`
|
||||
: `$(close) ${nls.localize(
|
||||
'arduino/common/noBoardSelected',
|
||||
'No board selected'
|
||||
)}`,
|
||||
className: 'arduino-selected-board',
|
||||
});
|
||||
if (selectedBoard) {
|
||||
this.statusBar.setElement('arduino-selected-port', {
|
||||
alignment: StatusBarAlignment.RIGHT,
|
||||
text: selectedPort
|
||||
? nls.localize(
|
||||
'arduino/common/selectedOn',
|
||||
'on {0}',
|
||||
selectedPort.address
|
||||
)
|
||||
: nls.localize('arduino/common/notConnected', '[not connected]'),
|
||||
className: 'arduino-selected-port',
|
||||
});
|
||||
}
|
||||
};
|
||||
this.boardsServiceClientImpl.onBoardsConfigChanged(updateStatusBar);
|
||||
updateStatusBar(this.boardsServiceClientImpl.boardsConfig);
|
||||
this.appStateService.reachedState('ready').then(async () => {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (
|
||||
CurrentSketch.isValid(sketch) &&
|
||||
!(await this.sketchService.isTemp(sketch))
|
||||
) {
|
||||
this.toDisposeOnStop.push(this.fileService.watch(new URI(sketch.uri)));
|
||||
this.toDisposeOnStop.push(
|
||||
this.fileService.onDidFilesChange(async (event) => {
|
||||
for (const { type, resource } of event.changes) {
|
||||
if (
|
||||
type === FileChangeType.ADDED &&
|
||||
resource.parent.toString() === sketch.uri
|
||||
) {
|
||||
const reloadedSketch = await this.sketchService.loadSketch(
|
||||
sketch.uri
|
||||
);
|
||||
if (Sketch.isInSketch(resource, reloadedSketch)) {
|
||||
this.ensureOpened(resource.toString(), true, {
|
||||
mode: 'open',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async onStart(app: FrontendApplication): Promise<void> {
|
||||
this.updater
|
||||
.init(
|
||||
this.arduinoPreferences.get('arduino.ide.updateChannel'),
|
||||
this.arduinoPreferences.get('arduino.ide.updateBaseUrl')
|
||||
)
|
||||
.then(() => this.updater.checkForUpdates(true))
|
||||
.then(async (updateInfo) => {
|
||||
if (!updateInfo) return;
|
||||
const versionToSkip = await this.localStorageService.getData<string>(
|
||||
SKIP_IDE_VERSION
|
||||
);
|
||||
if (versionToSkip === updateInfo.version) return;
|
||||
this.updaterDialog.open(updateInfo);
|
||||
})
|
||||
.catch((e) => {
|
||||
this.messageService.error(
|
||||
nls.localize(
|
||||
'arduino/ide-updater/errorCheckingForUpdates',
|
||||
'Error while checking for Arduino IDE updates.\n{0}',
|
||||
e.message
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
const start = async ({ selectedBoard }: BoardsConfig.Config) => {
|
||||
if (selectedBoard) {
|
||||
const { name, fqbn } = selectedBoard;
|
||||
if (fqbn) {
|
||||
this.startLanguageServer(fqbn, name);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.boardsServiceClientImpl.onBoardsConfigChanged(start);
|
||||
this.hostedPluginEvents.onPluginsDidStart(() =>
|
||||
start(this.boardsServiceClientImpl.boardsConfig)
|
||||
);
|
||||
this.hostedPluginEvents.onPluginsWillUnload(
|
||||
() => (this.languageServerFqbn = undefined)
|
||||
);
|
||||
this.arduinoPreferences.onPreferenceChanged((event) => {
|
||||
if (event.newValue !== event.oldValue) {
|
||||
switch (event.preferenceName) {
|
||||
case 'arduino.language.log':
|
||||
start(this.boardsServiceClientImpl.boardsConfig);
|
||||
break;
|
||||
case 'arduino.window.zoomLevel':
|
||||
if (typeof event.newValue === 'number') {
|
||||
const webContents = remote.getCurrentWebContents();
|
||||
webContents.setZoomLevel(event.newValue || 0);
|
||||
}
|
||||
break;
|
||||
case 'arduino.ide.updateChannel':
|
||||
case 'arduino.ide.updateBaseUrl':
|
||||
this.updater.init(
|
||||
this.arduinoPreferences.get('arduino.ide.updateChannel'),
|
||||
this.arduinoPreferences.get('arduino.ide.updateBaseUrl')
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.arduinoPreferences.ready.then(() => {
|
||||
const webContents = remote.getCurrentWebContents();
|
||||
const zoomLevel = this.arduinoPreferences.get('arduino.window.zoomLevel');
|
||||
webContents.setZoomLevel(zoomLevel);
|
||||
});
|
||||
|
||||
app.shell.leftPanelHandler.removeBottomMenu('settings-menu');
|
||||
|
||||
this.fileSystemFrontendContribution.onDidChangeEditorFile(
|
||||
({ type, editor }) => {
|
||||
if (type === FileChangeType.DELETED) {
|
||||
const editorWidget = editor;
|
||||
if (SaveableWidget.is(editorWidget)) {
|
||||
editorWidget.closeWithoutSaving();
|
||||
} else {
|
||||
editorWidget.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onStop(): void {
|
||||
this.toDisposeOnStop.dispose();
|
||||
}
|
||||
|
||||
protected languageServerFqbn?: string;
|
||||
protected languageServerStartMutex = new Mutex();
|
||||
protected async startLanguageServer(
|
||||
fqbn: string,
|
||||
name: string | undefined
|
||||
): Promise<void> {
|
||||
const port = await this.daemon.tryGetPort();
|
||||
if (!port) {
|
||||
return;
|
||||
}
|
||||
const release = await this.languageServerStartMutex.acquire();
|
||||
try {
|
||||
await this.hostedPluginEvents.didStart;
|
||||
const details = await this.boardsService.getBoardDetails({ fqbn });
|
||||
if (!details) {
|
||||
// Core is not installed for the selected board.
|
||||
console.info(
|
||||
`Could not start language server for ${fqbn}. The core is not installed for the board.`
|
||||
this.appStateService.reachedState('ready').then(() =>
|
||||
this.arduinoPreferences.ready.then(() => {
|
||||
const webContents = remote.getCurrentWebContents();
|
||||
const zoomLevel = this.arduinoPreferences.get(
|
||||
'arduino.window.zoomLevel'
|
||||
);
|
||||
if (this.languageServerFqbn) {
|
||||
try {
|
||||
await this.commandRegistry.executeCommand(
|
||||
'arduino.languageserver.stop'
|
||||
);
|
||||
console.info(
|
||||
`Stopped language server process for ${this.languageServerFqbn}.`
|
||||
);
|
||||
this.languageServerFqbn = undefined;
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Failed to start language server process for ${this.languageServerFqbn}`,
|
||||
e
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (fqbn === this.languageServerFqbn) {
|
||||
// NOOP
|
||||
return;
|
||||
}
|
||||
this.logger.info(`Starting language server: ${fqbn}`);
|
||||
const log = this.arduinoPreferences.get('arduino.language.log');
|
||||
let currentSketchPath: string | undefined = undefined;
|
||||
if (log) {
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
if (CurrentSketch.isValid(currentSketch)) {
|
||||
currentSketchPath = await this.fileService.fsPath(
|
||||
new URI(currentSketch.uri)
|
||||
);
|
||||
}
|
||||
}
|
||||
const { clangdUri, lsUri } = await this.executableService.list();
|
||||
const [clangdPath, lsPath] = await Promise.all([
|
||||
this.fileService.fsPath(new URI(clangdUri)),
|
||||
this.fileService.fsPath(new URI(lsUri)),
|
||||
]);
|
||||
|
||||
this.languageServerFqbn = await Promise.race([
|
||||
new Promise<undefined>((_, reject) =>
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${20_000} ms.`)),
|
||||
20_000
|
||||
)
|
||||
),
|
||||
this.commandRegistry.executeCommand<string>(
|
||||
'arduino.languageserver.start',
|
||||
{
|
||||
lsPath,
|
||||
cliDaemonAddr: `localhost:${port}`,
|
||||
clangdPath,
|
||||
log: currentSketchPath ? currentSketchPath : log,
|
||||
cliDaemonInstance: '1',
|
||||
board: {
|
||||
fqbn,
|
||||
name: name ? `"${name}"` : undefined,
|
||||
},
|
||||
}
|
||||
),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.log(`Failed to start language server for ${fqbn}`, e);
|
||||
this.languageServerFqbn = undefined;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
webContents.setZoomLevel(zoomLevel);
|
||||
})
|
||||
);
|
||||
// Removes the _Settings_ (cog) icon from the left sidebar
|
||||
app.shell.leftPanelHandler.removeBottomMenu('settings-menu');
|
||||
}
|
||||
|
||||
registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
@@ -436,13 +124,21 @@ export class ArduinoFrontendContribution
|
||||
<BoardsToolBarItem
|
||||
key="boardsToolbarItem"
|
||||
commands={this.commandRegistry}
|
||||
boardsServiceClient={this.boardsServiceClientImpl}
|
||||
boardsServiceProvider={this.boardsServiceProvider}
|
||||
/>
|
||||
),
|
||||
isVisible: (widget) =>
|
||||
ArduinoToolbar.is(widget) && widget.side === 'left',
|
||||
priority: 7,
|
||||
});
|
||||
registry.registerItem({
|
||||
id: 'toggle-serial-plotter',
|
||||
command: SerialPlotterContribution.Commands.OPEN_TOOLBAR.id,
|
||||
tooltip: nls.localize(
|
||||
'arduino/serial/openSerialPlotter',
|
||||
'Serial Plotter'
|
||||
),
|
||||
});
|
||||
registry.registerItem({
|
||||
id: 'toggle-serial-monitor',
|
||||
command: MonitorViewContribution.TOGGLE_SERIAL_MONITOR_TOOLBAR,
|
||||
@@ -451,24 +147,6 @@ export class ArduinoFrontendContribution
|
||||
}
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG, {
|
||||
execute: () => this.editorMode.toggleCompileForDebug(),
|
||||
isToggled: () => this.editorMode.compileForDebug,
|
||||
});
|
||||
registry.registerCommand(ArduinoCommands.OPEN_SKETCH_FILES, {
|
||||
execute: async (uri: URI) => {
|
||||
this.openSketchFiles(uri);
|
||||
},
|
||||
});
|
||||
registry.registerCommand(ArduinoCommands.OPEN_BOARDS_DIALOG, {
|
||||
execute: async (query?: string | undefined) => {
|
||||
const boardsConfig = await this.boardsConfigDialog.open(query);
|
||||
if (boardsConfig) {
|
||||
this.boardsServiceClientImpl.boardsConfig = boardsConfig;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
for (const command of [
|
||||
EditorCommands.SPLIT_EDITOR_DOWN,
|
||||
EditorCommands.SPLIT_EDITOR_LEFT,
|
||||
@@ -501,104 +179,12 @@ export class ArduinoFrontendContribution
|
||||
ArduinoMenus.TOOLS,
|
||||
nls.localize('arduino/menu/tools', 'Tools')
|
||||
);
|
||||
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
|
||||
commandId: ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG.id,
|
||||
label: nls.localize(
|
||||
'arduino/debug/optimizeForDebugging',
|
||||
'Optimize for Debugging'
|
||||
),
|
||||
order: '5',
|
||||
});
|
||||
}
|
||||
|
||||
protected async openSketchFiles(uri: URI): 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 (mainFileUri.endsWith('.pde')) {
|
||||
const message = nls.localize(
|
||||
'arduino/common/oldFormat',
|
||||
"The '{0}' still uses the old `.pde` format. Do you want to switch to the new `.ino` extension?",
|
||||
sketch.name
|
||||
);
|
||||
const yes = nls.localize('vscode/extensionsUtils/yes', 'Yes');
|
||||
this.messageService
|
||||
.info(message, nls.localize('arduino/common/later', 'Later'), yes)
|
||||
.then(async (answer) => {
|
||||
if (answer === yes) {
|
||||
this.commandRegistry.executeCommand(
|
||||
SaveAsSketch.Commands.SAVE_AS_SKETCH.id,
|
||||
{
|
||||
execOnlyIfTemp: false,
|
||||
openAfterMove: true,
|
||||
wipeOriginal: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
const message = e instanceof Error ? e.message : JSON.stringify(e);
|
||||
this.messageService.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected async ensureOpened(
|
||||
uri: string,
|
||||
forceOpen = false,
|
||||
options?: EditorOpenerOptions | undefined
|
||||
): Promise<unknown> {
|
||||
const widget = this.editorManager.all.find(
|
||||
(widget) => widget.editor.uri.toString() === uri
|
||||
);
|
||||
if (!widget || forceOpen) {
|
||||
return this.editorManager.open(
|
||||
new URI(uri),
|
||||
options ?? {
|
||||
mode: 'reveal',
|
||||
preview: false,
|
||||
counter: 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
registerColors(colors: ColorRegistry): void {
|
||||
colors.register(
|
||||
{
|
||||
id: 'arduino.branding.primary',
|
||||
defaults: {
|
||||
dark: 'statusBar.background',
|
||||
light: 'statusBar.background',
|
||||
},
|
||||
description:
|
||||
'The primary branding color, such as dialog titles, library, and board manager list labels.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.branding.secondary',
|
||||
defaults: {
|
||||
dark: 'statusBar.background',
|
||||
light: 'statusBar.background',
|
||||
},
|
||||
description:
|
||||
'Secondary branding color for list selections, dropdowns, and widget borders.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.foreground',
|
||||
defaults: {
|
||||
dark: 'editorWidget.background',
|
||||
light: 'editorWidget.background',
|
||||
hc: 'editorWidget.background',
|
||||
},
|
||||
description:
|
||||
'Color of the Arduino IDE foreground which is used for dialogs, such as the Select Board dialog.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.background',
|
||||
id: 'arduino.toolbar.button.background',
|
||||
defaults: {
|
||||
dark: 'button.background',
|
||||
light: 'button.background',
|
||||
@@ -608,15 +194,35 @@ export class ArduinoFrontendContribution
|
||||
'Background color of the toolbar items. Such as Upload, Verify, etc.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.hoverBackground',
|
||||
id: 'arduino.toolbar.button.hoverBackground',
|
||||
defaults: {
|
||||
dark: 'button.hoverBackground',
|
||||
light: 'button.foreground',
|
||||
hc: 'textLink.foreground',
|
||||
light: 'button.hoverBackground',
|
||||
hc: 'button.background',
|
||||
},
|
||||
description:
|
||||
'Background color of the toolbar items when hovering over them. Such as Upload, Verify, etc.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.button.secondary.label',
|
||||
defaults: {
|
||||
dark: 'secondaryButton.foreground',
|
||||
light: 'button.foreground',
|
||||
hc: 'activityBar.inactiveForeground',
|
||||
},
|
||||
description:
|
||||
'Foreground color of the toolbar items. Such as Serial Monitor and Serial Plotter',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.button.secondary.hoverBackground',
|
||||
defaults: {
|
||||
dark: 'secondaryButton.hoverBackground',
|
||||
light: 'button.hoverBackground',
|
||||
hc: 'textLink.foreground',
|
||||
},
|
||||
description:
|
||||
'Background color of the toolbar items when hovering over them, such as "Serial Monitor" and "Serial Plotter"',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.toggleBackground',
|
||||
defaults: {
|
||||
@@ -628,26 +234,77 @@ export class ArduinoFrontendContribution
|
||||
'Toggle color of the toolbar items when they are currently toggled (the command is in progress)',
|
||||
},
|
||||
{
|
||||
id: 'arduino.output.foreground',
|
||||
id: 'arduino.toolbar.dropdown.border',
|
||||
defaults: {
|
||||
dark: 'editor.foreground',
|
||||
light: 'editor.foreground',
|
||||
hc: 'editor.foreground',
|
||||
dark: 'dropdown.border',
|
||||
light: 'dropdown.border',
|
||||
hc: 'dropdown.border',
|
||||
},
|
||||
description: 'Color of the text in the Output view.',
|
||||
description: 'Border color of the Board Selector.',
|
||||
},
|
||||
|
||||
{
|
||||
id: 'arduino.toolbar.dropdown.borderActive',
|
||||
defaults: {
|
||||
dark: 'focusBorder',
|
||||
light: 'focusBorder',
|
||||
hc: 'focusBorder',
|
||||
},
|
||||
description: "Border color of the Board Selector when it's active",
|
||||
},
|
||||
|
||||
{
|
||||
id: 'arduino.toolbar.dropdown.background',
|
||||
defaults: {
|
||||
dark: 'tab.unfocusedActiveBackground',
|
||||
light: 'dropdown.background',
|
||||
hc: 'dropdown.background',
|
||||
},
|
||||
description: 'Background color of the Board Selector.',
|
||||
},
|
||||
|
||||
{
|
||||
id: 'arduino.toolbar.dropdown.label',
|
||||
defaults: {
|
||||
dark: 'dropdown.foreground',
|
||||
light: 'dropdown.foreground',
|
||||
hc: 'dropdown.foreground',
|
||||
},
|
||||
description: 'Font color of the Board Selector.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.output.background',
|
||||
id: 'arduino.toolbar.dropdown.iconSelected',
|
||||
defaults: {
|
||||
dark: 'editor.background',
|
||||
light: 'editor.background',
|
||||
hc: 'editor.background',
|
||||
dark: 'list.activeSelectionIconForeground',
|
||||
light: 'list.activeSelectionIconForeground',
|
||||
hc: 'list.activeSelectionIconForeground',
|
||||
},
|
||||
description: 'Background color of the Output view.',
|
||||
description:
|
||||
'Color of the selected protocol icon in the Board Selector.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.dropdown.option.backgroundHover',
|
||||
defaults: {
|
||||
dark: 'list.hoverBackground',
|
||||
light: 'list.hoverBackground',
|
||||
hc: 'list.hoverBackground',
|
||||
},
|
||||
description: 'Background color on hover of the Board Selector options.',
|
||||
},
|
||||
{
|
||||
id: 'arduino.toolbar.dropdown.option.backgroundSelected',
|
||||
defaults: {
|
||||
dark: 'list.activeSelectionBackground',
|
||||
light: 'list.activeSelectionBackground',
|
||||
hc: 'list.activeSelectionBackground',
|
||||
},
|
||||
description:
|
||||
'Background color of the selected board in the Board Selector.',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: should be handled by `Close` contribution. https://github.com/arduino/arduino-ide/issues/1016
|
||||
onWillStop(): OnWillStopAction {
|
||||
return {
|
||||
reason: 'temp-sketch',
|
||||
|
@@ -50,13 +50,17 @@ import {
|
||||
ApplicationShell as TheiaApplicationShell,
|
||||
ShellLayoutRestorer as TheiaShellLayoutRestorer,
|
||||
CommonFrontendContribution as TheiaCommonFrontendContribution,
|
||||
DockPanelRenderer as TheiaDockPanelRenderer,
|
||||
TabBarRendererFactory,
|
||||
ContextMenuRenderer,
|
||||
createTreeContainer,
|
||||
TreeWidget,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { MenuContribution } from '@theia/core/lib/common/menu';
|
||||
import { ApplicationShell } from './theia/core/application-shell';
|
||||
import {
|
||||
ApplicationShell,
|
||||
DockPanelRenderer,
|
||||
} from './theia/core/application-shell';
|
||||
import { FrontendApplication } from './theia/core/frontend-application';
|
||||
import {
|
||||
BoardsConfigDialog,
|
||||
@@ -80,10 +84,12 @@ import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browse
|
||||
import { ProblemManager } from './theia/markers/problem-manager';
|
||||
import { BoardsAutoInstaller } from './boards/boards-auto-installer';
|
||||
import { ShellLayoutRestorer } from './theia/core/shell-layout-restorer';
|
||||
import { EditorMode } from './editor-mode';
|
||||
import { ListItemRenderer } from './widgets/component-list/list-item-renderer';
|
||||
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
|
||||
import { MonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service';
|
||||
import {
|
||||
MonacoThemeJson,
|
||||
MonacoThemingService,
|
||||
} from '@theia/monaco/lib/browser/monaco-theming-service';
|
||||
import {
|
||||
ArduinoDaemonPath,
|
||||
ArduinoDaemon,
|
||||
@@ -121,7 +127,6 @@ import { SaveAsSketch } from './contributions/save-as-sketch';
|
||||
import { SaveSketch } from './contributions/save-sketch';
|
||||
import { VerifySketch } from './contributions/verify-sketch';
|
||||
import { UploadSketch } from './contributions/upload-sketch';
|
||||
import { SurveyNotification } from './contributions/survey-notification';
|
||||
import { CommonFrontendContribution } from './theia/core/common-frontend-contribution';
|
||||
import { EditContributions } from './contributions/edit-contributions';
|
||||
import { OpenSketchExternal } from './contributions/open-sketch-external';
|
||||
@@ -164,7 +169,7 @@ import { MonacoTextModelService } from './theia/monaco/monaco-text-model-service
|
||||
import { ResponseServiceImpl } from './response-service-impl';
|
||||
import {
|
||||
ResponseService,
|
||||
ResponseServiceArduino,
|
||||
ResponseServiceClient,
|
||||
ResponseServicePath,
|
||||
} from '../common/protocol/response-service';
|
||||
import { NotificationCenter } from './notification-center';
|
||||
@@ -302,20 +307,46 @@ import { CoreErrorHandler } from './contributions/core-error-handler';
|
||||
import { CompilerErrors } from './contributions/compiler-errors';
|
||||
import { WidgetManager } from './theia/core/widget-manager';
|
||||
import { WidgetManager as TheiaWidgetManager } from '@theia/core/lib/browser/widget-manager';
|
||||
import { StartupTasks } from './widgets/sketchbook/startup-task';
|
||||
import { IndexesUpdateProgress } from './contributions/indexes-update-progress';
|
||||
import { Daemon } from './contributions/daemon';
|
||||
import { FirstStartupInstaller } from './contributions/first-startup-installer';
|
||||
import { OpenSketchFiles } from './contributions/open-sketch-files';
|
||||
import { InoLanguage } from './contributions/ino-language';
|
||||
import { SelectedBoard } from './contributions/selected-board';
|
||||
import { CheckForUpdates } from './contributions/check-for-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';
|
||||
|
||||
MonacoThemingService.register({
|
||||
id: 'arduino-theme',
|
||||
label: 'Light (Arduino)',
|
||||
uiTheme: 'vs',
|
||||
json: require('../../src/browser/data/default.color-theme.json'),
|
||||
});
|
||||
|
||||
MonacoThemingService.register({
|
||||
id: 'arduino-theme-dark',
|
||||
label: 'Dark (Arduino)',
|
||||
uiTheme: 'vs-dark',
|
||||
json: require('../../src/browser/data/dark.color-theme.json'),
|
||||
});
|
||||
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();
|
||||
}
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
// Commands and toolbar items
|
||||
@@ -483,14 +514,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
WorkspaceVariableContribution
|
||||
);
|
||||
|
||||
// Customizing default Theia layout based on the editor mode: `pro-mode` or `classic`.
|
||||
bind(EditorMode).toSelf().inSingletonScope();
|
||||
bind(FrontendApplicationContribution).toService(EditorMode);
|
||||
|
||||
// Survey notification
|
||||
bind(SurveyNotification).toSelf().inSingletonScope();
|
||||
bind(FrontendApplicationContribution).toService(SurveyNotification);
|
||||
|
||||
bind(SurveyNotificationService)
|
||||
.toDynamicValue((context) => {
|
||||
return ElectronIpcConnectionProvider.createProxy(
|
||||
@@ -566,7 +589,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
|
||||
// Disabled reference counter in the editor manager to avoid opening the same editor (with different opener options) multiple times.
|
||||
bind(EditorManager).toSelf().inSingletonScope();
|
||||
rebind(TheiaEditorManager).to(EditorManager);
|
||||
rebind(TheiaEditorManager).toService(EditorManager);
|
||||
|
||||
// replace search icon
|
||||
rebind(TheiaSearchInWorkspaceFactory)
|
||||
@@ -698,6 +721,16 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
Contribution.configure(bind, PlotterFrontendContribution);
|
||||
Contribution.configure(bind, Format);
|
||||
Contribution.configure(bind, CompilerErrors);
|
||||
Contribution.configure(bind, StartupTasks);
|
||||
Contribution.configure(bind, IndexesUpdateProgress);
|
||||
Contribution.configure(bind, Daemon);
|
||||
Contribution.configure(bind, FirstStartupInstaller);
|
||||
Contribution.configure(bind, OpenSketchFiles);
|
||||
Contribution.configure(bind, InoLanguage);
|
||||
Contribution.configure(bind, SelectedBoard);
|
||||
Contribution.configure(bind, CheckForUpdates);
|
||||
Contribution.configure(bind, OpenBoardsConfig);
|
||||
Contribution.configure(bind, SketchFilesTracker);
|
||||
|
||||
// Disabled the quick-pick customization from Theia when multiple formatters are available.
|
||||
// Use the default VS Code behavior, and pick the first one. In the IDE2, clang-format has `exclusive` selectors.
|
||||
@@ -719,7 +752,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
});
|
||||
|
||||
bind(ResponseService).toService(ResponseServiceImpl);
|
||||
bind(ResponseServiceArduino).toService(ResponseServiceImpl);
|
||||
bind(ResponseServiceClient).toService(ResponseServiceImpl);
|
||||
|
||||
bind(NotificationCenter).toSelf().inSingletonScope();
|
||||
bind(FrontendApplicationContribution).toService(NotificationCenter);
|
||||
@@ -795,6 +828,14 @@ 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);
|
||||
|
||||
// Preferences
|
||||
bindArduinoPreferences(bind);
|
||||
|
||||
|
@@ -51,6 +51,14 @@ export const ArduinoConfigSchema: PreferenceSchema = {
|
||||
),
|
||||
default: false,
|
||||
},
|
||||
'arduino.language.realTimeDiagnostics': {
|
||||
type: 'boolean',
|
||||
description: nls.localize(
|
||||
'arduino/preferences/language.realTimeDiagnostics',
|
||||
"If true, the language server provides real-time diagnostics when typing in the editor. It's false by default."
|
||||
),
|
||||
default: false,
|
||||
},
|
||||
'arduino.compile.verbose': {
|
||||
type: 'boolean',
|
||||
description: nls.localize(
|
||||
@@ -177,10 +185,10 @@ export const ArduinoConfigSchema: PreferenceSchema = {
|
||||
),
|
||||
default: true,
|
||||
},
|
||||
'arduino.cloud.sketchSyncEnpoint': {
|
||||
'arduino.cloud.sketchSyncEndpoint': {
|
||||
type: 'string',
|
||||
description: nls.localize(
|
||||
'arduino/preferences/cloud.sketchSyncEnpoint',
|
||||
'arduino/preferences/cloud.sketchSyncEndpoint',
|
||||
'The endpoint used to push and pull sketches from a backend. By default it points to Arduino Cloud API.'
|
||||
),
|
||||
default: 'https://api2.arduino.cc/create',
|
||||
@@ -238,6 +246,7 @@ export const ArduinoConfigSchema: PreferenceSchema = {
|
||||
|
||||
export interface ArduinoConfiguration {
|
||||
'arduino.language.log': boolean;
|
||||
'arduino.language.realTimeDiagnostics': boolean;
|
||||
'arduino.compile.verbose': boolean;
|
||||
'arduino.compile.experimental': boolean;
|
||||
'arduino.compile.revealRange': ErrorRevealStrategy;
|
||||
@@ -254,7 +263,7 @@ export interface ArduinoConfiguration {
|
||||
'arduino.cloud.pull.warn': boolean;
|
||||
'arduino.cloud.push.warn': boolean;
|
||||
'arduino.cloud.pushpublic.warn': boolean;
|
||||
'arduino.cloud.sketchSyncEnpoint': string;
|
||||
'arduino.cloud.sketchSyncEndpoint': string;
|
||||
'arduino.auth.clientID': string;
|
||||
'arduino.auth.domain': string;
|
||||
'arduino.auth.audience': string;
|
||||
|
@@ -5,19 +5,37 @@ import {
|
||||
BoardsService,
|
||||
BoardsPackage,
|
||||
Board,
|
||||
Port,
|
||||
} from '../../common/protocol/boards-service';
|
||||
import { BoardsServiceProvider } from './boards-service-provider';
|
||||
import { BoardsConfig } from './boards-config';
|
||||
import { Installable, ResponseServiceArduino } from '../../common/protocol';
|
||||
import { Installable, ResponseServiceClient } from '../../common/protocol';
|
||||
import { BoardsListWidgetFrontendContribution } from './boards-widget-frontend-contribution';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { NotificationCenter } from '../notification-center';
|
||||
|
||||
interface AutoInstallPromptAction {
|
||||
// isAcceptance, whether or not the action indicates acceptance of auto-install proposal
|
||||
isAcceptance?: boolean;
|
||||
key: string;
|
||||
handler: (...args: unknown[]) => unknown;
|
||||
}
|
||||
|
||||
type AutoInstallPromptActions = AutoInstallPromptAction[];
|
||||
|
||||
/**
|
||||
* Listens on `BoardsConfig.Config` changes, if a board is selected which does not
|
||||
* have the corresponding core installed, it proposes the user to install the core.
|
||||
*/
|
||||
|
||||
// * Cases in which we do not show the auto-install prompt:
|
||||
// 1. When a related platform is already installed
|
||||
// 2. When a prompt is already showing in the UI
|
||||
// 3. When a board is unplugged
|
||||
@injectable()
|
||||
export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
@inject(NotificationCenter)
|
||||
private readonly notificationCenter: NotificationCenter;
|
||||
|
||||
@inject(MessageService)
|
||||
protected readonly messageService: MessageService;
|
||||
|
||||
@@ -27,8 +45,8 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClient: BoardsServiceProvider;
|
||||
|
||||
@inject(ResponseServiceArduino)
|
||||
protected readonly responseService: ResponseServiceArduino;
|
||||
@inject(ResponseServiceClient)
|
||||
protected readonly responseService: ResponseServiceClient;
|
||||
|
||||
@inject(BoardsListWidgetFrontendContribution)
|
||||
protected readonly boardsManagerFrontendContribution: BoardsListWidgetFrontendContribution;
|
||||
@@ -36,97 +54,228 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
|
||||
// Workaround for https://github.com/eclipse-theia/theia/issues/9349
|
||||
protected notifications: Board[] = [];
|
||||
|
||||
// * "refusal" meaning a "prompt action" not accepting the auto-install offer ("X" or "install manually")
|
||||
// we can use "portSelectedOnLastRefusal" to deduce when a board is unplugged after a user has "refused"
|
||||
// an auto-install prompt. Important to know as we do not want "an unplug" to trigger a "refused" prompt
|
||||
// showing again
|
||||
private portSelectedOnLastRefusal: Port | undefined;
|
||||
private lastRefusedPackageId: string | undefined;
|
||||
|
||||
onStart(): void {
|
||||
this.boardsServiceClient.onBoardsConfigChanged(
|
||||
this.ensureCoreExists.bind(this)
|
||||
);
|
||||
this.ensureCoreExists(this.boardsServiceClient.boardsConfig);
|
||||
}
|
||||
const setEventListeners = () => {
|
||||
this.boardsServiceClient.onBoardsConfigChanged((config) => {
|
||||
const { selectedBoard, selectedPort } = config;
|
||||
|
||||
protected ensureCoreExists(config: BoardsConfig.Config): void {
|
||||
const { selectedBoard, selectedPort } = config;
|
||||
if (
|
||||
selectedBoard &&
|
||||
selectedPort &&
|
||||
!this.notifications.find((board) => Board.sameAs(board, selectedBoard))
|
||||
) {
|
||||
this.notifications.push(selectedBoard);
|
||||
this.boardsService.search({}).then((packages) => {
|
||||
// filter packagesForBoard selecting matches from the cli (installed packages)
|
||||
// and matches based on the board name
|
||||
// NOTE: this ensures the Deprecated & new packages are all in the array
|
||||
// so that we can check if any of the valid packages is already installed
|
||||
const packagesForBoard = packages.filter(
|
||||
(pkg) =>
|
||||
BoardsPackage.contains(selectedBoard, pkg) ||
|
||||
pkg.boards.some((board) => board.name === selectedBoard.name)
|
||||
);
|
||||
const boardWasUnplugged =
|
||||
!selectedPort && this.portSelectedOnLastRefusal;
|
||||
|
||||
this.clearLastRefusedPromptInfo();
|
||||
|
||||
// check if one of the packages for the board is already installed. if so, no hint
|
||||
if (
|
||||
packagesForBoard.some(({ installedVersion }) => !!installedVersion)
|
||||
boardWasUnplugged ||
|
||||
!selectedBoard ||
|
||||
this.promptAlreadyShowingForBoard(selectedBoard)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// filter the installable (not installed) packages,
|
||||
// CLI returns the packages already sorted with the deprecated ones at the end of the list
|
||||
// in order to ensure the new ones are preferred
|
||||
const candidates = packagesForBoard.filter(
|
||||
({ installable, installedVersion }) =>
|
||||
installable && !installedVersion
|
||||
);
|
||||
this.ensureCoreExists(selectedBoard, selectedPort);
|
||||
});
|
||||
|
||||
const candidate = candidates[0];
|
||||
if (candidate) {
|
||||
const version = candidate.availableVersions[0]
|
||||
? `[v ${candidate.availableVersions[0]}]`
|
||||
: '';
|
||||
const yes = nls.localize('vscode/extensionsUtils/yes', 'Yes');
|
||||
const manualInstall = nls.localize(
|
||||
'arduino/board/installManually',
|
||||
'Install Manually'
|
||||
);
|
||||
// tslint:disable-next-line:max-line-length
|
||||
this.messageService
|
||||
.info(
|
||||
nls.localize(
|
||||
'arduino/board/installNow',
|
||||
'The "{0} {1}" core has to be installed for the currently selected "{2}" board. Do you want to install it now?',
|
||||
candidate.name,
|
||||
version,
|
||||
selectedBoard.name
|
||||
),
|
||||
manualInstall,
|
||||
yes
|
||||
)
|
||||
.then(async (answer) => {
|
||||
const index = this.notifications.findIndex((board) =>
|
||||
Board.sameAs(board, selectedBoard)
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.notifications.splice(index, 1);
|
||||
}
|
||||
if (answer === yes) {
|
||||
await Installable.installWithProgress({
|
||||
installable: this.boardsService,
|
||||
item: candidate,
|
||||
messageService: this.messageService,
|
||||
responseService: this.responseService,
|
||||
version: candidate.availableVersions[0],
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (answer === manualInstall) {
|
||||
this.boardsManagerFrontendContribution
|
||||
.openView({ reveal: true })
|
||||
.then((widget) =>
|
||||
widget.refresh(candidate.name.toLocaleLowerCase())
|
||||
);
|
||||
}
|
||||
});
|
||||
// we "clearRefusedPackageInfo" if a "refused" package is eventually
|
||||
// installed, though this is not strictly necessary. It's more of a
|
||||
// cleanup, to ensure the related variables are representative of
|
||||
// current state.
|
||||
this.notificationCenter.onPlatformDidInstall((installed) => {
|
||||
if (this.lastRefusedPackageId === installed.item.id) {
|
||||
this.clearLastRefusedPromptInfo();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// we should invoke this.ensureCoreExists only once we're sure
|
||||
// everything has been reconciled
|
||||
this.boardsServiceClient.reconciled.then(() => {
|
||||
const { selectedBoard, selectedPort } =
|
||||
this.boardsServiceClient.boardsConfig;
|
||||
|
||||
if (selectedBoard) {
|
||||
this.ensureCoreExists(selectedBoard, selectedPort);
|
||||
}
|
||||
|
||||
setEventListeners();
|
||||
});
|
||||
}
|
||||
|
||||
private removeNotificationByBoard(selectedBoard: Board): void {
|
||||
const index = this.notifications.findIndex((notification) =>
|
||||
Board.sameAs(notification, selectedBoard)
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.notifications.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private clearLastRefusedPromptInfo(): void {
|
||||
this.lastRefusedPackageId = undefined;
|
||||
this.portSelectedOnLastRefusal = undefined;
|
||||
}
|
||||
|
||||
private setLastRefusedPromptInfo(
|
||||
packageId: string,
|
||||
selectedPort?: Port
|
||||
): void {
|
||||
this.lastRefusedPackageId = packageId;
|
||||
this.portSelectedOnLastRefusal = selectedPort;
|
||||
}
|
||||
|
||||
private promptAlreadyShowingForBoard(board: Board): boolean {
|
||||
return Boolean(
|
||||
this.notifications.find((notification) =>
|
||||
Board.sameAs(notification, board)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected ensureCoreExists(selectedBoard: Board, selectedPort?: Port): void {
|
||||
this.notifications.push(selectedBoard);
|
||||
this.boardsService.search({}).then((packages) => {
|
||||
const candidate = this.getInstallCandidate(packages, selectedBoard);
|
||||
|
||||
if (candidate) {
|
||||
this.showAutoInstallPrompt(candidate, selectedBoard, selectedPort);
|
||||
} else {
|
||||
this.removeNotificationByBoard(selectedBoard);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getInstallCandidate(
|
||||
packages: BoardsPackage[],
|
||||
selectedBoard: Board
|
||||
): BoardsPackage | undefined {
|
||||
// filter packagesForBoard selecting matches from the cli (installed packages)
|
||||
// and matches based on the board name
|
||||
// NOTE: this ensures the Deprecated & new packages are all in the array
|
||||
// so that we can check if any of the valid packages is already installed
|
||||
const packagesForBoard = packages.filter(
|
||||
(pkg) =>
|
||||
BoardsPackage.contains(selectedBoard, pkg) ||
|
||||
pkg.boards.some((board) => board.name === selectedBoard.name)
|
||||
);
|
||||
|
||||
// check if one of the packages for the board is already installed. if so, no hint
|
||||
if (packagesForBoard.some(({ installedVersion }) => !!installedVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// filter the installable (not installed) packages,
|
||||
// CLI returns the packages already sorted with the deprecated ones at the end of the list
|
||||
// in order to ensure the new ones are preferred
|
||||
const candidates = packagesForBoard.filter(
|
||||
({ installable, installedVersion }) => installable && !installedVersion
|
||||
);
|
||||
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
private showAutoInstallPrompt(
|
||||
candidate: BoardsPackage,
|
||||
selectedBoard: Board,
|
||||
selectedPort?: Port
|
||||
): void {
|
||||
const candidateName = candidate.name;
|
||||
const version = candidate.availableVersions[0]
|
||||
? `[v ${candidate.availableVersions[0]}]`
|
||||
: '';
|
||||
|
||||
const info = this.generatePromptInfoText(
|
||||
candidateName,
|
||||
version,
|
||||
selectedBoard.name
|
||||
);
|
||||
|
||||
const actions = this.createPromptActions(candidate);
|
||||
|
||||
const onRefuse = () => {
|
||||
this.setLastRefusedPromptInfo(candidate.id, selectedPort);
|
||||
};
|
||||
const handleAction = this.createOnAnswerHandler(actions, onRefuse);
|
||||
|
||||
const onAnswer = (answer: string) => {
|
||||
this.removeNotificationByBoard(selectedBoard);
|
||||
|
||||
handleAction(answer);
|
||||
};
|
||||
|
||||
this.messageService
|
||||
.info(info, ...actions.map((action) => action.key))
|
||||
.then(onAnswer);
|
||||
}
|
||||
|
||||
private generatePromptInfoText(
|
||||
candidateName: string,
|
||||
version: string,
|
||||
boardName: string
|
||||
): string {
|
||||
return nls.localize(
|
||||
'arduino/board/installNow',
|
||||
'The "{0} {1}" core has to be installed for the currently selected "{2}" board. Do you want to install it now?',
|
||||
candidateName,
|
||||
version,
|
||||
boardName
|
||||
);
|
||||
}
|
||||
|
||||
private createPromptActions(
|
||||
candidate: BoardsPackage
|
||||
): AutoInstallPromptActions {
|
||||
const yes = nls.localize('vscode/extensionsUtils/yes', 'Yes');
|
||||
const manualInstall = nls.localize(
|
||||
'arduino/board/installManually',
|
||||
'Install Manually'
|
||||
);
|
||||
|
||||
const actions: AutoInstallPromptActions = [
|
||||
{
|
||||
key: manualInstall,
|
||||
handler: () => {
|
||||
this.boardsManagerFrontendContribution
|
||||
.openView({ reveal: true })
|
||||
.then((widget) =>
|
||||
widget.refresh(candidate.name.toLocaleLowerCase())
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
isAcceptance: true,
|
||||
key: yes,
|
||||
handler: () => {
|
||||
return Installable.installWithProgress({
|
||||
installable: this.boardsService,
|
||||
item: candidate,
|
||||
messageService: this.messageService,
|
||||
responseService: this.responseService,
|
||||
version: candidate.availableVersions[0],
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
private createOnAnswerHandler(
|
||||
actions: AutoInstallPromptActions,
|
||||
onRefuse?: () => void
|
||||
): (answer: string) => void {
|
||||
return (answer) => {
|
||||
const actionToHandle = actions.find((action) => action.key === answer);
|
||||
actionToHandle?.handler();
|
||||
|
||||
if (!actionToHandle?.isAcceptance && onRefuse) {
|
||||
onRefuse();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -113,7 +113,7 @@ export class BoardsConfig extends React.Component<
|
||||
);
|
||||
}
|
||||
}),
|
||||
this.props.notificationCenter.onAttachedBoardsChanged((event) =>
|
||||
this.props.notificationCenter.onAttachedBoardsDidChange((event) =>
|
||||
this.updatePorts(
|
||||
event.newState.ports,
|
||||
AttachedBoardsChangeEvent.diff(event).detached.ports
|
||||
@@ -126,19 +126,19 @@ export class BoardsConfig extends React.Component<
|
||||
);
|
||||
}
|
||||
),
|
||||
this.props.notificationCenter.onPlatformInstalled(() =>
|
||||
this.props.notificationCenter.onPlatformDidInstall(() =>
|
||||
this.updateBoards(this.state.query)
|
||||
),
|
||||
this.props.notificationCenter.onPlatformUninstalled(() =>
|
||||
this.props.notificationCenter.onPlatformDidUninstall(() =>
|
||||
this.updateBoards(this.state.query)
|
||||
),
|
||||
this.props.notificationCenter.onIndexUpdated(() =>
|
||||
this.props.notificationCenter.onIndexDidUpdate(() =>
|
||||
this.updateBoards(this.state.query)
|
||||
),
|
||||
this.props.notificationCenter.onDaemonStarted(() =>
|
||||
this.props.notificationCenter.onDaemonDidStart(() =>
|
||||
this.updateBoards(this.state.query)
|
||||
),
|
||||
this.props.notificationCenter.onDaemonStopped(() =>
|
||||
this.props.notificationCenter.onDaemonDidStop(() =>
|
||||
this.setState({ searchResults: [] })
|
||||
),
|
||||
this.props.onFilteredTextDidChangeEvent((query) =>
|
||||
|
@@ -33,7 +33,7 @@ export class BoardsDataStore implements FrontendApplicationContribution {
|
||||
protected readonly onChangedEmitter = new Emitter<void>();
|
||||
|
||||
onStart(): void {
|
||||
this.notificationCenter.onPlatformInstalled(async ({ item }) => {
|
||||
this.notificationCenter.onPlatformDidInstall(async ({ item }) => {
|
||||
let shouldFireChanged = false;
|
||||
for (const fqbn of item.boards
|
||||
.map(({ fqbn }) => fqbn)
|
||||
|
@@ -1,4 +1,8 @@
|
||||
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import {
|
||||
BoardsPackage,
|
||||
BoardsService,
|
||||
@@ -33,10 +37,10 @@ export class BoardsListWidget extends ListWidget<BoardsPackage> {
|
||||
protected override init(): void {
|
||||
super.init();
|
||||
this.toDispose.pushAll([
|
||||
this.notificationCenter.onPlatformInstalled(() =>
|
||||
this.notificationCenter.onPlatformDidInstall(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
this.notificationCenter.onPlatformUninstalled(() =>
|
||||
this.notificationCenter.onPlatformDidUninstall(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
]);
|
||||
|
@@ -17,9 +17,10 @@ import {
|
||||
import { BoardsConfig } from './boards-config';
|
||||
import { naturalCompare } from '../../common/utils';
|
||||
import { NotificationCenter } from '../notification-center';
|
||||
import { ArduinoCommands } from '../arduino-commands';
|
||||
import { StorageWrapper } from '../storage-wrapper';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
|
||||
@injectable()
|
||||
export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
@@ -38,6 +39,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
@inject(NotificationCenter)
|
||||
protected notificationCenter: NotificationCenter;
|
||||
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
protected readonly onBoardsConfigChangedEmitter =
|
||||
new Emitter<BoardsConfig.Config>();
|
||||
protected readonly onAvailableBoardsChangedEmitter = new Emitter<
|
||||
@@ -73,29 +77,40 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
this.onAvailableBoardsChangedEmitter.event;
|
||||
readonly onAvailablePortsChanged = this.onAvailablePortsChangedEmitter.event;
|
||||
|
||||
private readonly _reconciled = new Deferred<void>();
|
||||
|
||||
onStart(): void {
|
||||
this.notificationCenter.onAttachedBoardsChanged(
|
||||
this.notificationCenter.onAttachedBoardsDidChange(
|
||||
this.notifyAttachedBoardsChanged.bind(this)
|
||||
);
|
||||
this.notificationCenter.onPlatformInstalled(
|
||||
this.notificationCenter.onPlatformDidInstall(
|
||||
this.notifyPlatformInstalled.bind(this)
|
||||
);
|
||||
this.notificationCenter.onPlatformUninstalled(
|
||||
this.notificationCenter.onPlatformDidUninstall(
|
||||
this.notifyPlatformUninstalled.bind(this)
|
||||
);
|
||||
|
||||
Promise.all([
|
||||
this.boardsService.getAttachedBoards(),
|
||||
this.boardsService.getAvailablePorts(),
|
||||
this.loadState(),
|
||||
]).then(([attachedBoards, availablePorts]) => {
|
||||
this.appStateService.reachedState('ready').then(async () => {
|
||||
const [attachedBoards, availablePorts] = await Promise.all([
|
||||
this.boardsService.getAttachedBoards(),
|
||||
this.boardsService.getAvailablePorts(),
|
||||
this.loadState(),
|
||||
]);
|
||||
this._attachedBoards = attachedBoards;
|
||||
this._availablePorts = availablePorts;
|
||||
this.onAvailablePortsChangedEmitter.fire(this._availablePorts);
|
||||
this.reconcileAvailableBoards().then(() => this.tryReconnect());
|
||||
|
||||
await this.reconcileAvailableBoards();
|
||||
|
||||
this.tryReconnect();
|
||||
this._reconciled.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
get reconciled(): Promise<void> {
|
||||
return this._reconciled.promise;
|
||||
}
|
||||
|
||||
protected notifyAttachedBoardsChanged(
|
||||
event: AttachedBoardsChangeEvent
|
||||
): void {
|
||||
@@ -155,7 +170,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
.then(async (answer) => {
|
||||
if (answer === yes) {
|
||||
this.commandService.executeCommand(
|
||||
ArduinoCommands.OPEN_BOARDS_DIALOG.id,
|
||||
'arduino-open-boards-dialog',
|
||||
selectedBoard.name
|
||||
);
|
||||
}
|
||||
@@ -185,8 +200,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const selectedAvailableBoard = AvailableBoard.is(selectedBoard)
|
||||
? selectedBoard
|
||||
: this._availableBoards.find((availableBoard) =>
|
||||
Board.sameAs(availableBoard, selectedBoard)
|
||||
);
|
||||
Board.sameAs(availableBoard, selectedBoard)
|
||||
);
|
||||
if (
|
||||
selectedAvailableBoard &&
|
||||
selectedAvailableBoard.selected &&
|
||||
@@ -209,7 +224,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
}
|
||||
|
||||
protected async tryReconnect(): Promise<boolean> {
|
||||
protected tryReconnect(): boolean {
|
||||
if (this.latestValidBoardsConfig && !this.canUploadTo(this.boardsConfig)) {
|
||||
for (const board of this.availableBoards.filter(
|
||||
({ state }) => state !== AvailableBoard.State.incomplete
|
||||
@@ -231,7 +246,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
if (
|
||||
this.latestValidBoardsConfig.selectedBoard.fqbn === board.fqbn &&
|
||||
this.latestValidBoardsConfig.selectedBoard.name === board.name &&
|
||||
this.latestValidBoardsConfig.selectedPort.protocol === board.port?.protocol
|
||||
this.latestValidBoardsConfig.selectedPort.protocol ===
|
||||
board.port?.protocol
|
||||
) {
|
||||
this.boardsConfig = {
|
||||
...this.latestValidBoardsConfig,
|
||||
@@ -258,7 +274,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
|
||||
protected setBoardsConfig(config: BoardsConfig.Config): void {
|
||||
this.logger.info('Board config changed: ', JSON.stringify(config));
|
||||
this.logger.debug('Board config changed: ', JSON.stringify(config));
|
||||
this._boardsConfig = config;
|
||||
this.latestBoardsConfig = this._boardsConfig;
|
||||
if (this.canUploadTo(this._boardsConfig)) {
|
||||
@@ -376,14 +392,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const timeoutTask =
|
||||
!!timeout && timeout > 0
|
||||
? new Promise<void>((_, reject) =>
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${timeout} ms.`)),
|
||||
timeout
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${timeout} ms.`)),
|
||||
timeout
|
||||
)
|
||||
)
|
||||
)
|
||||
: new Promise<void>(() => {
|
||||
/* never */
|
||||
});
|
||||
/* never */
|
||||
});
|
||||
const waitUntilTask = new Promise<void>((resolve) => {
|
||||
let candidate = find(what, this.availableBoards);
|
||||
if (candidate) {
|
||||
@@ -500,6 +516,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
for (let i = 0; !hasChanged && i < availableBoards.length; i++) {
|
||||
const [left, right] = [availableBoards[i], currentAvailableBoards[i]];
|
||||
hasChanged =
|
||||
left.fqbn !== right.fqbn ||
|
||||
!!AvailableBoard.compare(left, right) ||
|
||||
left.selected !== right.selected;
|
||||
}
|
||||
@@ -534,8 +551,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
|
||||
protected getLastSelectedBoardOnPortKey(port: Port | string): string {
|
||||
// TODO: we lose the port's `protocol` info (`serial`, `network`, etc.) here if the `port` is a `string`.
|
||||
return `last-selected-board-on-port:${typeof port === 'string' ? port : port.address
|
||||
}`;
|
||||
return `last-selected-board-on-port:${
|
||||
typeof port === 'string' ? port : port.address
|
||||
}`;
|
||||
}
|
||||
|
||||
protected async loadState(): Promise<void> {
|
||||
|
@@ -3,13 +3,14 @@ import * as ReactDOM from '@theia/core/shared/react-dom';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { Port } from '../../common/protocol';
|
||||
import { BoardsConfig } from './boards-config';
|
||||
import { ArduinoCommands } from '../arduino-commands';
|
||||
import { OpenBoardsConfig } from '../contributions/open-boards-config';
|
||||
import {
|
||||
BoardsServiceProvider,
|
||||
AvailableBoard,
|
||||
} from './boards-service-provider';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import classNames from 'classnames';
|
||||
import { BoardsConfig } from './boards-config';
|
||||
|
||||
export interface BoardsDropDownListCoords {
|
||||
readonly top: number;
|
||||
@@ -28,10 +29,12 @@ export namespace BoardsDropDown {
|
||||
|
||||
export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
protected dropdownElement: HTMLElement;
|
||||
private listRef: React.RefObject<HTMLDivElement>;
|
||||
|
||||
constructor(props: BoardsDropDown.Props) {
|
||||
super(props);
|
||||
|
||||
this.listRef = React.createRef();
|
||||
let list = document.getElementById('boards-dropdown-container');
|
||||
if (!list) {
|
||||
list = document.createElement('div');
|
||||
@@ -41,6 +44,12 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
}
|
||||
}
|
||||
|
||||
override componentDidUpdate(prevProps: BoardsDropDown.Props): void {
|
||||
if (prevProps.coords === 'hidden' && this.listRef.current) {
|
||||
this.listRef.current.focus();
|
||||
}
|
||||
}
|
||||
|
||||
override render(): React.ReactNode {
|
||||
return ReactDOM.createPortal(this.renderNode(), this.dropdownElement);
|
||||
}
|
||||
@@ -61,21 +70,22 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
position: 'absolute',
|
||||
...coords,
|
||||
}}
|
||||
ref={this.listRef}
|
||||
tabIndex={0}
|
||||
>
|
||||
{items
|
||||
.map(({ name, port, selected, onClick }) => ({
|
||||
label: nls.localize(
|
||||
'arduino/board/boardListItem',
|
||||
'{0} at {1}',
|
||||
name,
|
||||
Port.toString(port)
|
||||
),
|
||||
selected,
|
||||
onClick,
|
||||
}))
|
||||
.map(this.renderItem)}
|
||||
<div className="arduino-boards-dropdown-list--items-container">
|
||||
{items
|
||||
.map(({ name, port, selected, onClick }) => ({
|
||||
boardLabel: name,
|
||||
port,
|
||||
selected,
|
||||
onClick,
|
||||
}))
|
||||
.map(this.renderItem)}
|
||||
</div>
|
||||
<div
|
||||
key={footerLabel}
|
||||
tabIndex={0}
|
||||
className="arduino-boards-dropdown-item arduino-board-dropdown-footer"
|
||||
onClick={() => this.props.openBoardsConfig()}
|
||||
>
|
||||
@@ -86,22 +96,52 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
}
|
||||
|
||||
protected renderItem({
|
||||
label,
|
||||
boardLabel,
|
||||
port,
|
||||
selected,
|
||||
onClick,
|
||||
}: {
|
||||
label: string;
|
||||
boardLabel: string;
|
||||
port: Port;
|
||||
selected?: boolean;
|
||||
onClick: () => void;
|
||||
}): React.ReactNode {
|
||||
const protocolIcon = iconNameFromProtocol(port.protocol);
|
||||
const onKeyUp = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
onClick();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
key={label}
|
||||
className={`arduino-boards-dropdown-item ${selected ? 'selected' : ''}`}
|
||||
key={`board-item--${boardLabel}-${port.address}`}
|
||||
className={classNames('arduino-boards-dropdown-item', {
|
||||
'arduino-boards-dropdown-item--selected': selected,
|
||||
})}
|
||||
onClick={onClick}
|
||||
onKeyUp={onKeyUp}
|
||||
tabIndex={0}
|
||||
>
|
||||
<div>{label}</div>
|
||||
{selected ? <span className="fa fa-check" /> : ''}
|
||||
<div
|
||||
className={classNames(
|
||||
'arduino-boards-dropdown-item--protocol',
|
||||
'fa',
|
||||
protocolIcon
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
className="arduino-boards-dropdown-item--label"
|
||||
title={`${boardLabel}\n${port.address}`}
|
||||
>
|
||||
<div className="arduino-boards-dropdown-item--board-label noWrapInfo noselect">
|
||||
{boardLabel}
|
||||
</div>
|
||||
<div className="arduino-boards-dropdown-item--port-label noWrapInfo noselect">
|
||||
{port.address}
|
||||
</div>
|
||||
</div>
|
||||
{selected ? <div className="fa fa-check" /> : ''}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -119,7 +159,7 @@ export class BoardsToolBarItem extends React.Component<
|
||||
constructor(props: BoardsToolBarItem.Props) {
|
||||
super(props);
|
||||
|
||||
const { availableBoards } = props.boardsServiceClient;
|
||||
const { availableBoards } = props.boardsServiceProvider;
|
||||
this.state = {
|
||||
availableBoards,
|
||||
coords: 'hidden',
|
||||
@@ -131,8 +171,8 @@ export class BoardsToolBarItem extends React.Component<
|
||||
}
|
||||
|
||||
override componentDidMount(): void {
|
||||
this.props.boardsServiceClient.onAvailableBoardsChanged((availableBoards) =>
|
||||
this.setState({ availableBoards })
|
||||
this.props.boardsServiceProvider.onAvailableBoardsChanged(
|
||||
(availableBoards) => this.setState({ availableBoards })
|
||||
);
|
||||
}
|
||||
|
||||
@@ -140,7 +180,7 @@ export class BoardsToolBarItem extends React.Component<
|
||||
this.toDispose.dispose();
|
||||
}
|
||||
|
||||
protected readonly show = (event: React.MouseEvent<HTMLElement>) => {
|
||||
protected readonly show = (event: React.MouseEvent<HTMLElement>): void => {
|
||||
const { currentTarget: element } = event;
|
||||
if (element instanceof HTMLElement) {
|
||||
if (this.state.coords === 'hidden') {
|
||||
@@ -163,36 +203,43 @@ export class BoardsToolBarItem extends React.Component<
|
||||
|
||||
override render(): React.ReactNode {
|
||||
const { coords, availableBoards } = this.state;
|
||||
const boardsConfig = this.props.boardsServiceClient.boardsConfig;
|
||||
const title = BoardsConfig.Config.toString(boardsConfig, {
|
||||
default: nls.localize(
|
||||
'arduino/common/noBoardSelected',
|
||||
'No board selected'
|
||||
),
|
||||
});
|
||||
const decorator = (() => {
|
||||
const selectedBoard = availableBoards.find(({ selected }) => selected);
|
||||
if (!selectedBoard || !selectedBoard.port) {
|
||||
return 'fa fa-times notAttached';
|
||||
}
|
||||
if (selectedBoard.state === AvailableBoard.State.guessed) {
|
||||
return 'fa fa-exclamation-triangle guessed';
|
||||
}
|
||||
return '';
|
||||
})();
|
||||
const { selectedBoard, selectedPort } =
|
||||
this.props.boardsServiceProvider.boardsConfig;
|
||||
|
||||
const boardLabel =
|
||||
selectedBoard?.name ||
|
||||
nls.localize('arduino/board/selectBoard', 'Select Board');
|
||||
const selectedPortLabel = portLabel(selectedPort?.address);
|
||||
|
||||
const isConnected = Boolean(selectedBoard && selectedPort);
|
||||
const protocolIcon = isConnected
|
||||
? iconNameFromProtocol(selectedPort?.protocol || '')
|
||||
: null;
|
||||
const protocolIconClassNames = classNames(
|
||||
'arduino-boards-toolbar-item--protocol',
|
||||
'fa',
|
||||
protocolIcon
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="arduino-boards-toolbar-item-container">
|
||||
<div className="arduino-boards-toolbar-item" title={title}>
|
||||
<div className="inner-container" onClick={this.show}>
|
||||
<span className={decorator} />
|
||||
<div className="label noWrapInfo">
|
||||
<div className="noWrapInfo noselect">{title}</div>
|
||||
</div>
|
||||
<span className="fa fa-caret-down caret" />
|
||||
</div>
|
||||
<div
|
||||
className="arduino-boards-toolbar-item-container"
|
||||
title={selectedPortLabel}
|
||||
onClick={this.show}
|
||||
>
|
||||
{protocolIcon && <div className={protocolIconClassNames} />}
|
||||
<div
|
||||
className={classNames(
|
||||
'arduino-boards-toolbar-item--label',
|
||||
'noWrapInfo',
|
||||
'noselect',
|
||||
{ 'arduino-boards-toolbar-item--label-connected': isConnected }
|
||||
)}
|
||||
>
|
||||
{boardLabel}
|
||||
</div>
|
||||
<div className="fa fa-caret-down caret" />
|
||||
</div>
|
||||
<BoardsDropDown
|
||||
coords={coords}
|
||||
@@ -201,17 +248,20 @@ export class BoardsToolBarItem extends React.Component<
|
||||
.map((board) => ({
|
||||
...board,
|
||||
onClick: () => {
|
||||
if (board.state === AvailableBoard.State.incomplete) {
|
||||
this.props.boardsServiceClient.boardsConfig = {
|
||||
if (!board.fqbn) {
|
||||
const previousBoardConfig =
|
||||
this.props.boardsServiceProvider.boardsConfig;
|
||||
this.props.boardsServiceProvider.boardsConfig = {
|
||||
selectedPort: board.port,
|
||||
};
|
||||
this.openDialog();
|
||||
this.openDialog(previousBoardConfig);
|
||||
} else {
|
||||
this.props.boardsServiceClient.boardsConfig = {
|
||||
this.props.boardsServiceProvider.boardsConfig = {
|
||||
selectedBoard: board,
|
||||
selectedPort: board.port,
|
||||
};
|
||||
}
|
||||
this.setState({ coords: 'hidden' });
|
||||
},
|
||||
}))}
|
||||
openBoardsConfig={this.openDialog}
|
||||
@@ -220,14 +270,25 @@ export class BoardsToolBarItem extends React.Component<
|
||||
);
|
||||
}
|
||||
|
||||
protected openDialog = () => {
|
||||
this.props.commands.executeCommand(ArduinoCommands.OPEN_BOARDS_DIALOG.id);
|
||||
this.setState({ coords: 'hidden' });
|
||||
protected openDialog = async (
|
||||
previousBoardConfig?: BoardsConfig.Config
|
||||
): Promise<void> => {
|
||||
const selectedBoardConfig =
|
||||
await this.props.commands.executeCommand<BoardsConfig.Config>(
|
||||
OpenBoardsConfig.Commands.OPEN_DIALOG.id
|
||||
);
|
||||
if (
|
||||
previousBoardConfig &&
|
||||
(!selectedBoardConfig?.selectedPort ||
|
||||
!selectedBoardConfig?.selectedBoard)
|
||||
) {
|
||||
this.props.boardsServiceProvider.boardsConfig = previousBoardConfig;
|
||||
}
|
||||
};
|
||||
}
|
||||
export namespace BoardsToolBarItem {
|
||||
export interface Props {
|
||||
readonly boardsServiceClient: BoardsServiceProvider;
|
||||
readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
readonly commands: CommandRegistry;
|
||||
}
|
||||
|
||||
@@ -236,3 +297,26 @@ export namespace BoardsToolBarItem {
|
||||
coords: BoardsDropDownListCoords | 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
function iconNameFromProtocol(protocol: string): string {
|
||||
switch (protocol) {
|
||||
case 'serial':
|
||||
return 'fa-arduino-technology-usb';
|
||||
case 'network':
|
||||
return 'fa-arduino-technology-connection';
|
||||
/*
|
||||
Bluetooth ports are not listed yet from the CLI;
|
||||
Not sure about the naming ('bluetooth'); make sure it's correct before uncommenting the following lines
|
||||
*/
|
||||
// case 'bluetooth':
|
||||
// return 'fa-arduino-technology-bluetooth';
|
||||
default:
|
||||
return 'fa-arduino-technology-3dimensionscube';
|
||||
}
|
||||
}
|
||||
|
||||
function portLabel(portName?: string): string {
|
||||
return portName
|
||||
? nls.localize('arduino/board/portLabel', 'Port: {0}', portName)
|
||||
: nls.localize('arduino/board/disconnected', 'Disconnected');
|
||||
}
|
||||
|
@@ -4,11 +4,8 @@ import URI from '@theia/core/lib/common/uri';
|
||||
import { ConfirmDialog } from '@theia/core/lib/browser/dialogs';
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import {
|
||||
Installable,
|
||||
LibraryService,
|
||||
ResponseServiceArduino,
|
||||
} from '../../common/protocol';
|
||||
import { LibraryService, ResponseServiceClient } from '../../common/protocol';
|
||||
import { ExecuteWithProgress } from '../../common/protocol/progressible';
|
||||
import {
|
||||
SketchContribution,
|
||||
Command,
|
||||
@@ -22,8 +19,8 @@ export class AddZipLibrary extends SketchContribution {
|
||||
@inject(EnvVariablesServer)
|
||||
protected readonly envVariableServer: EnvVariablesServer;
|
||||
|
||||
@inject(ResponseServiceArduino)
|
||||
protected readonly responseService: ResponseServiceArduino;
|
||||
@inject(ResponseServiceClient)
|
||||
protected readonly responseService: ResponseServiceClient;
|
||||
|
||||
@inject(LibraryService)
|
||||
protected readonly libraryService: LibraryService;
|
||||
@@ -88,7 +85,7 @@ export class AddZipLibrary extends SketchContribution {
|
||||
|
||||
private async doInstall(zipUri: string, overwrite?: boolean): Promise<void> {
|
||||
try {
|
||||
await Installable.doWithProgress({
|
||||
await ExecuteWithProgress.doWithProgress({
|
||||
messageService: this.messageService,
|
||||
progressText:
|
||||
nls.localize('arduino/common/processing', 'Processing') +
|
||||
|
@@ -101,8 +101,8 @@ PID: ${PID}`;
|
||||
}
|
||||
|
||||
override onStart(): void {
|
||||
this.notificationCenter.onPlatformInstalled(() => this.updateMenus());
|
||||
this.notificationCenter.onPlatformUninstalled(() => this.updateMenus());
|
||||
this.notificationCenter.onPlatformDidInstall(() => this.updateMenus());
|
||||
this.notificationCenter.onPlatformDidUninstall(() => this.updateMenus());
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(() => this.updateMenus());
|
||||
this.boardsServiceProvider.onAvailableBoardsChanged(() =>
|
||||
this.updateMenus()
|
||||
|
@@ -1,23 +1,16 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import {
|
||||
CoreServiceContribution,
|
||||
Command,
|
||||
CommandRegistry,
|
||||
CoreServiceContribution,
|
||||
MenuModelRegistry,
|
||||
} from './contribution';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
|
||||
@injectable()
|
||||
export class BurnBootloader extends CoreServiceContribution {
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(BurnBootloader.Commands.BURN_BOOTLOADER, {
|
||||
execute: () => this.burnBootloader(),
|
||||
@@ -35,32 +28,19 @@ export class BurnBootloader extends CoreServiceContribution {
|
||||
});
|
||||
}
|
||||
|
||||
async burnBootloader(): Promise<void> {
|
||||
private async burnBootloader(): Promise<void> {
|
||||
const options = await this.options();
|
||||
try {
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const port = boardsConfig.selectedPort;
|
||||
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] =
|
||||
await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
|
||||
const board = {
|
||||
...boardsConfig.selectedBoard,
|
||||
name: boardsConfig.selectedBoard?.name || '',
|
||||
fqbn,
|
||||
};
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
await this.coreService.burnBootloader({
|
||||
board,
|
||||
programmer,
|
||||
port,
|
||||
verify,
|
||||
verbose,
|
||||
await this.doWithProgress({
|
||||
progressText: nls.localize(
|
||||
'arduino/bootloader/burningBootloader',
|
||||
'Burning bootloader...'
|
||||
),
|
||||
task: (progressId, coreService) =>
|
||||
coreService.burnBootloader({
|
||||
...options,
|
||||
progressId,
|
||||
}),
|
||||
});
|
||||
this.messageService.info(
|
||||
nls.localize(
|
||||
@@ -75,6 +55,27 @@ export class BurnBootloader extends CoreServiceContribution {
|
||||
this.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async options(): Promise<CoreService.Options.Bootloader> {
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const port = boardsConfig.selectedPort;
|
||||
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] =
|
||||
await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
return {
|
||||
fqbn,
|
||||
programmer,
|
||||
port,
|
||||
verify,
|
||||
verbose,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace BurnBootloader {
|
||||
|
@@ -0,0 +1,64 @@
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { LocalStorageService } from '@theia/core/lib/browser/storage-service';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
IDEUpdater,
|
||||
SKIP_IDE_VERSION,
|
||||
} from '../../common/protocol/ide-updater';
|
||||
import { IDEUpdaterDialog } from '../dialogs/ide-updater/ide-updater-dialog';
|
||||
import { Contribution } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class CheckForUpdates extends Contribution {
|
||||
@inject(IDEUpdater)
|
||||
private readonly updater: IDEUpdater;
|
||||
|
||||
@inject(IDEUpdaterDialog)
|
||||
private readonly updaterDialog: IDEUpdaterDialog;
|
||||
|
||||
@inject(LocalStorageService)
|
||||
private readonly localStorage: LocalStorageService;
|
||||
|
||||
override onStart(): void {
|
||||
this.preferences.onPreferenceChanged(
|
||||
({ preferenceName, newValue, oldValue }) => {
|
||||
if (newValue !== oldValue) {
|
||||
switch (preferenceName) {
|
||||
case 'arduino.ide.updateChannel':
|
||||
case 'arduino.ide.updateBaseUrl':
|
||||
this.updater.init(
|
||||
this.preferences.get('arduino.ide.updateChannel'),
|
||||
this.preferences.get('arduino.ide.updateBaseUrl')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
override onReady(): void {
|
||||
this.updater
|
||||
.init(
|
||||
this.preferences.get('arduino.ide.updateChannel'),
|
||||
this.preferences.get('arduino.ide.updateBaseUrl')
|
||||
)
|
||||
.then(() => this.updater.checkForUpdates(true))
|
||||
.then(async (updateInfo) => {
|
||||
if (!updateInfo) return;
|
||||
const versionToSkip = await this.localStorage.getData<string>(
|
||||
SKIP_IDE_VERSION
|
||||
);
|
||||
if (versionToSkip === updateInfo.version) return;
|
||||
this.updaterDialog.open(updateInfo);
|
||||
})
|
||||
.catch((e) => {
|
||||
this.messageService.error(
|
||||
nls.localize(
|
||||
'arduino/ide-updater/errorCheckingForUpdates',
|
||||
'Error while checking for Arduino IDE updates.\n{0}',
|
||||
e.message
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
@@ -29,10 +29,7 @@ import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
||||
import { MonacoToProtocolConverter } from '@theia/monaco/lib/browser/monaco-to-protocol-converter';
|
||||
import { ProtocolToMonacoConverter } from '@theia/monaco/lib/browser/protocol-to-monaco-converter';
|
||||
import { CoreError } from '../../common/protocol/core-service';
|
||||
import {
|
||||
ArduinoPreferences,
|
||||
ErrorRevealStrategy,
|
||||
} from '../arduino-preferences';
|
||||
import { ErrorRevealStrategy } from '../arduino-preferences';
|
||||
import { InoSelector } from '../ino-selectors';
|
||||
import { fullRange } from '../utils/monaco';
|
||||
import { Contribution } from './contribution';
|
||||
@@ -127,9 +124,6 @@ export class CompilerErrors
|
||||
@inject(CoreErrorHandler)
|
||||
private readonly coreErrorHandler: CoreErrorHandler;
|
||||
|
||||
@inject(ArduinoPreferences)
|
||||
private readonly preferences: ArduinoPreferences;
|
||||
|
||||
private readonly errors: ErrorDecoration[] = [];
|
||||
private readonly onDidChangeEmitter = new monaco.Emitter<this>();
|
||||
private readonly currentErrorDidChangEmitter = new Emitter<ErrorDecoration>();
|
||||
@@ -275,7 +269,7 @@ export class CompilerErrors
|
||||
}
|
||||
|
||||
private async handleCompilerErrorsDidChange(
|
||||
errors: CoreError.Compiler[]
|
||||
errors: CoreError.ErrorLocation[]
|
||||
): Promise<void> {
|
||||
this.toDisposeOnCompilerErrorDidChange.dispose();
|
||||
const compilerErrorsPerResource = this.groupByResource(
|
||||
@@ -312,8 +306,8 @@ export class CompilerErrors
|
||||
}
|
||||
|
||||
private async filter(
|
||||
errors: CoreError.Compiler[]
|
||||
): Promise<CoreError.Compiler[]> {
|
||||
errors: CoreError.ErrorLocation[]
|
||||
): Promise<CoreError.ErrorLocation[]> {
|
||||
if (!errors.length) {
|
||||
return [];
|
||||
}
|
||||
@@ -326,7 +320,7 @@ export class CompilerErrors
|
||||
}
|
||||
|
||||
private async decorateEditors(
|
||||
errors: Map<string, CoreError.Compiler[]>
|
||||
errors: Map<string, CoreError.ErrorLocation[]>
|
||||
): Promise<{ dispose: Disposable; errors: ErrorDecoration[] }> {
|
||||
const composite = await Promise.all(
|
||||
[...errors.entries()].map(([uri, errors]) =>
|
||||
@@ -346,7 +340,7 @@ export class CompilerErrors
|
||||
|
||||
private async decorateEditor(
|
||||
uri: string,
|
||||
errors: CoreError.Compiler[]
|
||||
errors: CoreError.ErrorLocation[]
|
||||
): Promise<{ dispose: Disposable; errors: ErrorDecoration[] }> {
|
||||
const editor = await this.editorManager.getByUri(new URI(uri));
|
||||
if (!editor) {
|
||||
@@ -523,7 +517,7 @@ export class CompilerErrors
|
||||
}
|
||||
|
||||
private async trackEditors(
|
||||
errors: Map<string, CoreError.Compiler[]>,
|
||||
errors: Map<string, CoreError.ErrorLocation[]>,
|
||||
...track: ((editor: EditorWidget) => Disposable)[]
|
||||
): Promise<Disposable> {
|
||||
return new DisposableCollection(
|
||||
@@ -605,8 +599,8 @@ export class CompilerErrors
|
||||
}
|
||||
|
||||
private groupByResource(
|
||||
errors: CoreError.Compiler[]
|
||||
): Map<string, CoreError.Compiler[]> {
|
||||
errors: CoreError.ErrorLocation[]
|
||||
): Map<string, CoreError.ErrorLocation[]> {
|
||||
return errors.reduce((acc, curr) => {
|
||||
const {
|
||||
location: { uri },
|
||||
@@ -618,7 +612,7 @@ export class CompilerErrors
|
||||
}
|
||||
errors.push(curr);
|
||||
return acc;
|
||||
}, new Map<string, CoreError.Compiler[]>());
|
||||
}, new Map<string, CoreError.ErrorLocation[]>());
|
||||
}
|
||||
|
||||
private monacoEditor(widget: EditorWidget): MonacoEditor | undefined;
|
||||
|
@@ -37,7 +37,6 @@ import {
|
||||
CommandContribution,
|
||||
CommandService,
|
||||
} from '@theia/core/lib/common/command';
|
||||
import { EditorMode } from '../editor-mode';
|
||||
import { SettingsService } from '../dialogs/settings/settings';
|
||||
import {
|
||||
CurrentSketch,
|
||||
@@ -50,13 +49,16 @@ import {
|
||||
Sketch,
|
||||
CoreService,
|
||||
CoreError,
|
||||
ResponseServiceClient,
|
||||
} from '../../common/protocol';
|
||||
import { ArduinoPreferences } from '../arduino-preferences';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { CoreErrorHandler } from './core-error-handler';
|
||||
import { nls } from '@theia/core';
|
||||
import { OutputChannelManager } from '../theia/output/output-channel';
|
||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
||||
import { ExecuteWithProgress } from '../../common/protocol/progressible';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
|
||||
export {
|
||||
Command,
|
||||
@@ -90,15 +92,15 @@ export abstract class Contribution
|
||||
@inject(WorkspaceService)
|
||||
protected readonly workspaceService: WorkspaceService;
|
||||
|
||||
@inject(EditorMode)
|
||||
protected readonly editorMode: EditorMode;
|
||||
|
||||
@inject(LabelProvider)
|
||||
protected readonly labelProvider: LabelProvider;
|
||||
|
||||
@inject(SettingsService)
|
||||
protected readonly settingsService: SettingsService;
|
||||
|
||||
@inject(ArduinoPreferences)
|
||||
protected readonly preferences: ArduinoPreferences;
|
||||
|
||||
@inject(FrontendApplicationStateService)
|
||||
protected readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
@@ -146,9 +148,6 @@ export abstract class SketchContribution extends Contribution {
|
||||
@inject(SketchesServiceClientImpl)
|
||||
protected readonly sketchServiceClient: SketchesServiceClientImpl;
|
||||
|
||||
@inject(ArduinoPreferences)
|
||||
protected readonly preferences: ArduinoPreferences;
|
||||
|
||||
@inject(EditorManager)
|
||||
protected readonly editorManager: EditorManager;
|
||||
|
||||
@@ -171,18 +170,23 @@ export abstract class SketchContribution extends Contribution {
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class CoreServiceContribution extends SketchContribution {
|
||||
@inject(CoreService)
|
||||
protected readonly coreService: CoreService;
|
||||
export abstract class CoreServiceContribution extends SketchContribution {
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(CoreErrorHandler)
|
||||
protected readonly coreErrorHandler: CoreErrorHandler;
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
@inject(CoreService)
|
||||
private readonly coreService: CoreService;
|
||||
|
||||
@inject(ClipboardService)
|
||||
private readonly clipboardService: ClipboardService;
|
||||
|
||||
@inject(ResponseServiceClient)
|
||||
private readonly responseService: ResponseServiceClient;
|
||||
|
||||
protected handleError(error: unknown): void {
|
||||
this.coreErrorHandler.tryHandle(error);
|
||||
this.tryToastErrorMessage(error);
|
||||
}
|
||||
|
||||
@@ -218,6 +222,25 @@ export class CoreServiceContribution extends SketchContribution {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
protected async doWithProgress<T>(options: {
|
||||
progressText: string;
|
||||
keepOutput?: boolean;
|
||||
task: (progressId: string, coreService: CoreService) => Promise<T>;
|
||||
}): Promise<T> {
|
||||
const { progressText, keepOutput, task } = options;
|
||||
this.outputChannelManager
|
||||
.getChannel('Arduino')
|
||||
.show({ preserveFocus: true });
|
||||
const result = await ExecuteWithProgress.doWithProgress({
|
||||
messageService: this.messageService,
|
||||
responseService: this.responseService,
|
||||
progressText,
|
||||
run: ({ progressId }) => task(progressId, this.coreService),
|
||||
keepOutput,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Contribution {
|
||||
|
@@ -4,29 +4,29 @@ import { CoreError } from '../../common/protocol/core-service';
|
||||
|
||||
@injectable()
|
||||
export class CoreErrorHandler {
|
||||
private readonly compilerErrors: CoreError.Compiler[] = [];
|
||||
private readonly errors: CoreError.ErrorLocation[] = [];
|
||||
private readonly compilerErrorsDidChangeEmitter = new Emitter<
|
||||
CoreError.Compiler[]
|
||||
CoreError.ErrorLocation[]
|
||||
>();
|
||||
|
||||
tryHandle(error: unknown): void {
|
||||
if (CoreError.is(error)) {
|
||||
this.compilerErrors.length = 0;
|
||||
this.compilerErrors.push(...error.data.filter(CoreError.Compiler.is));
|
||||
this.errors.length = 0;
|
||||
this.errors.push(...error.data);
|
||||
this.fireCompilerErrorsDidChange();
|
||||
}
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.compilerErrors.length = 0;
|
||||
this.errors.length = 0;
|
||||
this.fireCompilerErrorsDidChange();
|
||||
}
|
||||
|
||||
get onCompilerErrorsDidChange(): Event<CoreError.Compiler[]> {
|
||||
get onCompilerErrorsDidChange(): Event<CoreError.ErrorLocation[]> {
|
||||
return this.compilerErrorsDidChangeEmitter.event;
|
||||
}
|
||||
|
||||
private fireCompilerErrorsDidChange(): void {
|
||||
this.compilerErrorsDidChangeEmitter.fire(this.compilerErrors.slice());
|
||||
this.compilerErrorsDidChangeEmitter.fire(this.errors.slice());
|
||||
}
|
||||
}
|
||||
|
41
arduino-ide-extension/src/browser/contributions/daemon.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { nls } from '@theia/core';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { ArduinoDaemon } from '../../common/protocol';
|
||||
import { Contribution, Command, CommandRegistry } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class Daemon extends Contribution {
|
||||
@inject(ArduinoDaemon)
|
||||
private readonly daemon: ArduinoDaemon;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(Daemon.Commands.START_DAEMON, {
|
||||
execute: () => this.daemon.start(),
|
||||
});
|
||||
registry.registerCommand(Daemon.Commands.STOP_DAEMON, {
|
||||
execute: () => this.daemon.stop(),
|
||||
});
|
||||
registry.registerCommand(Daemon.Commands.RESTART_DAEMON, {
|
||||
execute: () => this.daemon.restart(),
|
||||
});
|
||||
}
|
||||
}
|
||||
export namespace Daemon {
|
||||
export namespace Commands {
|
||||
export const START_DAEMON: Command = {
|
||||
id: 'arduino-start-daemon',
|
||||
label: nls.localize('arduino/daemon/start', 'Start Daemon'),
|
||||
category: 'Arduino',
|
||||
};
|
||||
export const STOP_DAEMON: Command = {
|
||||
id: 'arduino-stop-daemon',
|
||||
label: nls.localize('arduino/daemon/stop', 'Stop Daemon'),
|
||||
category: 'Arduino',
|
||||
};
|
||||
export const RESTART_DAEMON: Command = {
|
||||
id: 'arduino-restart-daemon',
|
||||
label: nls.localize('arduino/daemon/restart', 'Restart Daemon'),
|
||||
category: 'Arduino',
|
||||
};
|
||||
}
|
||||
}
|
@@ -12,46 +12,53 @@ import {
|
||||
SketchContribution,
|
||||
TabBarToolbarRegistry,
|
||||
} from './contribution';
|
||||
import { MaybePromise, nls } from '@theia/core/lib/common';
|
||||
import { MaybePromise, MenuModelRegistry, nls } from '@theia/core/lib/common';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
|
||||
import { MainMenuManager } from '../../common/main-menu-manager';
|
||||
|
||||
const COMPILE_FOR_DEBUG_KEY = 'arduino-compile-for-debug';
|
||||
@injectable()
|
||||
export class Debug extends SketchContribution {
|
||||
@inject(HostedPluginSupport)
|
||||
protected hostedPluginSupport: HostedPluginSupport;
|
||||
private readonly hostedPluginSupport: HostedPluginSupport;
|
||||
|
||||
@inject(NotificationCenter)
|
||||
protected readonly notificationCenter: NotificationCenter;
|
||||
private readonly notificationCenter: NotificationCenter;
|
||||
|
||||
@inject(ExecutableService)
|
||||
protected readonly executableService: ExecutableService;
|
||||
private readonly executableService: ExecutableService;
|
||||
|
||||
@inject(BoardsService)
|
||||
protected readonly boardService: BoardsService;
|
||||
private readonly boardService: BoardsService;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
private readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
@inject(MainMenuManager)
|
||||
private readonly mainMenuManager: MainMenuManager;
|
||||
|
||||
/**
|
||||
* If `undefined`, debugging is enabled. Otherwise, the reason why it's disabled.
|
||||
*/
|
||||
protected _disabledMessages?: string = nls.localize(
|
||||
private _disabledMessages?: string = nls.localize(
|
||||
'arduino/common/noBoardSelected',
|
||||
'No board selected'
|
||||
); // Initial pessimism.
|
||||
protected disabledMessageDidChangeEmitter = new Emitter<string | undefined>();
|
||||
protected onDisabledMessageDidChange =
|
||||
private disabledMessageDidChangeEmitter = new Emitter<string | undefined>();
|
||||
private onDisabledMessageDidChange =
|
||||
this.disabledMessageDidChangeEmitter.event;
|
||||
|
||||
protected get disabledMessage(): string | undefined {
|
||||
private get disabledMessage(): string | undefined {
|
||||
return this._disabledMessages;
|
||||
}
|
||||
protected set disabledMessage(message: string | undefined) {
|
||||
private set disabledMessage(message: string | undefined) {
|
||||
this._disabledMessages = message;
|
||||
this.disabledMessageDidChangeEmitter.fire(this._disabledMessages);
|
||||
}
|
||||
|
||||
protected readonly debugToolbarItem = {
|
||||
private readonly debugToolbarItem = {
|
||||
id: Debug.Commands.START_DEBUGGING.id,
|
||||
command: Debug.Commands.START_DEBUGGING.id,
|
||||
tooltip: `${
|
||||
@@ -83,8 +90,8 @@ export class Debug extends SketchContribution {
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(({ selectedBoard }) =>
|
||||
this.refreshState(selectedBoard)
|
||||
);
|
||||
this.notificationCenter.onPlatformInstalled(() => this.refreshState());
|
||||
this.notificationCenter.onPlatformUninstalled(() => this.refreshState());
|
||||
this.notificationCenter.onPlatformDidInstall(() => this.refreshState());
|
||||
this.notificationCenter.onPlatformDidUninstall(() => this.refreshState());
|
||||
}
|
||||
|
||||
override onReady(): MaybePromise<void> {
|
||||
@@ -98,12 +105,27 @@ export class Debug extends SketchContribution {
|
||||
ArduinoToolbar.is(widget) && widget.side === 'left',
|
||||
isEnabled: () => !this.disabledMessage,
|
||||
});
|
||||
registry.registerCommand(Debug.Commands.TOGGLE_OPTIMIZE_FOR_DEBUG, {
|
||||
execute: () => this.toggleCompileForDebug(),
|
||||
isToggled: () => this.compileForDebug,
|
||||
});
|
||||
registry.registerCommand(Debug.Commands.IS_OPTIMIZE_FOR_DEBUG, {
|
||||
execute: () => this.compileForDebug,
|
||||
});
|
||||
}
|
||||
|
||||
override registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
registry.registerItem(this.debugToolbarItem);
|
||||
}
|
||||
|
||||
override registerMenus(registry: MenuModelRegistry): void {
|
||||
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
|
||||
commandId: Debug.Commands.TOGGLE_OPTIMIZE_FOR_DEBUG.id,
|
||||
label: Debug.Commands.TOGGLE_OPTIMIZE_FOR_DEBUG.label,
|
||||
order: '5',
|
||||
});
|
||||
}
|
||||
|
||||
private async refreshState(
|
||||
board: Board | undefined = this.boardsServiceProvider.boardsConfig
|
||||
.selectedBoard
|
||||
@@ -145,7 +167,7 @@ export class Debug extends SketchContribution {
|
||||
}
|
||||
}
|
||||
|
||||
protected async startDebug(
|
||||
private async startDebug(
|
||||
board: Board | undefined = this.boardsServiceProvider.boardsConfig
|
||||
.selectedBoard
|
||||
): Promise<void> {
|
||||
@@ -183,8 +205,19 @@ export class Debug extends SketchContribution {
|
||||
};
|
||||
return this.commandService.executeCommand('arduino.debug.start', config);
|
||||
}
|
||||
}
|
||||
|
||||
get compileForDebug(): boolean {
|
||||
const value = window.localStorage.getItem(COMPILE_FOR_DEBUG_KEY);
|
||||
return value === 'true';
|
||||
}
|
||||
|
||||
async toggleCompileForDebug(): Promise<void> {
|
||||
const oldState = this.compileForDebug;
|
||||
const newState = !oldState;
|
||||
window.localStorage.setItem(COMPILE_FOR_DEBUG_KEY, String(newState));
|
||||
this.mainMenuManager.update();
|
||||
}
|
||||
}
|
||||
export namespace Debug {
|
||||
export namespace Commands {
|
||||
export const START_DEBUGGING = Command.toLocalizedCommand(
|
||||
@@ -195,5 +228,16 @@ export namespace Debug {
|
||||
},
|
||||
'vscode/debug.contribution/startDebuggingHelp'
|
||||
);
|
||||
export const TOGGLE_OPTIMIZE_FOR_DEBUG = Command.toLocalizedCommand(
|
||||
{
|
||||
id: 'arduino-toggle-optimize-for-debug',
|
||||
label: 'Optimize for Debugging',
|
||||
category: 'Arduino',
|
||||
},
|
||||
'arduino/debug/optimizeForDebugging'
|
||||
);
|
||||
export const IS_OPTIMIZE_FOR_DEBUG: Command = {
|
||||
id: 'arduino-is-optimize-for-debug',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution';
|
||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
||||
import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service';
|
||||
import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service';
|
||||
import {
|
||||
Contribution,
|
||||
@@ -20,13 +19,10 @@ import type { StandaloneCodeEditor } from '@theia/monaco-editor-core/esm/vs/edit
|
||||
@injectable()
|
||||
export class EditContributions extends Contribution {
|
||||
@inject(MonacoEditorService)
|
||||
protected readonly codeEditorService: MonacoEditorService;
|
||||
private readonly codeEditorService: MonacoEditorService;
|
||||
|
||||
@inject(ClipboardService)
|
||||
protected readonly clipboardService: ClipboardService;
|
||||
|
||||
@inject(PreferenceService)
|
||||
protected readonly preferences: PreferenceService;
|
||||
private readonly clipboardService: ClipboardService;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(EditContributions.Commands.GO_TO_LINE, {
|
||||
|
@@ -202,8 +202,8 @@ export class LibraryExamples extends Examples {
|
||||
protected readonly queue = new PQueue({ autoStart: true, concurrency: 1 });
|
||||
|
||||
override onStart(): void {
|
||||
this.notificationCenter.onLibraryInstalled(() => this.register());
|
||||
this.notificationCenter.onLibraryUninstalled(() => this.register());
|
||||
this.notificationCenter.onLibraryDidInstall(() => this.register());
|
||||
this.notificationCenter.onLibraryDidUninstall(() => this.register());
|
||||
}
|
||||
|
||||
override async onReady(): Promise<void> {
|
||||
|
@@ -0,0 +1,97 @@
|
||||
import { LocalStorageService } from '@theia/core/lib/browser';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { BoardsService, LibraryService } from '../../common/protocol';
|
||||
import { Contribution } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class FirstStartupInstaller extends Contribution {
|
||||
@inject(LocalStorageService)
|
||||
private readonly localStorageService: LocalStorageService;
|
||||
@inject(BoardsService)
|
||||
private readonly boardsService: BoardsService;
|
||||
@inject(LibraryService)
|
||||
private readonly libraryService: LibraryService;
|
||||
|
||||
override async onReady(): Promise<void> {
|
||||
const isFirstStartup = !(await this.localStorageService.getData(
|
||||
FirstStartupInstaller.INIT_LIBS_AND_PACKAGES
|
||||
));
|
||||
if (isFirstStartup) {
|
||||
const avrPackage = await this.boardsService.getBoardPackage({
|
||||
id: 'arduino:avr',
|
||||
});
|
||||
const builtInLibrary = (
|
||||
await this.libraryService.search({ query: 'Arduino_BuiltIn' })
|
||||
)[0];
|
||||
|
||||
let avrPackageError: Error | undefined;
|
||||
let builtInLibraryError: Error | undefined;
|
||||
|
||||
if (avrPackage) {
|
||||
try {
|
||||
await this.boardsService.install({
|
||||
item: avrPackage,
|
||||
noOverwrite: true, // We don't want to automatically replace custom platforms the user might already have in place
|
||||
});
|
||||
} catch (e) {
|
||||
// There's no error code, I need to parse the error message: https://github.com/arduino/arduino-cli/commit/ffe4232b359fcfa87238d68acf1c3b64a1621f14#diff-10ffbdde46838dd9caa881fd1f2a5326a49f8061f6cfd7c9d430b4875a6b6895R62
|
||||
if (
|
||||
e.message.includes(
|
||||
`Platform ${avrPackage.id}@${avrPackage.installedVersion} already installed`
|
||||
)
|
||||
) {
|
||||
// If arduino:avr installation fails because it's already installed we don't want to retry on next start-up
|
||||
console.error(e);
|
||||
} else {
|
||||
// But if there is any other error (e.g.: no interntet cconnection), we want to retry next time
|
||||
avrPackageError = e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
avrPackageError = new Error('Could not find platform.');
|
||||
}
|
||||
|
||||
if (builtInLibrary) {
|
||||
try {
|
||||
await this.libraryService.install({
|
||||
item: builtInLibrary,
|
||||
installDependencies: true,
|
||||
noOverwrite: true, // We don't want to automatically replace custom libraries the user might already have in place
|
||||
});
|
||||
} catch (e) {
|
||||
// There's no error code, I need to parse the error message: https://github.com/arduino/arduino-cli/commit/2ea3608453b17b1157f8a1dc892af2e13e40f4f0#diff-1de7569144d4e260f8dde0e0d00a4e2a218c57966d583da1687a70d518986649R95
|
||||
if (/Library (.*) is already installed/.test(e.message)) {
|
||||
// If Arduino_BuiltIn installation fails because it's already installed we don't want to retry on next start-up
|
||||
console.log('error installing core', e);
|
||||
} else {
|
||||
// But if there is any other error (e.g.: no interntet cconnection), we want to retry next time
|
||||
builtInLibraryError = e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
builtInLibraryError = new Error('Could not find library');
|
||||
}
|
||||
|
||||
if (avrPackageError) {
|
||||
this.messageService.error(
|
||||
`Could not install Arduino AVR platform: ${avrPackageError}`
|
||||
);
|
||||
}
|
||||
if (builtInLibraryError) {
|
||||
this.messageService.error(
|
||||
`Could not install ${builtInLibrary.name} library: ${builtInLibraryError}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!avrPackageError && !builtInLibraryError) {
|
||||
await this.localStorageService.setData(
|
||||
FirstStartupInstaller.INIT_LIBS_AND_PACKAGES,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export namespace FirstStartupInstaller {
|
||||
export const INIT_LIBS_AND_PACKAGES = 'initializedLibsAndPackages';
|
||||
}
|
@@ -49,8 +49,8 @@ export class IncludeLibrary extends SketchContribution {
|
||||
this.boardsServiceClient.onBoardsConfigChanged(() =>
|
||||
this.updateMenuActions()
|
||||
);
|
||||
this.notificationCenter.onLibraryInstalled(() => this.updateMenuActions());
|
||||
this.notificationCenter.onLibraryUninstalled(() =>
|
||||
this.notificationCenter.onLibraryDidInstall(() => this.updateMenuActions());
|
||||
this.notificationCenter.onLibraryDidUninstall(() =>
|
||||
this.updateMenuActions()
|
||||
);
|
||||
}
|
||||
|
@@ -0,0 +1,71 @@
|
||||
import { Progress } from '@theia/core/lib/common/message-service-protocol';
|
||||
import { ProgressService } from '@theia/core/lib/common/progress-service';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { ProgressMessage } from '../../common/protocol';
|
||||
import { NotificationCenter } from '../notification-center';
|
||||
import { Contribution } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class IndexesUpdateProgress extends Contribution {
|
||||
@inject(NotificationCenter)
|
||||
private readonly notificationCenter: NotificationCenter;
|
||||
@inject(ProgressService)
|
||||
private readonly progressService: ProgressService;
|
||||
private currentProgress:
|
||||
| (Progress & Readonly<{ progressId: string }>)
|
||||
| undefined;
|
||||
|
||||
override onStart(): void {
|
||||
this.notificationCenter.onIndexWillUpdate((progressId) =>
|
||||
this.getOrCreateProgress(progressId)
|
||||
);
|
||||
this.notificationCenter.onIndexUpdateDidProgress((progress) => {
|
||||
this.getOrCreateProgress(progress).then((delegate) =>
|
||||
delegate.report(progress)
|
||||
);
|
||||
});
|
||||
this.notificationCenter.onIndexDidUpdate((progressId) => {
|
||||
this.cancelProgress(progressId);
|
||||
});
|
||||
this.notificationCenter.onIndexUpdateDidFail(({ progressId, message }) => {
|
||||
this.cancelProgress(progressId);
|
||||
this.messageService.error(message);
|
||||
});
|
||||
}
|
||||
|
||||
private async getOrCreateProgress(
|
||||
progressOrId: ProgressMessage | string
|
||||
): Promise<Progress & { progressId: string }> {
|
||||
const progressId = ProgressMessage.is(progressOrId)
|
||||
? progressOrId.progressId
|
||||
: progressOrId;
|
||||
if (this.currentProgress?.progressId === progressId) {
|
||||
return this.currentProgress;
|
||||
}
|
||||
if (this.currentProgress) {
|
||||
this.currentProgress.cancel();
|
||||
}
|
||||
this.currentProgress = undefined;
|
||||
const progress = await this.progressService.showProgress({
|
||||
text: '',
|
||||
options: { location: 'notification' },
|
||||
});
|
||||
if (ProgressMessage.is(progressOrId)) {
|
||||
progress.report(progressOrId);
|
||||
}
|
||||
this.currentProgress = { ...progress, progressId };
|
||||
return this.currentProgress;
|
||||
}
|
||||
|
||||
private cancelProgress(progressId: string) {
|
||||
if (this.currentProgress) {
|
||||
if (this.currentProgress.progressId !== progressId) {
|
||||
console.warn(
|
||||
`Mismatching progress IDs. Expected ${progressId}, got ${this.currentProgress.progressId}. Canceling anyway.`
|
||||
);
|
||||
}
|
||||
this.currentProgress.cancel();
|
||||
this.currentProgress = undefined;
|
||||
}
|
||||
}
|
||||
}
|
159
arduino-ide-extension/src/browser/contributions/ino-language.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { Mutex } from 'async-mutex';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
ArduinoDaemon,
|
||||
BoardsService,
|
||||
ExecutableService,
|
||||
} from '../../common/protocol';
|
||||
import { HostedPluginEvents } from '../hosted-plugin-events';
|
||||
import { SketchContribution, URI } from './contribution';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import { BoardsConfig } from '../boards/boards-config';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
|
||||
@injectable()
|
||||
export class InoLanguage extends SketchContribution {
|
||||
@inject(HostedPluginEvents)
|
||||
private readonly hostedPluginEvents: HostedPluginEvents;
|
||||
|
||||
@inject(ExecutableService)
|
||||
private readonly executableService: ExecutableService;
|
||||
|
||||
@inject(ArduinoDaemon)
|
||||
private readonly daemon: ArduinoDaemon;
|
||||
|
||||
@inject(BoardsService)
|
||||
private readonly boardsService: BoardsService;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
private readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
private languageServerFqbn?: string;
|
||||
private languageServerStartMutex = new Mutex();
|
||||
|
||||
override onReady(): void {
|
||||
const start = (
|
||||
{ selectedBoard }: BoardsConfig.Config,
|
||||
forceStart = false
|
||||
) => {
|
||||
if (selectedBoard) {
|
||||
const { name, fqbn } = selectedBoard;
|
||||
if (fqbn) {
|
||||
this.startLanguageServer(fqbn, name, forceStart);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(start);
|
||||
this.hostedPluginEvents.onPluginsDidStart(() =>
|
||||
start(this.boardsServiceProvider.boardsConfig)
|
||||
);
|
||||
this.hostedPluginEvents.onPluginsWillUnload(
|
||||
() => (this.languageServerFqbn = undefined)
|
||||
);
|
||||
this.preferences.onPreferenceChanged(
|
||||
({ preferenceName, oldValue, newValue }) => {
|
||||
if (oldValue !== newValue) {
|
||||
switch (preferenceName) {
|
||||
case 'arduino.language.log':
|
||||
case 'arduino.language.realTimeDiagnostics':
|
||||
start(this.boardsServiceProvider.boardsConfig, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
start(this.boardsServiceProvider.boardsConfig);
|
||||
}
|
||||
|
||||
private async startLanguageServer(
|
||||
fqbn: string,
|
||||
name: string | undefined,
|
||||
forceStart = false
|
||||
): Promise<void> {
|
||||
const port = await this.daemon.tryGetPort();
|
||||
if (!port) {
|
||||
return;
|
||||
}
|
||||
const release = await this.languageServerStartMutex.acquire();
|
||||
try {
|
||||
await this.hostedPluginEvents.didStart;
|
||||
const details = await this.boardsService.getBoardDetails({ fqbn });
|
||||
if (!details) {
|
||||
// Core is not installed for the selected board.
|
||||
console.info(
|
||||
`Could not start language server for ${fqbn}. The core is not installed for the board.`
|
||||
);
|
||||
if (this.languageServerFqbn) {
|
||||
try {
|
||||
await this.commandService.executeCommand(
|
||||
'arduino.languageserver.stop'
|
||||
);
|
||||
console.info(
|
||||
`Stopped language server process for ${this.languageServerFqbn}.`
|
||||
);
|
||||
this.languageServerFqbn = undefined;
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Failed to start language server process for ${this.languageServerFqbn}`,
|
||||
e
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!forceStart && fqbn === this.languageServerFqbn) {
|
||||
// NOOP
|
||||
return;
|
||||
}
|
||||
this.logger.info(`Starting language server: ${fqbn}`);
|
||||
const log = this.preferences.get('arduino.language.log');
|
||||
const realTimeDiagnostics = this.preferences.get(
|
||||
'arduino.language.realTimeDiagnostics'
|
||||
);
|
||||
let currentSketchPath: string | undefined = undefined;
|
||||
if (log) {
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
if (CurrentSketch.isValid(currentSketch)) {
|
||||
currentSketchPath = await this.fileService.fsPath(
|
||||
new URI(currentSketch.uri)
|
||||
);
|
||||
}
|
||||
}
|
||||
const { clangdUri, lsUri } = await this.executableService.list();
|
||||
const [clangdPath, lsPath] = await Promise.all([
|
||||
this.fileService.fsPath(new URI(clangdUri)),
|
||||
this.fileService.fsPath(new URI(lsUri)),
|
||||
]);
|
||||
|
||||
this.languageServerFqbn = await Promise.race([
|
||||
new Promise<undefined>((_, reject) =>
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${20_000} ms.`)),
|
||||
20_000
|
||||
)
|
||||
),
|
||||
this.commandService.executeCommand<string>(
|
||||
'arduino.languageserver.start',
|
||||
{
|
||||
lsPath,
|
||||
cliDaemonAddr: `localhost:${port}`,
|
||||
clangdPath,
|
||||
log: currentSketchPath ? currentSketchPath : log,
|
||||
cliDaemonInstance: '1',
|
||||
board: {
|
||||
fqbn,
|
||||
name: name ? `"${name}"` : undefined,
|
||||
},
|
||||
realTimeDiagnostics,
|
||||
silentOutput: true,
|
||||
}
|
||||
),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.log(`Failed to start language server for ${fqbn}`, e);
|
||||
this.languageServerFqbn = undefined;
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,7 +9,6 @@ import {
|
||||
CommandRegistry,
|
||||
MenuModelRegistry,
|
||||
KeybindingRegistry,
|
||||
TabBarToolbarRegistry,
|
||||
} from './contribution';
|
||||
|
||||
@injectable()
|
||||
@@ -40,15 +39,6 @@ export class NewSketch extends SketchContribution {
|
||||
});
|
||||
}
|
||||
|
||||
override registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
registry.registerItem({
|
||||
id: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id,
|
||||
command: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id,
|
||||
tooltip: nls.localize('arduino/sketch/new', 'New'),
|
||||
priority: 3,
|
||||
});
|
||||
}
|
||||
|
||||
async newSketch(): Promise<void> {
|
||||
try {
|
||||
const sketch = await this.sketchService.createNewSketch();
|
||||
|
@@ -0,0 +1,32 @@
|
||||
import { CommandRegistry } from '@theia/core';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { BoardsConfigDialog } from '../boards/boards-config-dialog';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import { Contribution, Command } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class OpenBoardsConfig extends Contribution {
|
||||
@inject(BoardsServiceProvider)
|
||||
private readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
@inject(BoardsConfigDialog)
|
||||
private readonly boardsConfigDialog: BoardsConfigDialog;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(OpenBoardsConfig.Commands.OPEN_DIALOG, {
|
||||
execute: async (query?: string | undefined) => {
|
||||
const boardsConfig = await this.boardsConfigDialog.open(query);
|
||||
if (boardsConfig) {
|
||||
return (this.boardsServiceProvider.boardsConfig = boardsConfig);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
export namespace OpenBoardsConfig {
|
||||
export namespace Commands {
|
||||
export const OPEN_DIALOG: Command = {
|
||||
id: 'arduino-open-boards-dialog',
|
||||
};
|
||||
}
|
||||
}
|
@@ -36,7 +36,7 @@ export class OpenRecentSketch extends SketchContribution {
|
||||
protected toDisposeBeforeRegister = new Map<string, DisposableCollection>();
|
||||
|
||||
override onStart(): void {
|
||||
this.notificationCenter.onRecentSketchesChanged(({ sketches }) =>
|
||||
this.notificationCenter.onRecentSketchesDidChange(({ sketches }) =>
|
||||
this.refreshMenu(sketches)
|
||||
);
|
||||
}
|
||||
|
@@ -0,0 +1,109 @@
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import type { EditorOpenerOptions } from '@theia/editor/lib/browser/editor-manager';
|
||||
import { SketchesError } from '../../common/protocol';
|
||||
import {
|
||||
Command,
|
||||
CommandRegistry,
|
||||
SketchContribution,
|
||||
URI,
|
||||
} from './contribution';
|
||||
import { SaveAsSketch } from './save-as-sketch';
|
||||
|
||||
@injectable()
|
||||
export class OpenSketchFiles extends SketchContribution {
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(OpenSketchFiles.Commands.OPEN_SKETCH_FILES, {
|
||||
execute: (uri: URI) => this.openSketchFiles(uri),
|
||||
});
|
||||
registry.registerCommand(OpenSketchFiles.Commands.ENSURE_OPENED, {
|
||||
execute: (
|
||||
uri: string,
|
||||
forceOpen?: boolean,
|
||||
options?: EditorOpenerOptions
|
||||
) => {
|
||||
this.ensureOpened(uri, forceOpen, options);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async openSketchFiles(uri: URI): 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 (mainFileUri.endsWith('.pde')) {
|
||||
const message = nls.localize(
|
||||
'arduino/common/oldFormat',
|
||||
"The '{0}' still uses the old `.pde` format. Do you want to switch to the new `.ino` extension?",
|
||||
sketch.name
|
||||
);
|
||||
const yes = nls.localize('vscode/extensionsUtils/yes', 'Yes');
|
||||
this.messageService
|
||||
.info(message, nls.localize('arduino/common/later', 'Later'), yes)
|
||||
.then(async (answer) => {
|
||||
if (answer === yes) {
|
||||
this.commandService.executeCommand(
|
||||
SaveAsSketch.Commands.SAVE_AS_SKETCH.id,
|
||||
{
|
||||
execOnlyIfTemp: false,
|
||||
openAfterMove: true,
|
||||
wipeOriginal: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (SketchesError.NotFound.is(err)) {
|
||||
this.openFallbackSketch();
|
||||
} else {
|
||||
console.error(err);
|
||||
const message =
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: typeof err === 'string'
|
||||
? err
|
||||
: String(err);
|
||||
this.messageService.error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async openFallbackSketch(): Promise<void> {
|
||||
const sketch = await this.sketchService.createNewSketch();
|
||||
this.workspaceService.open(new URI(sketch.uri), { preserveWindow: true });
|
||||
}
|
||||
|
||||
private async ensureOpened(
|
||||
uri: string,
|
||||
forceOpen = false,
|
||||
options?: EditorOpenerOptions
|
||||
): Promise<unknown> {
|
||||
const widget = this.editorManager.all.find(
|
||||
(widget) => widget.editor.uri.toString() === uri
|
||||
);
|
||||
if (!widget || forceOpen) {
|
||||
return this.editorManager.open(
|
||||
new URI(uri),
|
||||
options ?? {
|
||||
mode: 'reveal',
|
||||
preview: false,
|
||||
counter: 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
export namespace OpenSketchFiles {
|
||||
export namespace Commands {
|
||||
export const OPEN_SKETCH_FILES: Command = {
|
||||
id: 'arduino-open-sketch-files',
|
||||
};
|
||||
export const ENSURE_OPENED: Command = {
|
||||
id: 'arduino-ensure-opened',
|
||||
};
|
||||
}
|
||||
}
|
@@ -16,7 +16,6 @@ import {
|
||||
CommandRegistry,
|
||||
MenuModelRegistry,
|
||||
KeybindingRegistry,
|
||||
TabBarToolbarRegistry,
|
||||
} from './contribution';
|
||||
import { ExamplesService } from '../../common/protocol/examples-service';
|
||||
import { BuiltInExamples } from './examples';
|
||||
@@ -131,15 +130,6 @@ export class OpenSketch extends SketchContribution {
|
||||
});
|
||||
}
|
||||
|
||||
override registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
registry.registerItem({
|
||||
id: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id,
|
||||
command: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id,
|
||||
tooltip: nls.localize('vscode/dialogMainService/open', 'Open'),
|
||||
priority: 4,
|
||||
});
|
||||
}
|
||||
|
||||
async openSketch(
|
||||
toOpen: MaybePromise<Sketch | undefined> = this.selectSketch()
|
||||
): Promise<void> {
|
||||
|
@@ -77,15 +77,11 @@ export class SaveAsSketch extends SketchContribution {
|
||||
const exists = await this.fileService.exists(
|
||||
sketchDirUri.resolve(sketch.name)
|
||||
);
|
||||
const defaultUri = exists
|
||||
? sketchDirUri.resolve(
|
||||
sketchDirUri
|
||||
.resolve(
|
||||
`${sketch.name}_copy_${dateFormat(new Date(), 'yyyymmddHHMMss')}`
|
||||
)
|
||||
.toString()
|
||||
)
|
||||
: sketchDirUri.resolve(sketch.name);
|
||||
const defaultUri = sketchDirUri.resolve(
|
||||
exists
|
||||
? `${sketch.name}_copy_${dateFormat(new Date(), 'yyyymmddHHMMss')}`
|
||||
: sketch.name
|
||||
);
|
||||
const defaultPath = await this.fileService.fsPath(defaultUri);
|
||||
const { filePath, canceled } = await remote.dialog.showSaveDialog({
|
||||
title: nls.localize(
|
||||
|
@@ -9,7 +9,6 @@ import {
|
||||
CommandRegistry,
|
||||
MenuModelRegistry,
|
||||
KeybindingRegistry,
|
||||
TabBarToolbarRegistry,
|
||||
} from './contribution';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
@@ -43,15 +42,6 @@ export class SaveSketch extends SketchContribution {
|
||||
});
|
||||
}
|
||||
|
||||
override registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
registry.registerItem({
|
||||
id: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id,
|
||||
command: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id,
|
||||
tooltip: nls.localize('vscode/fileCommands/save', 'Save'),
|
||||
priority: 5,
|
||||
});
|
||||
}
|
||||
|
||||
async saveSketch(): Promise<void> {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
|
@@ -0,0 +1,54 @@
|
||||
import {
|
||||
StatusBar,
|
||||
StatusBarAlignment,
|
||||
} from '@theia/core/lib/browser/status-bar/status-bar';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { BoardsConfig } from '../boards/boards-config';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import { Contribution } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class SelectedBoard extends Contribution {
|
||||
@inject(StatusBar)
|
||||
private readonly statusBar: StatusBar;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
private readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
override onStart(): void {
|
||||
this.boardsServiceProvider.onBoardsConfigChanged((config) =>
|
||||
this.update(config)
|
||||
);
|
||||
}
|
||||
|
||||
override onReady(): void {
|
||||
this.update(this.boardsServiceProvider.boardsConfig);
|
||||
}
|
||||
|
||||
private update({ selectedBoard, selectedPort }: BoardsConfig.Config): void {
|
||||
this.statusBar.setElement('arduino-selected-board', {
|
||||
alignment: StatusBarAlignment.RIGHT,
|
||||
text: selectedBoard
|
||||
? `$(microchip) ${selectedBoard.name}`
|
||||
: `$(close) ${nls.localize(
|
||||
'arduino/common/noBoardSelected',
|
||||
'No board selected'
|
||||
)}`,
|
||||
className: 'arduino-selected-board',
|
||||
});
|
||||
if (selectedBoard) {
|
||||
this.statusBar.setElement('arduino-selected-port', {
|
||||
alignment: StatusBarAlignment.RIGHT,
|
||||
text: selectedPort
|
||||
? nls.localize(
|
||||
'arduino/common/selectedOn',
|
||||
'on {0}',
|
||||
selectedPort.address
|
||||
)
|
||||
: nls.localize('arduino/common/notConnected', '[not connected]'),
|
||||
className: 'arduino-selected-port',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -49,7 +49,10 @@ export class Settings extends SketchContribution {
|
||||
) + '...',
|
||||
order: '0',
|
||||
});
|
||||
registry.registerSubmenu(ArduinoMenus.FILE__ADVANCED_SUBMENU, 'Advanced');
|
||||
registry.registerSubmenu(
|
||||
ArduinoMenus.FILE__ADVANCED_SUBMENU,
|
||||
nls.localize('arduino/menu/advanced', 'Advanced')
|
||||
);
|
||||
}
|
||||
|
||||
override registerKeybindings(registry: KeybindingRegistry): void {
|
||||
|
@@ -276,7 +276,7 @@ export namespace SketchControl {
|
||||
export namespace Commands {
|
||||
export const OPEN_SKETCH_CONTROL__TOOLBAR: Command = {
|
||||
id: 'arduino-open-sketch-control--toolbar',
|
||||
iconClass: 'fa fa-caret-down',
|
||||
iconClass: 'fa fa-arduino-sketch-tabs-menu',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,69 @@
|
||||
import { SaveableWidget } from '@theia/core/lib/browser/saveable';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { FileSystemFrontendContribution } from '@theia/filesystem/lib/browser/filesystem-frontend-contribution';
|
||||
import { FileChangeType } from '@theia/filesystem/lib/common/files';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import { Sketch, SketchContribution, URI } from './contribution';
|
||||
import { OpenSketchFiles } from './open-sketch-files';
|
||||
|
||||
@injectable()
|
||||
export class SketchFilesTracker extends SketchContribution {
|
||||
@inject(FileSystemFrontendContribution)
|
||||
private readonly fileSystemFrontendContribution: FileSystemFrontendContribution;
|
||||
private readonly toDisposeOnStop = new DisposableCollection();
|
||||
|
||||
override onStart(): void {
|
||||
this.fileSystemFrontendContribution.onDidChangeEditorFile(
|
||||
({ type, editor }) => {
|
||||
if (type === FileChangeType.DELETED) {
|
||||
const editorWidget = editor;
|
||||
if (SaveableWidget.is(editorWidget)) {
|
||||
editorWidget.closeWithoutSaving();
|
||||
} else {
|
||||
editorWidget.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
override onReady(): void {
|
||||
this.sketchServiceClient.currentSketch().then(async (sketch) => {
|
||||
if (
|
||||
CurrentSketch.isValid(sketch) &&
|
||||
!(await this.sketchService.isTemp(sketch))
|
||||
) {
|
||||
this.toDisposeOnStop.push(this.fileService.watch(new URI(sketch.uri)));
|
||||
this.toDisposeOnStop.push(
|
||||
this.fileService.onDidFilesChange(async (event) => {
|
||||
for (const { type, resource } of event.changes) {
|
||||
if (
|
||||
type === FileChangeType.ADDED &&
|
||||
resource.parent.toString() === sketch.uri
|
||||
) {
|
||||
const reloadedSketch = await this.sketchService.loadSketch(
|
||||
sketch.uri
|
||||
);
|
||||
if (Sketch.isInSketch(resource, reloadedSketch)) {
|
||||
this.commandService.executeCommand(
|
||||
OpenSketchFiles.Commands.ENSURE_OPENED.id,
|
||||
resource.toString(),
|
||||
true,
|
||||
{
|
||||
mode: 'open',
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onStop(): void {
|
||||
this.toDisposeOnStop.dispose();
|
||||
}
|
||||
}
|
@@ -5,7 +5,11 @@ import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { MainMenuManager } from '../../common/main-menu-manager';
|
||||
import { NotificationCenter } from '../notification-center';
|
||||
import { Examples } from './examples';
|
||||
import { SketchContainer } from '../../common/protocol';
|
||||
import {
|
||||
SketchContainer,
|
||||
SketchesError,
|
||||
SketchRef,
|
||||
} from '../../common/protocol';
|
||||
import { OpenSketch } from './open-sketch';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
|
||||
@@ -24,15 +28,14 @@ export class Sketchbook extends Examples {
|
||||
protected readonly notificationCenter: NotificationCenter;
|
||||
|
||||
override onStart(): void {
|
||||
this.sketchServiceClient.onSketchbookDidChange(() => {
|
||||
this.sketchService.getSketches({}).then((container) => {
|
||||
this.register(container);
|
||||
this.mainMenuManager.update();
|
||||
});
|
||||
});
|
||||
this.sketchServiceClient.onSketchbookDidChange(() => this.update());
|
||||
}
|
||||
|
||||
override async onReady(): Promise<void> {
|
||||
this.update();
|
||||
}
|
||||
|
||||
private update() {
|
||||
this.sketchService.getSketches({}).then((container) => {
|
||||
this.register(container);
|
||||
this.mainMenuManager.update();
|
||||
@@ -59,11 +62,24 @@ export class Sketchbook extends Examples {
|
||||
protected override createHandler(uri: string): CommandHandler {
|
||||
return {
|
||||
execute: async () => {
|
||||
const sketch = await this.sketchService.loadSketch(uri);
|
||||
return this.commandService.executeCommand(
|
||||
OpenSketch.Commands.OPEN_SKETCH.id,
|
||||
sketch
|
||||
);
|
||||
let sketch: SketchRef | undefined = undefined;
|
||||
try {
|
||||
sketch = await this.sketchService.loadSketch(uri);
|
||||
} catch (err) {
|
||||
if (SketchesError.NotFound.is(err)) {
|
||||
// To handle the following:
|
||||
// Open IDE2, delete a sketch from sketchbook, click on File > Sketchbook > the deleted sketch.
|
||||
// Filesystem watcher misses out delete events on macOS; hence IDE2 has no chance to update the menu items.
|
||||
this.messageService.error(err.message);
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
if (sketch) {
|
||||
await this.commandService.executeCommand(
|
||||
OpenSketch.Commands.OPEN_SKETCH.id,
|
||||
sketch
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@@ -3,56 +3,47 @@ import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { BoardUserField, CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus';
|
||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import {
|
||||
CoreServiceContribution,
|
||||
Command,
|
||||
CommandRegistry,
|
||||
MenuModelRegistry,
|
||||
KeybindingRegistry,
|
||||
TabBarToolbarRegistry,
|
||||
CoreServiceContribution,
|
||||
} from './contribution';
|
||||
import { UserFieldsDialog } from '../dialogs/user-fields/user-fields-dialog';
|
||||
import { DisposableCollection, nls } from '@theia/core/lib/common';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import type { VerifySketchParams } from './verify-sketch';
|
||||
|
||||
@injectable()
|
||||
export class UploadSketch extends CoreServiceContribution {
|
||||
@inject(MenuModelRegistry)
|
||||
protected readonly menuRegistry: MenuModelRegistry;
|
||||
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
private readonly menuRegistry: MenuModelRegistry;
|
||||
|
||||
@inject(UserFieldsDialog)
|
||||
protected readonly userFieldsDialog: UserFieldsDialog;
|
||||
private readonly userFieldsDialog: UserFieldsDialog;
|
||||
|
||||
protected cachedUserFields: Map<string, BoardUserField[]> = new Map();
|
||||
private boardRequiresUserFields = false;
|
||||
private readonly cachedUserFields: Map<string, BoardUserField[]> = new Map();
|
||||
private readonly menuActionsDisposables = new DisposableCollection();
|
||||
|
||||
protected readonly onDidChangeEmitter = new Emitter<Readonly<void>>();
|
||||
readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
|
||||
protected uploadInProgress = false;
|
||||
protected boardRequiresUserFields = false;
|
||||
|
||||
protected readonly menuActionsDisposables = new DisposableCollection();
|
||||
private readonly onDidChangeEmitter = new Emitter<void>();
|
||||
private readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
private uploadInProgress = false;
|
||||
|
||||
protected override init(): void {
|
||||
super.init();
|
||||
this.boardsServiceClientImpl.onBoardsConfigChanged(async () => {
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(async () => {
|
||||
const userFields =
|
||||
await this.boardsServiceClientImpl.selectedBoardUserFields();
|
||||
await this.boardsServiceProvider.selectedBoardUserFields();
|
||||
this.boardRequiresUserFields = userFields.length > 0;
|
||||
this.registerMenus(this.menuRegistry);
|
||||
});
|
||||
}
|
||||
|
||||
private selectedFqbnAddress(): string {
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const fqbn = boardsConfig.selectedBoard?.fqbn;
|
||||
if (!fqbn) {
|
||||
return '';
|
||||
@@ -76,7 +67,7 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
if (this.boardRequiresUserFields && !this.cachedUserFields.has(key)) {
|
||||
// Deep clone the array of board fields to avoid editing the cached ones
|
||||
this.userFieldsDialog.value = (
|
||||
await this.boardsServiceClientImpl.selectedBoardUserFields()
|
||||
await this.boardsServiceProvider.selectedBoardUserFields()
|
||||
).map((f) => ({ ...f }));
|
||||
const result = await this.userFieldsDialog.open();
|
||||
if (!result) {
|
||||
@@ -98,8 +89,7 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
const cached = this.cachedUserFields.get(key);
|
||||
// Deep clone the array of board fields to avoid editing the cached ones
|
||||
this.userFieldsDialog.value = (
|
||||
cached ??
|
||||
(await this.boardsServiceClientImpl.selectedBoardUserFields())
|
||||
cached ?? (await this.boardsServiceProvider.selectedBoardUserFields())
|
||||
).map((f) => ({ ...f }));
|
||||
|
||||
const result = await this.userFieldsDialog.open();
|
||||
@@ -130,7 +120,6 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
|
||||
override registerMenus(registry: MenuModelRegistry): void {
|
||||
this.menuActionsDisposables.dispose();
|
||||
|
||||
this.menuActionsDisposables.push(
|
||||
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
|
||||
commandId: UploadSketch.Commands.UPLOAD_SKETCH.id,
|
||||
@@ -153,7 +142,7 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
new PlaceholderMenuNode(
|
||||
ArduinoMenus.SKETCH__MAIN_GROUP,
|
||||
// commandId: UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.id,
|
||||
UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.label!,
|
||||
UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.label,
|
||||
{ order: '2' }
|
||||
)
|
||||
)
|
||||
@@ -193,46 +182,42 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
}
|
||||
|
||||
async uploadSketch(usingProgrammer = false): Promise<void> {
|
||||
// even with buttons disabled, better to double check if an upload is already in progress
|
||||
if (this.uploadInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// toggle the toolbar button and menu item state.
|
||||
// uploadInProgress will be set to false whether the upload fails or not
|
||||
this.uploadInProgress = true;
|
||||
this.coreErrorHandler.reset();
|
||||
this.onDidChangeEmitter.fire();
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const [fqbn, { selectedProgrammer }, verify, verbose, sourceOverride] =
|
||||
await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
this.sourceOverride(),
|
||||
]);
|
||||
|
||||
const board = {
|
||||
...boardsConfig.selectedBoard,
|
||||
name: boardsConfig.selectedBoard?.name || '',
|
||||
fqbn,
|
||||
};
|
||||
let options: CoreService.Upload.Options | undefined = undefined;
|
||||
const optimizeForDebug = this.editorMode.compileForDebug;
|
||||
const { selectedPort } = boardsConfig;
|
||||
const port = selectedPort;
|
||||
const userFields =
|
||||
this.cachedUserFields.get(this.selectedFqbnAddress()) ?? [];
|
||||
if (userFields.length === 0 && this.boardRequiresUserFields) {
|
||||
const verifyOptions =
|
||||
await this.commandService.executeCommand<CoreService.Options.Compile>(
|
||||
'arduino-verify-sketch',
|
||||
<VerifySketchParams>{
|
||||
exportBinaries: false,
|
||||
silent: true,
|
||||
}
|
||||
);
|
||||
if (!verifyOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uploadOptions = await this.uploadOptions(
|
||||
usingProgrammer,
|
||||
verifyOptions
|
||||
);
|
||||
if (!uploadOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: This does not belong here.
|
||||
// IDE2 should not do any preliminary checks but let the CLI fail and then toast a user consumable error message.
|
||||
if (
|
||||
uploadOptions.userFields.length === 0 &&
|
||||
this.boardRequiresUserFields
|
||||
) {
|
||||
this.messageService.error(
|
||||
nls.localize(
|
||||
'arduino/sketch/userFieldsNotFoundError',
|
||||
@@ -242,37 +227,13 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
if (usingProgrammer) {
|
||||
const programmer = selectedProgrammer;
|
||||
options = {
|
||||
sketch,
|
||||
board,
|
||||
optimizeForDebug,
|
||||
programmer,
|
||||
port,
|
||||
verbose,
|
||||
verify,
|
||||
sourceOverride,
|
||||
userFields,
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
sketch,
|
||||
board,
|
||||
optimizeForDebug,
|
||||
port,
|
||||
verbose,
|
||||
verify,
|
||||
sourceOverride,
|
||||
userFields,
|
||||
};
|
||||
}
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
if (usingProgrammer) {
|
||||
await this.coreService.uploadUsingProgrammer(options);
|
||||
} else {
|
||||
await this.coreService.upload(options);
|
||||
}
|
||||
await this.doWithProgress({
|
||||
progressText: nls.localize('arduino/sketch/uploading', 'Uploading...'),
|
||||
task: (progressId, coreService) =>
|
||||
coreService.upload({ ...uploadOptions, progressId }),
|
||||
keepOutput: true,
|
||||
});
|
||||
|
||||
this.messageService.info(
|
||||
nls.localize('arduino/sketch/doneUploading', 'Done uploading.'),
|
||||
{ timeout: 3000 }
|
||||
@@ -284,6 +245,52 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadOptions(
|
||||
usingProgrammer: boolean,
|
||||
verifyOptions: CoreService.Options.Compile
|
||||
): Promise<CoreService.Options.Upload | undefined> {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return undefined;
|
||||
}
|
||||
const userFields = this.userFields();
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] =
|
||||
await Promise.all([
|
||||
verifyOptions.fqbn, // already decorated FQBN
|
||||
this.boardsDataStore.getData(this.sanitizeFqbn(verifyOptions.fqbn)),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
const port = boardsConfig.selectedPort;
|
||||
return {
|
||||
sketch,
|
||||
fqbn,
|
||||
...(usingProgrammer && { programmer }),
|
||||
port,
|
||||
verbose,
|
||||
verify,
|
||||
userFields,
|
||||
};
|
||||
}
|
||||
|
||||
private userFields() {
|
||||
return this.cachedUserFields.get(this.selectedFqbnAddress()) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the `VENDOR:ARCHITECTURE:BOARD_ID[:MENU_ID=OPTION_ID[,MENU2_ID=OPTION_ID ...]]` FQBN to
|
||||
* `VENDOR:ARCHITECTURE:BOARD_ID` format.
|
||||
* See the details of the `{build.fqbn}` entry in the [specs](https://arduino.github.io/arduino-cli/latest/platform-specification/#global-predefined-properties).
|
||||
*/
|
||||
private sanitizeFqbn(fqbn: string | undefined): string | undefined {
|
||||
if (!fqbn) {
|
||||
return undefined;
|
||||
}
|
||||
const [vendor, arch, id] = fqbn.split(':');
|
||||
return `${vendor}:${arch}:${id}`;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace UploadSketch {
|
||||
@@ -291,7 +298,7 @@ export namespace UploadSketch {
|
||||
export const UPLOAD_SKETCH: Command = {
|
||||
id: 'arduino-upload-sketch',
|
||||
};
|
||||
export const UPLOAD_WITH_CONFIGURATION: Command = {
|
||||
export const UPLOAD_WITH_CONFIGURATION: Command & { label: string } = {
|
||||
id: 'arduino-upload-with-configuration-sketch',
|
||||
label: nls.localize(
|
||||
'arduino/sketch/configureAndUpload',
|
||||
|
@@ -2,8 +2,6 @@ import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import {
|
||||
CoreServiceContribution,
|
||||
Command,
|
||||
@@ -14,27 +12,36 @@ import {
|
||||
} from './contribution';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { CoreErrorHandler } from './core-error-handler';
|
||||
|
||||
export interface VerifySketchParams {
|
||||
/**
|
||||
* Same as `CoreService.Options.Compile#exportBinaries`
|
||||
*/
|
||||
readonly exportBinaries?: boolean;
|
||||
/**
|
||||
* If `true`, there won't be any UI indication of the verify command. It's `false` by default.
|
||||
*/
|
||||
readonly silent?: boolean;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class VerifySketch extends CoreServiceContribution {
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
@inject(CoreErrorHandler)
|
||||
private readonly coreErrorHandler: CoreErrorHandler;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
protected readonly onDidChangeEmitter = new Emitter<Readonly<void>>();
|
||||
readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
|
||||
protected verifyInProgress = false;
|
||||
private readonly onDidChangeEmitter = new Emitter<void>();
|
||||
private readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
private verifyInProgress = false;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, {
|
||||
execute: () => this.verifySketch(),
|
||||
execute: (params?: VerifySketchParams) => this.verifySketch(params),
|
||||
isEnabled: () => !this.verifyInProgress,
|
||||
});
|
||||
registry.registerCommand(VerifySketch.Commands.EXPORT_BINARIES, {
|
||||
execute: () => this.verifySketch(true),
|
||||
execute: () => this.verifySketch({ exportBinaries: true }),
|
||||
isEnabled: () => !this.verifyInProgress,
|
||||
});
|
||||
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR, {
|
||||
@@ -84,57 +91,87 @@ export class VerifySketch extends CoreServiceContribution {
|
||||
});
|
||||
}
|
||||
|
||||
async verifySketch(exportBinaries?: boolean): Promise<void> {
|
||||
// even with buttons disabled, better to double check if a verify is already in progress
|
||||
protected override handleError(error: unknown): void {
|
||||
this.coreErrorHandler.tryHandle(error);
|
||||
super.handleError(error);
|
||||
}
|
||||
|
||||
private async verifySketch(
|
||||
params?: VerifySketchParams
|
||||
): Promise<CoreService.Options.Compile | undefined> {
|
||||
if (this.verifyInProgress) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// toggle the toolbar button and menu item state.
|
||||
// verifyInProgress will be set to false whether the compilation fails or not
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.verifyInProgress = true;
|
||||
if (!params?.silent) {
|
||||
this.verifyInProgress = true;
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
this.coreErrorHandler.reset();
|
||||
this.onDidChangeEmitter.fire();
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const [fqbn, sourceOverride] = await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
|
||||
const options = await this.options(params?.exportBinaries);
|
||||
if (!options) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
await this.doWithProgress({
|
||||
progressText: nls.localize(
|
||||
'arduino/sketch/compile',
|
||||
'Compiling sketch...'
|
||||
),
|
||||
this.sourceOverride(),
|
||||
]);
|
||||
const board = {
|
||||
...boardsConfig.selectedBoard,
|
||||
name: boardsConfig.selectedBoard?.name || '',
|
||||
fqbn,
|
||||
};
|
||||
const verbose = this.preferences.get('arduino.compile.verbose');
|
||||
const compilerWarnings = this.preferences.get('arduino.compile.warnings');
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
await this.coreService.compile({
|
||||
sketch,
|
||||
board,
|
||||
optimizeForDebug: this.editorMode.compileForDebug,
|
||||
verbose,
|
||||
exportBinaries,
|
||||
sourceOverride,
|
||||
compilerWarnings,
|
||||
task: (progressId, coreService) =>
|
||||
coreService.compile({
|
||||
...options,
|
||||
progressId,
|
||||
}),
|
||||
});
|
||||
this.messageService.info(
|
||||
nls.localize('arduino/sketch/doneCompiling', 'Done compiling.'),
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
// Returns with the used options for the compilation
|
||||
// so that follow-up tasks (such as upload) can reuse the compiled code.
|
||||
// Note that the `fqbn` is already decorated with the board settings, if any.
|
||||
return options;
|
||||
} catch (e) {
|
||||
this.handleError(e);
|
||||
return undefined;
|
||||
} finally {
|
||||
this.verifyInProgress = false;
|
||||
this.onDidChangeEmitter.fire();
|
||||
if (!params?.silent) {
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async options(
|
||||
exportBinaries?: boolean
|
||||
): Promise<CoreService.Options.Compile | undefined> {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return undefined;
|
||||
}
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const [fqbn, sourceOverride, optimizeForDebug] = await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard?.fqbn),
|
||||
this.sourceOverride(),
|
||||
this.commandService.executeCommand<boolean>(
|
||||
'arduino-is-optimize-for-debug'
|
||||
),
|
||||
]);
|
||||
const verbose = this.preferences.get('arduino.compile.verbose');
|
||||
const compilerWarnings = this.preferences.get('arduino.compile.warnings');
|
||||
return {
|
||||
sketch,
|
||||
fqbn,
|
||||
optimizeForDebug: Boolean(optimizeForDebug),
|
||||
verbose,
|
||||
exportBinaries,
|
||||
sourceOverride,
|
||||
compilerWarnings,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace VerifySketch {
|
||||
|
@@ -507,7 +507,8 @@ export class CreateApi {
|
||||
}
|
||||
|
||||
private domain(apiVersion = 'v2'): string {
|
||||
const endpoint = this.arduinoPreferences['arduino.cloud.sketchSyncEnpoint'];
|
||||
const endpoint =
|
||||
this.arduinoPreferences['arduino.cloud.sketchSyncEndpoint'];
|
||||
return `${endpoint}/${apiVersion}`;
|
||||
}
|
||||
|
||||
|
@@ -1,128 +0,0 @@
|
||||
{
|
||||
"tokenColors": [
|
||||
{
|
||||
"settings": {
|
||||
"foreground": "#434f54"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Comments",
|
||||
"scope": "comment",
|
||||
"settings": {
|
||||
"foreground": "#95a5a6cc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Keywords Attributes",
|
||||
"scope": [
|
||||
"storage",
|
||||
"support",
|
||||
"string.quoted.single.c"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#00979D"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "literal",
|
||||
"scope": [
|
||||
"meta.function.c",
|
||||
"entity.name.function",
|
||||
"meta.function-call.c",
|
||||
"variable.other"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#D35400"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "punctuation",
|
||||
"scope": [
|
||||
"punctuation.section",
|
||||
"meta.function-call.c",
|
||||
"meta.block.c",
|
||||
"meta.function.c",
|
||||
"entity.name.function.preprocessor.c",
|
||||
"meta.preprocessor.macro.c",
|
||||
"variable",
|
||||
"variable.name"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#434f54"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "constants",
|
||||
"scope": [
|
||||
"string.quoted.double",
|
||||
"constant"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#005C5F"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "meta keywords",
|
||||
"scope": [
|
||||
"keyword.control",
|
||||
"meta.preprocessor.c"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#728E00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "numeric preprocessor",
|
||||
"scope": [
|
||||
"meta.preprocessor.macro.c",
|
||||
"constant.numeric.preprocessor.c",
|
||||
"meta.preprocessor.c"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#434f54"
|
||||
}
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
"list.highlightForeground": "#005c5f",
|
||||
"list.activeSelectionForeground": "#424242",
|
||||
"list.activeSelectionBackground": "#DAE3E3",
|
||||
"list.inactiveSelectionForeground": "#424242",
|
||||
"list.inactiveSelectionBackground": "#DAE3E3",
|
||||
"list.hoverBackground": "#ECF1F1",
|
||||
"progressBar.background": "#005c5f",
|
||||
"editor.background": "#ffffff",
|
||||
"editorCursor.foreground": "#434f54",
|
||||
"editor.foreground": "#434f54",
|
||||
"editorWhitespace.foreground": "#bfbfbf",
|
||||
"editor.lineHighlightBackground": "#434f5410",
|
||||
"editor.selectionBackground": "#ffcb00",
|
||||
"editorWidget.background": "#F7F9F9",
|
||||
"focusBorder": "#7fcbcd99",
|
||||
"menubar.selectionBackground": "#ffffff",
|
||||
"menubar.selectionForeground": "#212121",
|
||||
"menu.selectionBackground": "#dae3e3",
|
||||
"menu.selectionForeground": "#212121",
|
||||
"editorGroupHeader.tabsBackground": "#f7f9f9",
|
||||
"button.background": "#7fcbcd",
|
||||
"titleBar.activeBackground": "#005c5f",
|
||||
"titleBar.activeForeground": "#ffffff",
|
||||
"terminal.background": "#000000",
|
||||
"terminal.foreground": "#e0e0e0",
|
||||
"dropdown.border": "#ececec",
|
||||
"dropdown.background": "#ececec",
|
||||
"activityBar.background": "#ececec",
|
||||
"activityBar.foreground": "#616161",
|
||||
"statusBar.background": "#005c5f",
|
||||
"secondaryButton.background": "#b5c8c9",
|
||||
"secondaryButton.foreground": "#ececec",
|
||||
"secondaryButton.hoverBackground": "#dae3e3",
|
||||
"arduino.branding.primary": "#00979d",
|
||||
"arduino.branding.secondary": "#b5c8c9",
|
||||
"arduino.foreground": "#edf1f1",
|
||||
"arduino.output.foreground": "#FFFFFF",
|
||||
"arduino.output.background": "#000000"
|
||||
},
|
||||
"type": "light",
|
||||
"name": "Arduino"
|
||||
}
|
@@ -4,18 +4,20 @@
|
||||
"colors": {
|
||||
"list.highlightForeground": "#0ca1a6",
|
||||
"list.activeSelectionForeground": "#dae3e3",
|
||||
"list.activeSelectionBackground": "#434f54",
|
||||
"list.activeSelectionBackground": "#0ca1a64d",
|
||||
"list.inactiveSelectionForeground": "#dae3e3",
|
||||
"list.inactiveSelectionBackground": "#434f54",
|
||||
"list.hoverBackground": "#1f272a",
|
||||
"list.activeSelectionIconForeground": "#0ca1a6",
|
||||
"progressBar.background": "#005c5f",
|
||||
"editor.background": "#1f272a",
|
||||
"editor.foreground": "#dae3e3",
|
||||
"editor.lineHighlightBackground": "#434f5410",
|
||||
"editor.selectionBackground": "#f1c40f",
|
||||
"editor.selectionBackground": "#00818480",
|
||||
"editorCursor.foreground": "#434f54",
|
||||
"editorWhitespace.foreground": "#bfbfbf",
|
||||
"editorWidget.background": "#171e21",
|
||||
"editorWidget.foreground": "#dae3e3",
|
||||
"focusBorder": "#dae3e3",
|
||||
"menubar.selectionBackground": "#ffffff",
|
||||
"menubar.selectionForeground": "#212121",
|
||||
@@ -23,10 +25,12 @@
|
||||
"menu.selectionForeground": "#212121",
|
||||
"editorGroupHeader.tabsBackground": "#171e21",
|
||||
"button.background": "#0ca1a6",
|
||||
"button.foreground": "#101618",
|
||||
"button.hoverBackground": "#7fcbcd",
|
||||
"titleBar.activeBackground": "#171e21",
|
||||
"titleBar.activeForeground": "#dae3e3",
|
||||
"terminal.background": "#000000",
|
||||
"terminal.foreground": "#e0e0e0",
|
||||
"terminal.foreground": "#ffffff",
|
||||
"dropdown.border": "#7fcbcd",
|
||||
"dropdown.background": "#2c353a",
|
||||
"dropdown.foreground": "#dae3e3",
|
||||
@@ -37,20 +41,33 @@
|
||||
"statusBar.background": "#171e21",
|
||||
"secondaryButton.background": "#ff000000",
|
||||
"secondaryButton.foreground": "#dae3e3",
|
||||
"secondaryButton.hoverBackground": "#434f54",
|
||||
"secondaryButton.hoverBackground": "#ffffff1a",
|
||||
"arduino.branding.primary": "#0ca1a6",
|
||||
"arduino.branding.secondary": "#b5c8c9",
|
||||
"arduino.foreground": "#edf1f1",
|
||||
"arduino.output.foreground": "#ffffff",
|
||||
"arduino.output.background": "#000000",
|
||||
"arduino.toolbar.hoverBackground": "#dae3e3",
|
||||
"arduino.toolbar.button.hoverBackground": "#dae3e3",
|
||||
"arduino.toolbar.button.secondary.label": "#dae3e3",
|
||||
"arduino.toolbar.button.secondary.hoverBackground": "#dae3e366",
|
||||
"arduino.toolbar.button.background": "#0ca1a6",
|
||||
"arduino.toolbar.dropdown.border": "#7fcbcd",
|
||||
"arduino.toolbar.dropdown.borderActive": "#0ca1a6",
|
||||
"arduino.toolbar.dropdown.background": "#2c353a",
|
||||
"arduino.toolbar.dropdown.label": "#dae3e3",
|
||||
"arduino.toolbar.dropdown.iconSelected": "#3fae98",
|
||||
"arduino.toolbar.dropdown.option.backgroundHover": "#374146",
|
||||
"arduino.toolbar.dropdown.option.backgroundSelected": "#4e5b61",
|
||||
"arduino.toolbar.toggleBackground": "#f1c40f",
|
||||
"sideBar.background": "#101618",
|
||||
"sideBar.foreground": "#dae3e3",
|
||||
"input.background": "#000000",
|
||||
"foreground": "#dae3e3",
|
||||
"settings.headerForeground": "#dae3e3",
|
||||
"tree.indentGuidesStroke": "#374146",
|
||||
"tab.unfocusedActiveForeground": "#dae3e3",
|
||||
"tab.inactiveBackground": "#171e21"
|
||||
"tab.inactiveBackground": "#171e21",
|
||||
"textLink.foreground": "#0ca1a6"
|
||||
},
|
||||
"tokenColors": [
|
||||
{
|
||||
@@ -146,4 +163,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@@ -4,30 +4,34 @@
|
||||
"colors": {
|
||||
"list.highlightForeground": "#008184",
|
||||
"list.activeSelectionForeground": "#4e5b61",
|
||||
"list.activeSelectionBackground": "#dae3e3",
|
||||
"list.activeSelectionBackground": "#00818433",
|
||||
"list.inactiveSelectionForeground": "#4e5b61",
|
||||
"list.inactiveSelectionBackground": "#dae3e3",
|
||||
"list.hoverBackground": "#ecf1f1",
|
||||
"list.activeSelectionIconForeground": "#008184",
|
||||
"progressBar.background": "#005c5f",
|
||||
"editor.background": "#ffffff",
|
||||
"editor.foreground": "#4e5b61",
|
||||
"editor.lineHighlightBackground": "#434f5410",
|
||||
"editor.selectionBackground": "#f1c40f",
|
||||
"editor.selectionBackground": "#7fcbcdb3",
|
||||
"editorCursor.foreground": "#434f54",
|
||||
"editorWhitespace.foreground": "#bfbfbf",
|
||||
"editorWidget.background": "#f7f9f9",
|
||||
"editorWidget.foreground": "#4e5b61",
|
||||
"focusBorder": "#7fcbcd",
|
||||
"menubar.selectionBackground": "#ffffff",
|
||||
"menubar.selectionForeground": "#212121",
|
||||
"menu.selectionBackground": "#dae3e3",
|
||||
"menu.selectionForeground": "#212121",
|
||||
"editorGroupHeader.tabsBackground": "#ecf1f1",
|
||||
"button.background": "#7fcbcd",
|
||||
"button.background": "#008184",
|
||||
"button.foreground": "#f7f9f9",
|
||||
"button.hoverBackground": "#005C5F",
|
||||
"titleBar.activeBackground": "#006d70",
|
||||
"titleBar.activeForeground": "#f7f9f9",
|
||||
"terminal.background": "#000000",
|
||||
"terminal.foreground": "#e0e0e0",
|
||||
"dropdown.border": "#f7f9f9",
|
||||
"terminal.foreground": "#ffffff",
|
||||
"dropdown.border": "#dae3e3",
|
||||
"dropdown.background": "#ffffff",
|
||||
"dropdown.foreground": "#4e5b61",
|
||||
"activityBar.background": "#ecf1f1",
|
||||
@@ -37,20 +41,33 @@
|
||||
"statusBar.background": "#006d70",
|
||||
"secondaryButton.background": "#ff000000",
|
||||
"secondaryButton.foreground": "#008184",
|
||||
"secondaryButton.hoverBackground": "#dae3e3",
|
||||
"secondaryButton.hoverBackground": "#005c5f1a",
|
||||
"arduino.branding.primary": "#008184",
|
||||
"arduino.branding.secondary": "#b5c8c9",
|
||||
"arduino.foreground": "#edf1f1",
|
||||
"arduino.output.foreground": "#ffffff",
|
||||
"arduino.output.background": "#000000",
|
||||
"arduino.toolbar.hoverBackground": "#f7f9f9",
|
||||
"arduino.toolbar.button.hoverBackground": "#f7f9f9",
|
||||
"arduino.toolbar.button.secondary.label": "#dae3e3",
|
||||
"arduino.toolbar.button.secondary.hoverBackground": "#dae3e366",
|
||||
"arduino.toolbar.button.background": "#7fcbcd",
|
||||
"arduino.toolbar.dropdown.border": "#dae3e3",
|
||||
"arduino.toolbar.dropdown.borderActive": "#7fcbcd",
|
||||
"arduino.toolbar.dropdown.background": "#ffffff",
|
||||
"arduino.toolbar.dropdown.label": "#4e5b61",
|
||||
"arduino.toolbar.dropdown.iconSelected": "#1da086",
|
||||
"arduino.toolbar.dropdown.option.backgroundHover": "#ecf1f1",
|
||||
"arduino.toolbar.dropdown.option.backgroundSelected": "#dae3e3",
|
||||
"arduino.toolbar.toggleBackground": "#f1c40f",
|
||||
"sideBar.background": "#f7f9f9",
|
||||
"sideBar.foreground": "#4e5b61",
|
||||
"input.background": "#ffffff",
|
||||
"foreground": "#4e5b61",
|
||||
"settings.headerForeground": "#4e5b61",
|
||||
"tree.indentGuidesStroke": "#dae3e3",
|
||||
"tab.unfocusedActiveForeground": "#4e5b61",
|
||||
"tab.inactiveBackground": "#ecf1f1"
|
||||
"tab.inactiveBackground": "#ecf1f1",
|
||||
"textLink.foreground": "#008184"
|
||||
},
|
||||
"tokenColors": [
|
||||
{
|
||||
@@ -146,4 +163,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@@ -94,7 +94,7 @@ export const CertificateUploaderComponent = ({
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="theia-button primary add-cert-btn"
|
||||
className="theia-button secondary add-cert-btn"
|
||||
onClick={() => {
|
||||
showAdd ? setShowAdd(false) : setShowAdd(true);
|
||||
}}
|
||||
|
@@ -12,10 +12,10 @@ import {
|
||||
IDEUpdater,
|
||||
IDEUpdaterClient,
|
||||
ProgressInfo,
|
||||
SKIP_IDE_VERSION,
|
||||
UpdateInfo,
|
||||
} from '../../../common/protocol/ide-updater';
|
||||
import { LocalStorageService } from '@theia/core/lib/browser';
|
||||
import { SKIP_IDE_VERSION } from '../../arduino-frontend-contribution';
|
||||
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||
|
||||
@injectable()
|
||||
|
@@ -21,7 +21,15 @@ import {
|
||||
AsyncLocalizationProvider,
|
||||
LanguageInfo,
|
||||
} from '@theia/core/lib/common/i18n/localization';
|
||||
import SettingsStepInput from './settings-step-input';
|
||||
|
||||
const maxScale = 200;
|
||||
const minScale = -100;
|
||||
const scaleStep = 20;
|
||||
|
||||
const maxFontSize = 72;
|
||||
const minFontSize = 0;
|
||||
const fontSizeStep = 2;
|
||||
export class SettingsComponent extends React.Component<
|
||||
SettingsComponent.Props,
|
||||
SettingsComponent.State
|
||||
@@ -88,6 +96,8 @@ export class SettingsComponent extends React.Component<
|
||||
}
|
||||
|
||||
protected renderSettings(): React.ReactNode {
|
||||
const scalePercentage = 100 + this.state.interfaceScale * 20;
|
||||
|
||||
return (
|
||||
<div className="content noselect">
|
||||
{nls.localize(
|
||||
@@ -119,7 +129,7 @@ export class SettingsComponent extends React.Component<
|
||||
'Show files inside Sketches'
|
||||
)}
|
||||
</label>
|
||||
<div className="flex-line">
|
||||
<div className="column-container">
|
||||
<div className="column">
|
||||
<div className="flex-line">
|
||||
{nls.localize(
|
||||
@@ -160,14 +170,13 @@ export class SettingsComponent extends React.Component<
|
||||
</div>
|
||||
<div className="column">
|
||||
<div className="flex-line">
|
||||
<input
|
||||
className="theia-input small"
|
||||
type="number"
|
||||
step={1}
|
||||
pattern="[0-9]+"
|
||||
onKeyDown={this.numbersOnlyKeyDown}
|
||||
<SettingsStepInput
|
||||
value={this.state.editorFontSize}
|
||||
onChange={this.editorFontSizeDidChange}
|
||||
setSettingsStateValue={this.setFontSize}
|
||||
step={fontSizeStep}
|
||||
maxValue={maxFontSize}
|
||||
minValue={minFontSize}
|
||||
classNames={{ input: 'theia-input small' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-line">
|
||||
@@ -179,14 +188,13 @@ export class SettingsComponent extends React.Component<
|
||||
/>
|
||||
{nls.localize('arduino/preferences/automatic', 'Automatic')}
|
||||
</label>
|
||||
<input
|
||||
className="theia-input small with-margin"
|
||||
type="number"
|
||||
step={20}
|
||||
pattern="[0-9]+"
|
||||
onKeyDown={this.noopKeyDown}
|
||||
value={100 + this.state.interfaceScale * 20}
|
||||
onChange={this.interfaceScaleDidChange}
|
||||
<SettingsStepInput
|
||||
value={scalePercentage}
|
||||
setSettingsStateValue={this.setInterfaceScale}
|
||||
step={scaleStep}
|
||||
maxValue={maxScale}
|
||||
minValue={minScale}
|
||||
classNames={{ input: 'theia-input small with-margin' }}
|
||||
/>
|
||||
%
|
||||
</div>
|
||||
@@ -516,13 +524,8 @@ export class SettingsComponent extends React.Component<
|
||||
}
|
||||
};
|
||||
|
||||
protected editorFontSizeDidChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
): void => {
|
||||
const { value } = event.target;
|
||||
if (value) {
|
||||
this.setState({ editorFontSize: parseInt(value, 10) });
|
||||
}
|
||||
private setFontSize = (editorFontSize: number) => {
|
||||
this.setState({ editorFontSize });
|
||||
};
|
||||
|
||||
protected rawAdditionalUrlsValueDidChange = (
|
||||
@@ -539,18 +542,10 @@ export class SettingsComponent extends React.Component<
|
||||
this.setState({ autoScaleInterface: event.target.checked });
|
||||
};
|
||||
|
||||
protected interfaceScaleDidChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
): void => {
|
||||
const { value } = event.target;
|
||||
const percentage = parseInt(value, 10);
|
||||
if (isNaN(percentage)) {
|
||||
return;
|
||||
}
|
||||
private setInterfaceScale = (percentage: number) => {
|
||||
const interfaceScale = (percentage - 100) / 20;
|
||||
if (!isNaN(interfaceScale)) {
|
||||
this.setState({ interfaceScale });
|
||||
}
|
||||
|
||||
this.setState({ interfaceScale });
|
||||
};
|
||||
|
||||
protected verifyAfterUploadDidChange = (
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
injectable,
|
||||
inject,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||
import { DialogError, ReactWidget } from '@theia/core/lib/browser';
|
||||
import { AbstractDialog, DialogProps } from '@theia/core/lib/browser';
|
||||
import { DialogError, DialogProps, ReactWidget } from '@theia/core/lib/browser';
|
||||
import { Settings, SettingsService } from './settings';
|
||||
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
||||
import { WindowService } from '@theia/core/lib/browser/window/window-service';
|
||||
@@ -12,6 +15,7 @@ import { nls } from '@theia/core/lib/common';
|
||||
import { SettingsComponent } from './settings-component';
|
||||
import { AsyncLocalizationProvider } from '@theia/core/lib/common/i18n/localization';
|
||||
import { AdditionalUrls } from '../../../common/protocol';
|
||||
import { AbstractDialog } from '../../theia/dialogs/dialogs';
|
||||
|
||||
@injectable()
|
||||
export class SettingsWidget extends ReactWidget {
|
||||
@@ -59,6 +63,7 @@ export class SettingsDialog extends AbstractDialog<Promise<Settings>> {
|
||||
protected override readonly props: SettingsDialogProps
|
||||
) {
|
||||
super(props);
|
||||
this.node.id = 'arduino-settings-dialog-container';
|
||||
this.contentNode.classList.add('arduino-settings-dialog');
|
||||
this.appendCloseButton(
|
||||
nls.localize('vscode/issueMainService/cancel', 'Cancel')
|
||||
@@ -73,7 +78,9 @@ export class SettingsDialog extends AbstractDialog<Promise<Settings>> {
|
||||
);
|
||||
}
|
||||
|
||||
protected override async isValid(settings: Promise<Settings>): Promise<DialogError> {
|
||||
protected override async isValid(
|
||||
settings: Promise<Settings>
|
||||
): Promise<DialogError> {
|
||||
const result = await this.settingsService.validate(settings);
|
||||
if (typeof result === 'string') {
|
||||
return result;
|
||||
|
@@ -0,0 +1,93 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
interface SettingsStepInputProps {
|
||||
value: number;
|
||||
setSettingsStateValue: (value: number) => void;
|
||||
step: number;
|
||||
maxValue: number;
|
||||
minValue: number;
|
||||
classNames?: { [key: string]: string };
|
||||
}
|
||||
|
||||
const SettingsStepInput: React.FC<SettingsStepInputProps> = (
|
||||
props: SettingsStepInputProps
|
||||
) => {
|
||||
const { value, setSettingsStateValue, step, maxValue, minValue, classNames } =
|
||||
props;
|
||||
|
||||
const clamp = (value: number, min: number, max: number): number => {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
};
|
||||
|
||||
const onStep = (
|
||||
roundingOperation: 'ceil' | 'floor',
|
||||
stepOperation: (a: number, b: number) => number
|
||||
): void => {
|
||||
const valueRoundedToScale = Math[roundingOperation](value / step) * step;
|
||||
const calculatedValue =
|
||||
valueRoundedToScale === value
|
||||
? stepOperation(value, step)
|
||||
: valueRoundedToScale;
|
||||
const newValue = clamp(calculatedValue, minValue, maxValue);
|
||||
|
||||
setSettingsStateValue(newValue);
|
||||
};
|
||||
|
||||
const onStepUp = (): void => {
|
||||
onStep('ceil', (a: number, b: number) => a + b);
|
||||
};
|
||||
|
||||
const onStepDown = (): void => {
|
||||
onStep('floor', (a: number, b: number) => a - b);
|
||||
};
|
||||
|
||||
const onUserInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const { value: eventValue } = event.target;
|
||||
|
||||
if (eventValue === '') {
|
||||
setSettingsStateValue(0);
|
||||
}
|
||||
|
||||
const number = Number(eventValue);
|
||||
|
||||
if (!isNaN(number) && number !== value) {
|
||||
const newValue = clamp(number, minValue, maxValue);
|
||||
|
||||
setSettingsStateValue(newValue);
|
||||
}
|
||||
};
|
||||
|
||||
const upDisabled = value >= maxValue;
|
||||
const downDisabled = value <= minValue;
|
||||
|
||||
return (
|
||||
<div className="settings-step-input-container">
|
||||
<input
|
||||
className={classnames('settings-step-input-element', classNames?.input)}
|
||||
value={value.toString()}
|
||||
onChange={onUserInput}
|
||||
type="number"
|
||||
pattern="[0-9]+"
|
||||
/>
|
||||
<div className="settings-step-input-buttons-container">
|
||||
<button
|
||||
className="settings-step-input-button settings-step-input-up-button"
|
||||
disabled={upDisabled}
|
||||
onClick={onStepUp}
|
||||
>
|
||||
▾
|
||||
</button>
|
||||
<button
|
||||
className="settings-step-input-button"
|
||||
disabled={downDisabled}
|
||||
onClick={onStepDown}
|
||||
>
|
||||
▾
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsStepInput;
|
@@ -139,7 +139,10 @@ export class SettingsService {
|
||||
this.preferenceService.get<number>(FONT_SIZE_SETTING, 12),
|
||||
this.preferenceService.get<string>(
|
||||
'workbench.colorTheme',
|
||||
'arduino-theme'
|
||||
window.matchMedia &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? 'arduino-theme-dark'
|
||||
: 'arduino-theme'
|
||||
),
|
||||
this.preferenceService.get<Settings.AutoSave>(
|
||||
AUTO_SAVE_SETTING,
|
||||
|
@@ -1,37 +0,0 @@
|
||||
import { injectable, inject } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
FrontendApplicationContribution,
|
||||
FrontendApplication,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { MainMenuManager } from '../common/main-menu-manager';
|
||||
|
||||
@injectable()
|
||||
export class EditorMode implements FrontendApplicationContribution {
|
||||
@inject(MainMenuManager)
|
||||
protected readonly mainMenuManager: MainMenuManager;
|
||||
|
||||
protected app: FrontendApplication;
|
||||
|
||||
onStart(app: FrontendApplication): void {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
get compileForDebug(): boolean {
|
||||
const value = window.localStorage.getItem(EditorMode.COMPILE_FOR_DEBUG_KEY);
|
||||
return value === 'true';
|
||||
}
|
||||
|
||||
async toggleCompileForDebug(): Promise<void> {
|
||||
const oldState = this.compileForDebug;
|
||||
const newState = !oldState;
|
||||
window.localStorage.setItem(
|
||||
EditorMode.COMPILE_FOR_DEBUG_KEY,
|
||||
String(newState)
|
||||
);
|
||||
this.mainMenuManager.update();
|
||||
}
|
||||
}
|
||||
|
||||
export namespace EditorMode {
|
||||
export const COMPILE_FOR_DEBUG_KEY = 'arduino-compile-for-debug';
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
<svg width="25" height="20" viewBox="0 0 25 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.125 14C20.125 14.2321 20.0328 14.4546 19.8687 14.6187C19.7046 14.7828 19.4821 14.875 19.25 14.875H10.5C10.2679 14.875 10.0454 14.7828 9.88128 14.6187C9.71719 14.4546 9.625 14.2321 9.625 14C9.625 13.7679 9.71719 13.5454 9.88128 13.3813C10.0454 13.2172 10.2679 13.125 10.5 13.125H19.25C19.4821 13.125 19.7046 13.2172 19.8687 13.3813C20.0328 13.5454 20.125 13.7679 20.125 14Z" fill="black"/>
|
||||
<path d="M24.2462 6.37875L22.75 4.89125V0.875C22.75 0.642936 22.6578 0.420376 22.4937 0.256282C22.3296 0.0921874 22.1071 0 21.875 0H3.5C3.26794 0 3.04538 0.0921874 2.88128 0.256282C2.71719 0.420376 2.625 0.642936 2.625 0.875V3.5H0.875C0.642936 3.5 0.420376 3.59219 0.256282 3.75628C0.0921872 3.92038 0 4.14294 0 4.375V8.75C0 8.98206 0.0921872 9.20462 0.256282 9.36872C0.420376 9.53281 0.642936 9.625 0.875 9.625H2.625V18.375C2.625 18.6071 2.71719 18.8296 2.88128 18.9937C3.04538 19.1578 3.26794 19.25 3.5 19.25H21.875C21.9902 19.2507 22.1043 19.2286 22.2109 19.1851C22.3175 19.1415 22.4145 19.0773 22.4962 18.9962L24.2462 17.2462C24.3273 17.1645 24.3915 17.0675 24.4351 16.9609C24.4786 16.8543 24.5007 16.7402 24.5 16.625V7C24.5007 6.88484 24.4786 6.77069 24.4351 6.66408C24.3915 6.55747 24.3273 6.46051 24.2462 6.37875ZM1.75 7.875V5.25H6.125V7.875H1.75ZM22.75 16.2663L21.5163 17.5H4.375V9.625H7C7.23206 9.625 7.45462 9.53281 7.61872 9.36872C7.78281 9.20462 7.875 8.98206 7.875 8.75V4.375C7.875 4.14294 7.78281 3.92038 7.61872 3.75628C7.45462 3.59219 7.23206 3.5 7 3.5H4.375V1.75H21V5.25C20.9993 5.36516 21.0214 5.47931 21.0649 5.58592C21.1085 5.69253 21.1727 5.78949 21.2538 5.87125L22.75 7.35875V16.2663Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
3
arduino-ide-extension/src/browser/icons/monitor.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.1858 13.92C8.73525 13.92 7.38744 13.4748 6.27173 12.7138L4.24581 14.7397C3.89434 15.0912 3.3245 15.0912 2.97303 14.7397C2.62156 14.3882 2.62156 13.8184 2.97303 13.4669L4.92544 11.5145C3.86685 10.2933 3.2258 8.70059 3.2258 6.95998C3.2258 3.11999 6.3458 0 10.1858 0C14.0258 0 17.1458 3.11999 17.1458 6.95998C17.1458 10.8 14.0258 13.92 10.1858 13.92ZM10.1858 2.4C7.6658 2.4 5.6258 4.43999 5.6258 6.95998C5.6258 9.47998 7.6658 11.52 10.1858 11.52C12.6938 11.52 14.7458 9.47998 14.7458 6.95998C14.7458 4.45199 12.7058 2.4 10.1858 2.4ZM17.9619 7.47017C17.9619 8.02365 18.4106 8.47233 18.9641 8.47233C19.5176 8.47233 19.9662 8.02365 19.9662 7.47017C19.9662 6.91669 19.5176 6.468 18.9641 6.468C18.4106 6.468 17.9619 6.91669 17.9619 7.47017ZM1.001 8.47246C0.448162 8.47246 0 8.0243 0 7.47147C0 6.91863 0.448162 6.47047 1.001 6.47047C1.55383 6.47047 2.002 6.91863 2.002 7.47147C2.002 8.0243 1.55383 8.47246 1.001 8.47246ZM22.7923 8.47233C22.2389 8.47233 21.7902 8.02365 21.7902 7.47017C21.7902 6.91669 22.2389 6.468 22.7923 6.468C23.3458 6.468 23.7945 6.91669 23.7945 7.47017C23.7945 8.02365 23.3458 8.47233 22.7923 8.47233ZM10.1978 8.23198C9.49529 8.23198 8.9258 7.66249 8.9258 6.95999C8.9258 6.25748 9.49529 5.68799 10.1978 5.68799C10.9003 5.68799 11.4698 6.25748 11.4698 6.95999C11.4698 7.66249 10.9003 8.23198 10.1978 8.23198Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
3
arduino-ide-extension/src/browser/icons/plotter.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 18.0019C5.62402 18.0019 5.27637 17.79 5.10547 17.4492L2.38184 12.0019H1C0.44727 12.0019 0 11.5546 0 11.0019C0 10.4492 0.44727 10.0019 1 10.0019H3C3.37891 10.0019 3.72461 10.2158 3.89453 10.5546L5.68555 14.1367L9.03028 0.759723C9.13868 0.322223 9.52637 0.0126525 9.97657 0.00191246C10.4209 -0.0273875 10.8281 0.283163 10.958 0.714803L13.7442 10.0019H15C15.5527 10.0019 16 10.4492 16 11.0019C16 11.5546 15.5527 12.0019 15 12.0019H13C12.5586 12.0019 12.169 11.7119 12.042 11.289L10.0879 4.77437L6.96974 17.2441C6.86818 17.6504 6.5254 17.9502 6.10939 17.9961C6.07228 18 6.03615 18.0019 6.00001 18.0019H6Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 732 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="13" height="3" viewBox="0 0 13 3" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.1875 2.25C6.80882 2.25 7.3125 1.74632 7.3125 1.125C7.3125 0.50368 6.80882 0 6.1875 0C5.56618 0 5.0625 0.50368 5.0625 1.125C5.0625 1.74632 5.56618 2.25 6.1875 2.25Z" fill="black"/>
|
||||
<path d="M11.25 2.25C11.8713 2.25 12.375 1.74632 12.375 1.125C12.375 0.50368 11.8713 0 11.25 0C10.6287 0 10.125 0.50368 10.125 1.125C10.125 1.74632 10.6287 2.25 11.25 2.25Z" fill="black"/>
|
||||
<path d="M1.125 2.25C1.74632 2.25 2.25 1.74632 2.25 1.125C2.25 0.50368 1.74632 0 1.125 0C0.50368 0 0 0.50368 0 1.125C0 1.74632 0.50368 2.25 1.125 2.25Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 650 B |
3
arduino-ide-extension/src/browser/icons/upload.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.71 7.71253L9.70996 13.7125C9.51001 13.9025 9.26001 14.0026 9 14.0026C8.73999 14.0026 8.48999 13.9025 8.29004 13.7125C7.90003 13.3226 7.90003 12.6825 8.29004 12.2926L12.5901 8.00257H1C0.44995 8.00257 0 7.55261 0 7.00256C0 6.45251 0.44995 6.00256 1 6.00256H12.5901L8.29004 1.71253C7.90003 1.32264 7.90003 0.682495 8.29004 0.292605C8.67993 -0.097535 9.32007 -0.097535 9.70996 0.292605L15.71 6.2926C16.1 6.68249 16.1 7.32264 15.71 7.71253V7.71253Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 576 B |
3
arduino-ide-extension/src/browser/icons/verify.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="11" viewBox="0 0 16 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 11C5.74414 11 5.48827 10.9023 5.29296 10.707L0.292965 5.70702C-0.097655 5.3164 -0.097655 4.68358 0.292965 4.29296C0.683585 3.90234 1.31641 3.90234 1.70703 4.29296L6 8.58593L14.293 0.292965C14.6836 -0.097655 15.3164 -0.097655 15.707 0.292965C16.0976 0.683585 16.0976 1.31641 15.707 1.70703L6.70703 10.707C6.51172 10.9023 6.25586 11 6 11Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 468 B |
@@ -52,9 +52,12 @@ export class IDEUpdaterCommands implements CommandContribution {
|
||||
}
|
||||
}
|
||||
export namespace IDEUpdaterCommands {
|
||||
export const CHECK_FOR_UPDATES: Command = {
|
||||
id: 'arduino-ide-check-for-updates',
|
||||
category: 'Arduino',
|
||||
label: 'Check for Arduino IDE updates',
|
||||
};
|
||||
export const CHECK_FOR_UPDATES: Command = Command.toLocalizedCommand(
|
||||
{
|
||||
id: 'arduino-ide-check-for-updates',
|
||||
label: 'Check for Arduino IDE updates',
|
||||
category: 'Arduino',
|
||||
},
|
||||
'arduino/ide-updater/checkForUpdates'
|
||||
);
|
||||
}
|
||||
|
@@ -41,8 +41,8 @@ export class LibraryListWidget extends ListWidget<LibraryPackage> {
|
||||
protected override init(): void {
|
||||
super.init();
|
||||
this.toDispose.pushAll([
|
||||
this.notificationCenter.onLibraryInstalled(() => this.refresh(undefined)),
|
||||
this.notificationCenter.onLibraryUninstalled(() =>
|
||||
this.notificationCenter.onLibraryDidInstall(() => this.refresh(undefined)),
|
||||
this.notificationCenter.onLibraryDidUninstall(() =>
|
||||
this.refresh(undefined)
|
||||
),
|
||||
]);
|
||||
|
@@ -17,6 +17,7 @@ import {
|
||||
LibraryPackage,
|
||||
Config,
|
||||
Sketch,
|
||||
ProgressMessage,
|
||||
} from '../common/protocol';
|
||||
import {
|
||||
FrontendApplicationStateService,
|
||||
@@ -33,25 +34,32 @@ export class NotificationCenter
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
protected readonly indexUpdatedEmitter = new Emitter<void>();
|
||||
protected readonly daemonStartedEmitter = new Emitter<string>();
|
||||
protected readonly daemonStoppedEmitter = new Emitter<void>();
|
||||
protected readonly configChangedEmitter = new Emitter<{
|
||||
protected readonly indexDidUpdateEmitter = new Emitter<string>();
|
||||
protected readonly indexWillUpdateEmitter = new Emitter<string>();
|
||||
protected readonly indexUpdateDidProgressEmitter =
|
||||
new Emitter<ProgressMessage>();
|
||||
protected readonly indexUpdateDidFailEmitter = new Emitter<{
|
||||
progressId: string;
|
||||
message: string;
|
||||
}>();
|
||||
protected readonly daemonDidStartEmitter = new Emitter<string>();
|
||||
protected readonly daemonDidStopEmitter = new Emitter<void>();
|
||||
protected readonly configDidChangeEmitter = new Emitter<{
|
||||
config: Config | undefined;
|
||||
}>();
|
||||
protected readonly platformInstalledEmitter = new Emitter<{
|
||||
protected readonly platformDidInstallEmitter = new Emitter<{
|
||||
item: BoardsPackage;
|
||||
}>();
|
||||
protected readonly platformUninstalledEmitter = new Emitter<{
|
||||
protected readonly platformDidUninstallEmitter = new Emitter<{
|
||||
item: BoardsPackage;
|
||||
}>();
|
||||
protected readonly libraryInstalledEmitter = new Emitter<{
|
||||
protected readonly libraryDidInstallEmitter = new Emitter<{
|
||||
item: LibraryPackage;
|
||||
}>();
|
||||
protected readonly libraryUninstalledEmitter = new Emitter<{
|
||||
protected readonly libraryDidUninstallEmitter = new Emitter<{
|
||||
item: LibraryPackage;
|
||||
}>();
|
||||
protected readonly attachedBoardsChangedEmitter =
|
||||
protected readonly attachedBoardsDidChangeEmitter =
|
||||
new Emitter<AttachedBoardsChangeEvent>();
|
||||
protected readonly recentSketchesChangedEmitter = new Emitter<{
|
||||
sketches: Sketch[];
|
||||
@@ -60,27 +68,34 @@ export class NotificationCenter
|
||||
new Emitter<FrontendApplicationState>();
|
||||
|
||||
protected readonly toDispose = new DisposableCollection(
|
||||
this.indexUpdatedEmitter,
|
||||
this.daemonStartedEmitter,
|
||||
this.daemonStoppedEmitter,
|
||||
this.configChangedEmitter,
|
||||
this.platformInstalledEmitter,
|
||||
this.platformUninstalledEmitter,
|
||||
this.libraryInstalledEmitter,
|
||||
this.libraryUninstalledEmitter,
|
||||
this.attachedBoardsChangedEmitter
|
||||
this.indexWillUpdateEmitter,
|
||||
this.indexUpdateDidProgressEmitter,
|
||||
this.indexDidUpdateEmitter,
|
||||
this.indexUpdateDidFailEmitter,
|
||||
this.daemonDidStartEmitter,
|
||||
this.daemonDidStopEmitter,
|
||||
this.configDidChangeEmitter,
|
||||
this.platformDidInstallEmitter,
|
||||
this.platformDidUninstallEmitter,
|
||||
this.libraryDidInstallEmitter,
|
||||
this.libraryDidUninstallEmitter,
|
||||
this.attachedBoardsDidChangeEmitter
|
||||
);
|
||||
|
||||
readonly onIndexUpdated = this.indexUpdatedEmitter.event;
|
||||
readonly onDaemonStarted = this.daemonStartedEmitter.event;
|
||||
readonly onDaemonStopped = this.daemonStoppedEmitter.event;
|
||||
readonly onConfigChanged = this.configChangedEmitter.event;
|
||||
readonly onPlatformInstalled = this.platformInstalledEmitter.event;
|
||||
readonly onPlatformUninstalled = this.platformUninstalledEmitter.event;
|
||||
readonly onLibraryInstalled = this.libraryInstalledEmitter.event;
|
||||
readonly onLibraryUninstalled = this.libraryUninstalledEmitter.event;
|
||||
readonly onAttachedBoardsChanged = this.attachedBoardsChangedEmitter.event;
|
||||
readonly onRecentSketchesChanged = this.recentSketchesChangedEmitter.event;
|
||||
readonly onIndexDidUpdate = this.indexDidUpdateEmitter.event;
|
||||
readonly onIndexWillUpdate = this.indexDidUpdateEmitter.event;
|
||||
readonly onIndexUpdateDidProgress = this.indexUpdateDidProgressEmitter.event;
|
||||
readonly onIndexUpdateDidFail = this.indexUpdateDidFailEmitter.event;
|
||||
readonly onDaemonDidStart = this.daemonDidStartEmitter.event;
|
||||
readonly onDaemonDidStop = this.daemonDidStopEmitter.event;
|
||||
readonly onConfigDidChange = this.configDidChangeEmitter.event;
|
||||
readonly onPlatformDidInstall = this.platformDidInstallEmitter.event;
|
||||
readonly onPlatformDidUninstall = this.platformDidUninstallEmitter.event;
|
||||
readonly onLibraryDidInstall = this.libraryDidInstallEmitter.event;
|
||||
readonly onLibraryDidUninstall = this.libraryDidUninstallEmitter.event;
|
||||
readonly onAttachedBoardsDidChange =
|
||||
this.attachedBoardsDidChangeEmitter.event;
|
||||
readonly onRecentSketchesDidChange = this.recentSketchesChangedEmitter.event;
|
||||
readonly onAppStateDidChange = this.onAppStateDidChangeEmitter.event;
|
||||
|
||||
@postConstruct()
|
||||
@@ -97,43 +112,61 @@ export class NotificationCenter
|
||||
this.toDispose.dispose();
|
||||
}
|
||||
|
||||
notifyIndexUpdated(): void {
|
||||
this.indexUpdatedEmitter.fire();
|
||||
notifyIndexWillUpdate(progressId: string): void {
|
||||
this.indexWillUpdateEmitter.fire(progressId);
|
||||
}
|
||||
|
||||
notifyDaemonStarted(port: string): void {
|
||||
this.daemonStartedEmitter.fire(port);
|
||||
notifyIndexUpdateDidProgress(progressMessage: ProgressMessage): void {
|
||||
this.indexUpdateDidProgressEmitter.fire(progressMessage);
|
||||
}
|
||||
|
||||
notifyDaemonStopped(): void {
|
||||
this.daemonStoppedEmitter.fire();
|
||||
notifyIndexDidUpdate(progressId: string): void {
|
||||
this.indexDidUpdateEmitter.fire(progressId);
|
||||
}
|
||||
|
||||
notifyConfigChanged(event: { config: Config | undefined }): void {
|
||||
this.configChangedEmitter.fire(event);
|
||||
notifyIndexUpdateDidFail({
|
||||
progressId,
|
||||
message,
|
||||
}: {
|
||||
progressId: string;
|
||||
message: string;
|
||||
}): void {
|
||||
this.indexUpdateDidFailEmitter.fire({ progressId, message });
|
||||
}
|
||||
|
||||
notifyPlatformInstalled(event: { item: BoardsPackage }): void {
|
||||
this.platformInstalledEmitter.fire(event);
|
||||
notifyDaemonDidStart(port: string): void {
|
||||
this.daemonDidStartEmitter.fire(port);
|
||||
}
|
||||
|
||||
notifyPlatformUninstalled(event: { item: BoardsPackage }): void {
|
||||
this.platformUninstalledEmitter.fire(event);
|
||||
notifyDaemonDidStop(): void {
|
||||
this.daemonDidStopEmitter.fire();
|
||||
}
|
||||
|
||||
notifyLibraryInstalled(event: { item: LibraryPackage }): void {
|
||||
this.libraryInstalledEmitter.fire(event);
|
||||
notifyConfigDidChange(event: { config: Config | undefined }): void {
|
||||
this.configDidChangeEmitter.fire(event);
|
||||
}
|
||||
|
||||
notifyLibraryUninstalled(event: { item: LibraryPackage }): void {
|
||||
this.libraryUninstalledEmitter.fire(event);
|
||||
notifyPlatformDidInstall(event: { item: BoardsPackage }): void {
|
||||
this.platformDidInstallEmitter.fire(event);
|
||||
}
|
||||
|
||||
notifyAttachedBoardsChanged(event: AttachedBoardsChangeEvent): void {
|
||||
this.attachedBoardsChangedEmitter.fire(event);
|
||||
notifyPlatformDidUninstall(event: { item: BoardsPackage }): void {
|
||||
this.platformDidUninstallEmitter.fire(event);
|
||||
}
|
||||
|
||||
notifyRecentSketchesChanged(event: { sketches: Sketch[] }): void {
|
||||
notifyLibraryDidInstall(event: { item: LibraryPackage }): void {
|
||||
this.libraryDidInstallEmitter.fire(event);
|
||||
}
|
||||
|
||||
notifyLibraryDidUninstall(event: { item: LibraryPackage }): void {
|
||||
this.libraryDidUninstallEmitter.fire(event);
|
||||
}
|
||||
|
||||
notifyAttachedBoardsDidChange(event: AttachedBoardsChangeEvent): void {
|
||||
this.attachedBoardsDidChangeEmitter.fire(event);
|
||||
}
|
||||
|
||||
notifyRecentSketchesDidChange(event: { sketches: Sketch[] }): void {
|
||||
this.recentSketchesChangedEmitter.fire(event);
|
||||
}
|
||||
}
|
||||
|
@@ -7,11 +7,11 @@ import {
|
||||
import {
|
||||
OutputMessage,
|
||||
ProgressMessage,
|
||||
ResponseServiceArduino,
|
||||
ResponseServiceClient,
|
||||
} from '../common/protocol/response-service';
|
||||
|
||||
@injectable()
|
||||
export class ResponseServiceImpl implements ResponseServiceArduino {
|
||||
export class ResponseServiceImpl implements ResponseServiceClient {
|
||||
@inject(OutputChannelManager)
|
||||
private readonly outputChannelManager: OutputChannelManager;
|
||||
|
||||
@@ -19,7 +19,7 @@ export class ResponseServiceImpl implements ResponseServiceArduino {
|
||||
|
||||
readonly onProgressDidChange = this.progressDidChangeEmitter.event;
|
||||
|
||||
clearArduinoChannel(): void {
|
||||
clearOutput(): void {
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
}
|
||||
|
||||
|
@@ -13,20 +13,26 @@ import { ipcRenderer } from '@theia/electron/shared/electron';
|
||||
import { MonitorManagerProxyClient } from '../../../common/protocol';
|
||||
import { BoardsServiceProvider } from '../../boards/boards-service-provider';
|
||||
import { MonitorModel } from '../../monitor-model';
|
||||
import { ArduinoToolbar } from '../../toolbar/arduino-toolbar';
|
||||
|
||||
const queryString = require('query-string');
|
||||
|
||||
export namespace SerialPlotterContribution {
|
||||
export namespace Commands {
|
||||
export const OPEN: Command = {
|
||||
id: 'serial-plotter-open',
|
||||
label: 'Serial Plotter',
|
||||
category: 'Arduino',
|
||||
};
|
||||
export const OPEN: Command = Command.toLocalizedCommand(
|
||||
{
|
||||
id: 'serial-plotter-open',
|
||||
label: 'Serial Plotter',
|
||||
category: 'Arduino',
|
||||
},
|
||||
'arduino/serial/openSerialPlotter'
|
||||
);
|
||||
|
||||
export const RESET: Command = {
|
||||
id: 'serial-plotter-reset',
|
||||
label: 'Reset Serial Plotter',
|
||||
category: 'Arduino',
|
||||
};
|
||||
export const OPEN_TOOLBAR: Command = {
|
||||
id: 'serial-plotter-open-toolbar',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -69,6 +75,14 @@ export class PlotterFrontendContribution extends Contribution {
|
||||
registry.registerCommand(SerialPlotterContribution.Commands.RESET, {
|
||||
execute: () => this.reset(),
|
||||
});
|
||||
registry.registerCommand(
|
||||
{ id: SerialPlotterContribution.Commands.OPEN_TOOLBAR.id },
|
||||
{
|
||||
isVisible: (widget) =>
|
||||
ArduinoToolbar.is(widget) && widget.side === 'right',
|
||||
execute: this.startPlotter.bind(this),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
override registerMenus(menus: MenuModelRegistry): void {
|
||||
|
@@ -49,3 +49,14 @@
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/* High Contrast Theme rules */
|
||||
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
|
||||
.hc-black.hc-theia.theia-hc .arduino-select__option--is-selected {
|
||||
outline: 1px solid var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .arduino-select__option--is-focused {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ div.dialogContent.select-board-dialog > div.head .title {
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.02em;
|
||||
font-size: 1.2em;
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
color: var(--theia-editorWidget-foreground);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ div#select-board-dialog .selectBoardContainer .body .list .item.selected {
|
||||
}
|
||||
|
||||
div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
color: var(--theia-list-activeSelectionIconForeground);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .search,
|
||||
@@ -43,7 +43,7 @@ div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
display: flex;
|
||||
color: var(--theia-editor-foreground);
|
||||
color: var(--theia-input-foreground);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .search input:focus {
|
||||
@@ -66,7 +66,7 @@ div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .container .content .title {
|
||||
color: #7f8c8d;
|
||||
color: var(--theia-editorWidget-foreground);
|
||||
padding: 0px 0px 10px 0px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .container .content .loading {
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
color: var(--theia-arduino-branding-secondary);
|
||||
color: var(--theia-editorWidget-foreground);
|
||||
padding: 10px 5px 10px 10px;
|
||||
text-transform: uppercase;
|
||||
/* The max, min-height comes from `.body .list` 200px + 47px top padding - 2 * 10px top padding */
|
||||
@@ -142,96 +142,132 @@ div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
|
||||
.p-Widget.dialogOverlay .dialogContent.select-board-dialog {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container {
|
||||
margin-left: 3px;
|
||||
align-items: center;
|
||||
background: var(--theia-arduino-toolbar-dropdown-background);
|
||||
border-radius: 1px;
|
||||
color: var(--theia-arduino-toolbar-dropdown-label);
|
||||
border: 1px solid var(--theia-arduino-toolbar-dropdown-border);
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
height: 28px;
|
||||
margin: 0 4px;
|
||||
overflow: hidden;
|
||||
padding: 0 10px;
|
||||
width: 210px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item--protocol,
|
||||
.arduino-boards-dropdown-item--protocol {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item--protocol ,
|
||||
.arduino-boards-dropdown-item--protocol {
|
||||
color: var(--theia-arduino-toolbar-dropdown-label);
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container
|
||||
.arduino-boards-toolbar-item
|
||||
.inner-container {
|
||||
.arduino-boards-toolbar-item {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container
|
||||
.arduino-boards-toolbar-item
|
||||
.inner-container
|
||||
.notAttached {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
color: red;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container
|
||||
.arduino-boards-toolbar-item
|
||||
.inner-container
|
||||
.guessed {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
color: var(--theia-warningBackground);
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item .label {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 5px;
|
||||
.arduino-boards-toolbar-item--label {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item .caret {
|
||||
.arduino-boards-toolbar-item--label-connected {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container .caret {
|
||||
width: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item {
|
||||
background: var(--theia-tab-unfocusedActiveBackground);
|
||||
color: var(--theia-foreground);
|
||||
height: 22px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0px 3px 0px 3px;
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-list {
|
||||
border: 3px solid var(--theia-activityBar-background);
|
||||
margin: -1px;
|
||||
z-index: 1;
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
border: 1px solid var(--theia-arduino-toolbar-dropdown-border);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-list:focus {
|
||||
border: 1px solid var(--theia-arduino-toolbar-dropdown-borderActive);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-list--items-container {
|
||||
overflow: auto;
|
||||
max-height: 404px;
|
||||
background: var(--theia-arduino-toolbar-dropdown-background);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-list--items-container::-webkit-scrollbar {
|
||||
background: var(--theia-arduino-toolbar-dropdown-background);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item {
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
background: var(--theia-arduino-toolbar-dropdown-background);
|
||||
color: var(--theia-arduino-toolbar-dropdown-label);
|
||||
cursor: default;
|
||||
display: flex;
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
gap: 10px;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
color: var(--theia-foreground);
|
||||
background: var(--theia-tab-unfocusedActiveBackground);
|
||||
border: 1px solid var(--theia-tab-unfocusedActiveBackground);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item--label {
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item--board-label {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item--port-label {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item:hover {
|
||||
background: var(--theia-arduino-toolbar-dropdown-option-backgroundHover);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item--selected,
|
||||
.arduino-boards-dropdown-item--selected:hover {
|
||||
background: var(--theia-arduino-toolbar-dropdown-option-backgroundSelected);
|
||||
border: 1px solid var(--theia-arduino-toolbar-dropdown-option-backgroundSelected);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item--selected
|
||||
.arduino-boards-dropdown-item--port-label {
|
||||
color: var(--theia-arduino-toolbar-dropdown-label);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item--selected .fa {
|
||||
color: var(--theia-arduino-toolbar-dropdown-iconSelected);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item .fa-check {
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item.selected,
|
||||
.arduino-boards-dropdown-item:hover {
|
||||
border: 1px solid var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.arduino-board-dropdown-footer {
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
color: var(--theia-secondaryButton-foreground);
|
||||
border-top: 1px solid var(--theia-dropdown-border);
|
||||
}
|
||||
|
||||
/* High Contrast Theme rules */
|
||||
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
|
||||
.hc-black.hc-theia.theia-hc #select-board-dialog .selectBoardContainer .body .list .item:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc div#select-board-dialog .selectBoardContainer .body .list .item.selected {
|
||||
outline: 1px solid var(--theia-focusBorder);
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
}
|
||||
.certificate-uploader-dialog .arduino-select__control {
|
||||
height: 31px;
|
||||
background: var(--theia-menubar-selectionBackground) !important;
|
||||
background: var(--theia-dropdown-background) !important;
|
||||
}
|
||||
|
||||
.certificate-uploader-dialog .dialogRow > button{
|
||||
@@ -15,9 +15,10 @@
|
||||
}
|
||||
|
||||
.certificate-uploader-dialog .certificate-list {
|
||||
border: 1px solid #BDC7C7;
|
||||
border: 1px solid var(--theia-editorWidget-border);
|
||||
border-radius: 2px;;
|
||||
background: var(--theia-menubar-selectionBackground) !important;
|
||||
color: var(--theia-editor-foreground);
|
||||
background-color: var(--theia-editor-background);
|
||||
overflow: auto;
|
||||
height: 120px;
|
||||
flex: 1;
|
||||
@@ -60,9 +61,10 @@
|
||||
|
||||
.certificate-add {
|
||||
padding: 16px;
|
||||
background-color: var(--theia-list-hoverBackground);
|
||||
border-radius: 3px;
|
||||
border: 1px solid #BDC7C7;
|
||||
border: 1px solid var(--theia-editorWidget-border);
|
||||
color: var(--theia-editorWidget-foreground);
|
||||
background-color: var(--theia-editorWidget-background);
|
||||
}
|
||||
|
||||
.certificate-add input {
|
||||
@@ -71,4 +73,4 @@
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,14 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.27 20H2.58C1.80648 17.3894 1.80648 14.6106 2.58 12H7.27C7.08644 13.3254 6.99622 14.662 7 16C6.99622 17.338 7.08644 18.6746 7.27 20Z" fill="black"/>
|
||||
<path d="M7.63999 22C8.12954 24.499 9.15286 26.8629 10.64 28.93C7.43807 27.5988 4.84154 25.1305 3.34999 22H7.63999Z" fill="black"/>
|
||||
<path d="M7.63999 9.99982H3.34999C4.84154 6.86936 7.43807 4.40106 10.64 3.06982C9.15286 5.13697 8.12954 7.50082 7.63999 9.99982Z" fill="black"/>
|
||||
<path d="M15 2.1499V9.9999H9.7C10.71 5.8999 12.69 2.8399 15 2.1499Z" fill="black"/>
|
||||
<path d="M9.29999 12H15V20H9.29999C8.90004 17.3483 8.90004 14.6517 9.29999 12Z" fill="black"/>
|
||||
<path d="M9.7 22H15V29.85C12.69 29.16 10.71 26.1 9.7 22Z" fill="black"/>
|
||||
<path d="M22.3 22C21.3 26.1 19.3 29.16 17 29.85V22H22.3Z" fill="black"/>
|
||||
<path d="M22.3 9.9999H17V2.1499C19.31 2.8399 21.29 5.8999 22.3 9.9999Z" fill="black"/>
|
||||
<path d="M22.7 20H17V12H22.7C22.8985 13.3241 22.9987 14.6611 23 16C22.9987 17.3389 22.8985 18.6759 22.7 20Z" fill="black"/>
|
||||
<path d="M24.36 22H28.65C27.1584 25.1305 24.5619 27.5988 21.36 28.93C22.8471 26.8629 23.8704 24.499 24.36 22Z" fill="black"/>
|
||||
<path d="M24.36 9.99982C23.8704 7.50082 22.8471 5.13697 21.36 3.06982C24.5619 4.40106 27.1584 6.86936 28.65 9.99982H24.36Z" fill="black"/>
|
||||
<path d="M30 16C30.0023 17.3545 29.8069 18.702 29.42 20H24.73C24.9136 18.6746 25.0038 17.338 25 16C25.0038 14.662 24.9136 13.3254 24.73 12H29.42C29.8069 13.298 30.0023 14.6455 30 16Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,14 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.54383 11.5H0.612583C0.129139 9.86839 0.129139 8.13161 0.612583 6.5H3.54383C3.42911 7.32835 3.37272 8.16374 3.37508 9C3.37272 9.83626 3.42911 10.6716 3.54383 11.5Z" fill="#616161"/>
|
||||
<path d="M3.775 12.75C4.08097 14.3119 4.72054 15.7893 5.65 17.0812C3.6488 16.2492 2.02597 14.7065 1.09375 12.75H3.775Z" fill="#616161"/>
|
||||
<path d="M3.775 5.25001H1.09375C2.02597 3.29347 3.6488 1.75079 5.65 0.918762C4.72054 2.21073 4.08097 3.68814 3.775 5.25001Z" fill="#616161"/>
|
||||
<path d="M8.375 0.34375V5.25H5.0625C5.69375 2.6875 6.93125 0.775 8.375 0.34375Z" fill="#616161"/>
|
||||
<path d="M4.81248 6.5H8.37498V11.5H4.81248C4.56251 9.84271 4.56251 8.15729 4.81248 6.5Z" fill="#616161"/>
|
||||
<path d="M5.0625 12.75H8.375V17.6562C6.93125 17.225 5.69375 15.3125 5.0625 12.75Z" fill="#616161"/>
|
||||
<path d="M12.9375 12.75C12.3125 15.3125 11.0625 17.225 9.625 17.6562V12.75H12.9375Z" fill="#616161"/>
|
||||
<path d="M12.9375 5.25H9.625V0.34375C11.0688 0.775 12.3063 2.6875 12.9375 5.25Z" fill="#616161"/>
|
||||
<path d="M13.1875 11.5H9.625V6.5H13.1875C13.3115 7.32757 13.3742 8.16318 13.375 9C13.3742 9.83682 13.3115 10.6724 13.1875 11.5Z" fill="#616161"/>
|
||||
<path d="M14.2251 12.75H16.9063C15.9741 14.7065 14.3513 16.2492 12.3501 17.0812C13.2796 15.7893 13.9191 14.3119 14.2251 12.75Z" fill="#616161"/>
|
||||
<path d="M14.2251 5.25001C13.9191 3.68814 13.2796 2.21073 12.3501 0.918762C14.3513 1.75079 15.9741 3.29347 16.9063 5.25001H14.2251Z" fill="#616161"/>
|
||||
<path d="M17.7503 9C17.7517 9.84653 17.6296 10.6887 17.3878 11.5H14.4565C14.5713 10.6716 14.6277 9.83626 14.6253 9C14.6277 8.16374 14.5713 7.32835 14.4565 6.5H17.3878C17.6296 7.31126 17.7517 8.15347 17.7503 9Z" fill="#616161"/>
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14 0C11.2311 0 8.52431 0.821086 6.22202 2.35943C3.91973 3.89777 2.12532 6.08427 1.06569 8.64243C0.00606596 11.2006 -0.271181 14.0155 0.269012 16.7313C0.809205 19.447 2.14258 21.9416 4.10051 23.8995C6.05845 25.8574 8.55301 27.1908 11.2687 27.731C13.9845 28.2712 16.7994 27.9939 19.3576 26.9343C21.9157 25.8747 24.1022 24.0803 25.6406 21.778C27.1789 19.4757 28 16.7689 28 14C28 10.287 26.525 6.72601 23.8995 4.1005C21.274 1.475 17.713 0 14 0ZM8.91001 3.13C7.72372 4.90553 6.90746 6.90195 6.51001 9H3.09001C4.2822 6.42178 6.34208 4.34421 8.91001 3.13ZM2.00001 14C1.9988 12.9879 2.12649 11.9798 2.38001 11H6.18001C5.94001 12.9928 5.94001 15.0072 6.18001 17H2.38001C2.12649 16.0202 1.9988 15.0121 2.00001 14ZM3.09001 19H6.51001C6.90746 21.0981 7.72372 23.0945 8.91001 24.87C6.34208 23.6558 4.2822 21.5782 3.09001 19ZM13 25.82C11.06 25.14 9.40001 22.5 8.58001 19H13V25.82ZM13 17H8.21001C7.92996 15.0098 7.92996 12.9902 8.21001 11H13V17ZM13 9H8.58001C9.40001 5.5 11.06 2.86 13 2.18V9ZM24.91 9H21.49C21.0926 6.90195 20.2763 4.90553 19.09 3.13C21.6579 4.34421 23.7178 6.42178 24.91 9ZM15 2.18C16.94 2.86 18.6 5.5 19.43 9H15V2.18ZM15 11H19.79C20.0701 12.9902 20.0701 15.0098 19.79 17H15V11ZM15 25.82V19H19.43C18.6 22.5 16.94 25.14 15 25.82ZM19.09 24.87C20.2763 23.0945 21.0926 21.0981 21.49 19H24.91C23.7178 21.5782 21.6579 23.6558 19.09 24.87ZM21.82 17C21.9418 16.0047 22.002 15.0028 22 14C22.002 12.9972 21.9418 11.9953 21.82 11H25.62C26.1281 12.9677 26.1281 15.0323 25.62 17H21.82Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -13,12 +13,23 @@
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.cloud-sketchbook-tree-icon {
|
||||
background: url("./cloud-sketchbook-tree-icon.svg") center center no-repeat;
|
||||
.p-TabBar-tabIcon.cloud-sketchbook-tree-icon {
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./cloud-sketchbook-tree-icon.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
width: var(--theia-icon-size);
|
||||
height: var(--theia-icon-size);
|
||||
background-size: auto 90%;
|
||||
-webkit-mask-size: 100%;
|
||||
}
|
||||
|
||||
.p-mod-current
|
||||
.cloud-sketchbook-tree-icon {
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./cloud-sketchbook-tree-icon-filled.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
-webkit-mask-size: 100%;
|
||||
}
|
||||
|
||||
.sketchbook-trees-container
|
||||
@@ -65,7 +76,7 @@
|
||||
.p-Widget.p-TabBar.p-DockPanel-tabBar
|
||||
> ul
|
||||
> li.p-TabBar-tab.p-mod-current {
|
||||
border-bottom: 2px solid var(--theia-statusBar-background);
|
||||
border-bottom: 2px solid var(--theia-activityBar-activeBorder);
|
||||
}
|
||||
|
||||
.sketchbook-trees-container .center {
|
||||
@@ -85,17 +96,23 @@
|
||||
|
||||
.cloud-sketchbook-welcome > .item .link {
|
||||
cursor: pointer;
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
color: var(--theia-textLink-foreground);
|
||||
}
|
||||
|
||||
.pull-sketch-icon {
|
||||
background: url("./pull-sketch-icon.svg") center center no-repeat;
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./pull-sketch-icon.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
width: var(--theia-icon-size);
|
||||
height: var(--theia-icon-size);
|
||||
}
|
||||
|
||||
.push-sketch-icon {
|
||||
background: url("./push-sketch-icon.svg") center center no-repeat;
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./push-sketch-icon.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
width: var(--theia-icon-size);
|
||||
height: var(--theia-icon-size);
|
||||
}
|
||||
@@ -181,4 +198,4 @@
|
||||
|
||||
.arduino-share-sketch-dialog .sketch-link-embed textarea {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,15 @@
|
||||
.p-Widget.dialogOverlay .dialogBlock {
|
||||
border-radius: 3px;
|
||||
padding: 0 28px;
|
||||
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.25);
|
||||
min-height: 0px;
|
||||
margin: 15px 20px;
|
||||
|
||||
/*
|
||||
padding (left + right) = 56px
|
||||
margin (left + right) = 40px
|
||||
total = padding + margin = 96px
|
||||
*/
|
||||
max-width: calc(100% - 96px) !important;
|
||||
padding: 0 28px;
|
||||
}
|
||||
|
||||
.p-Widget.dialogOverlay .dialogBlock .dialogTitle {
|
||||
@@ -10,7 +17,7 @@
|
||||
font-weight: 500;
|
||||
background-color: transparent;
|
||||
font-size: var(--theia-ui-font-size2);
|
||||
color: var(--theia-list-inactiveSelectionForeground);
|
||||
color: var(--theia-editorWidget-foreground);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
@@ -23,6 +30,10 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.p-Widget.dialogOverlay .dialogBlock .dialogContent > input {
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.p-Widget.dialogOverlay .dialogBlock .dialogContent > div {
|
||||
padding: 0 0 12px;
|
||||
}
|
||||
@@ -48,7 +59,8 @@
|
||||
}
|
||||
|
||||
.p-Widget.dialogOverlay .dialogBlock .dialogContent .dialogSection .dialogRow:first-child {
|
||||
margin-top: 0px;
|
||||
margin-top: 0px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.fl1{
|
||||
@@ -62,4 +74,4 @@
|
||||
|
||||
.fa.disabled {
|
||||
opacity: .4;
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
}
|
||||
|
||||
.monaco-list-row.show-file-icons.focused {
|
||||
background-color: #d6ebff;
|
||||
background-color: var(--theia-quickInputList-focusBackground);
|
||||
}
|
||||
|
||||
.monaco-editor .view-overlays .compiler-error {
|
||||
|
@@ -1,9 +1,14 @@
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('fonts/OpenSans-Bold-webfont.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
src:
|
||||
url('fonts/FontAwesome.ttf?nuchcq') format('truetype'),
|
||||
url('fonts/FontAwesome.woff?nuchcq') format('woff'),
|
||||
url('fonts/FontAwesome.svg?nuchcq#FontAwesome') format('svg');
|
||||
url('fonts/FontAwesome.ttf?2jhpmq') format('truetype'),
|
||||
url('fonts/FontAwesome.woff?2jhpmq') format('woff'),
|
||||
url('fonts/FontAwesome.svg?2jhpmq#FontAwesome') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
@@ -24,10 +29,39 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.fa-arduino-verify:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.fa-arduino-upload:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.fa-arduino-monitor:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.fa-arduino-sketch-tabs-menu:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.fa-arduino-plotter:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.fa-fa-check:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.fa-arduino-technology-3dimensionscube:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.fa-arduino-technology-usb:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.fa-arduino-technology-connection:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.fa-arduino-technology-bluetooth:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.fa-arduino-debugger:before {
|
||||
content: "\e905";
|
||||
}
|
||||
|
||||
.fa-arduino-search:before {
|
||||
content: "\e901";
|
||||
}
|
||||
@@ -88,9 +122,6 @@
|
||||
.fa-th-list:before {
|
||||
content: "\f00b";
|
||||
}
|
||||
.fa-check:before {
|
||||
content: "\f00c";
|
||||
}
|
||||
.fa-close:before {
|
||||
content: "\f00d";
|
||||
}
|
||||
@@ -130,9 +161,6 @@
|
||||
.fa-clock-o:before {
|
||||
content: "\f017";
|
||||
}
|
||||
.fa-road:before {
|
||||
content: "\f018";
|
||||
}
|
||||
.fa-download:before {
|
||||
content: "\f019";
|
||||
}
|
||||
@@ -163,9 +191,6 @@
|
||||
.fa-lock:before {
|
||||
content: "\f023";
|
||||
}
|
||||
.fa-flag:before {
|
||||
content: "\f024";
|
||||
}
|
||||
.fa-volume-off:before {
|
||||
content: "\f026";
|
||||
}
|
||||
@@ -187,9 +212,6 @@
|
||||
.fa-book:before {
|
||||
content: "\f02d";
|
||||
}
|
||||
.fa-bookmark:before {
|
||||
content: "\f02e";
|
||||
}
|
||||
.fa-print:before {
|
||||
content: "\f02f";
|
||||
}
|
||||
@@ -223,21 +245,12 @@
|
||||
.fa-indent:before {
|
||||
content: "\f03c";
|
||||
}
|
||||
.fa-video-camera:before {
|
||||
content: "\f03d";
|
||||
}
|
||||
.fa-pencil:before {
|
||||
content: "\f040";
|
||||
}
|
||||
.fa-map-marker:before {
|
||||
content: "\f041";
|
||||
}
|
||||
.fa-adjust:before {
|
||||
content: "\f042";
|
||||
}
|
||||
.fa-tint:before {
|
||||
content: "\f043";
|
||||
}
|
||||
.fa-edit:before {
|
||||
content: "\f044";
|
||||
}
|
||||
@@ -388,24 +401,12 @@
|
||||
.fa-arrows-h:before {
|
||||
content: "\f07e";
|
||||
}
|
||||
.fa-bar-chart:before {
|
||||
content: "\f080";
|
||||
}
|
||||
.fa-bar-chart-o:before {
|
||||
content: "\f080";
|
||||
}
|
||||
.fa-cogs:before {
|
||||
content: "\f085";
|
||||
}
|
||||
.fa-gears:before {
|
||||
content: "\f085";
|
||||
}
|
||||
.fa-thumbs-o-up:before {
|
||||
content: "\f087";
|
||||
}
|
||||
.fa-thumbs-o-down:before {
|
||||
content: "\f088";
|
||||
}
|
||||
.fa-star-half:before {
|
||||
content: "\f089";
|
||||
}
|
||||
@@ -454,9 +455,6 @@
|
||||
.fa-arrow-circle-down:before {
|
||||
content: "\f0ab";
|
||||
}
|
||||
.fa-globe:before {
|
||||
content: "\f0ac";
|
||||
}
|
||||
.fa-wrench:before {
|
||||
content: "\f0ad";
|
||||
}
|
||||
@@ -577,30 +575,9 @@
|
||||
.fa-angle-down:before {
|
||||
content: "\f107";
|
||||
}
|
||||
.fa-desktop:before {
|
||||
content: "\f108";
|
||||
}
|
||||
.fa-laptop:before {
|
||||
content: "\f109";
|
||||
}
|
||||
.fa-tablet:before {
|
||||
content: "\f10a";
|
||||
}
|
||||
.fa-mobile:before {
|
||||
content: "\f10b";
|
||||
}
|
||||
.fa-mobile-phone:before {
|
||||
content: "\f10b";
|
||||
}
|
||||
.fa-circle-o:before {
|
||||
content: "\f10c";
|
||||
}
|
||||
.fa-quote-left:before {
|
||||
content: "\f10d";
|
||||
}
|
||||
.fa-quote-right:before {
|
||||
content: "\f10e";
|
||||
}
|
||||
.fa-spinner:before {
|
||||
content: "\f110";
|
||||
}
|
||||
@@ -613,27 +590,15 @@
|
||||
.fa-reply:before {
|
||||
content: "\f112";
|
||||
}
|
||||
.fa-github-alt:before {
|
||||
content: "\f113";
|
||||
}
|
||||
.fa-folder-o:before {
|
||||
content: "\f114";
|
||||
}
|
||||
.fa-folder-open-o:before {
|
||||
content: "\f115";
|
||||
}
|
||||
.fa-gamepad:before {
|
||||
content: "\f11b";
|
||||
}
|
||||
.fa-keyboard-o:before {
|
||||
content: "\f11c";
|
||||
}
|
||||
.fa-flag-o:before {
|
||||
content: "\f11d";
|
||||
}
|
||||
.fa-flag-checkered:before {
|
||||
content: "\f11e";
|
||||
}
|
||||
.fa-terminal:before {
|
||||
content: "\f120";
|
||||
}
|
||||
|
@@ -8,11 +8,21 @@
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="reload" d="M512.083-9.079c118.817 0 232.769 47.2 316.781 131.213 84.019 84.019 131.219 197.969 131.219 316.785 0 8.487-3.373 16.627-9.376 22.628-5.997 6.001-14.138 9.373-22.624 9.373s-16.627-3.372-22.63-9.373c-5.997-6.001-9.37-14.141-9.37-22.627-0.019-87.81-30.131-172.959-85.318-241.26s-132.115-115.622-217.962-134.086c-85.848-18.458-175.428-6.931-253.811 32.646-78.383 39.584-140.833 104.832-176.941 184.87-36.108 80.045-43.693 170.045-21.49 255.001s72.852 159.737 143.505 211.878c70.653 52.141 157.042 78.492 244.768 74.662s171.487-37.612 237.33-95.712h-158.081c-8.487 0-16.626-3.372-22.627-9.373s-9.373-14.141-9.373-22.627c0-8.487 3.372-16.627 9.373-22.628s14.14-9.372 22.627-9.372h224.001c8.486 0 16.627 3.371 22.624 9.372 6.003 6.001 9.376 14.141 9.376 22.628v224c0 8.487-3.373 16.626-9.376 22.627-5.997 6.001-14.138 9.373-22.624 9.373s-16.627-3.371-22.63-9.373c-5.997-6.001-9.37-14.14-9.37-22.627v-136.96c-55.162 46.332-120.678 78.68-191.002 94.301s-143.375 14.052-212.963-4.571c-69.588-18.623-133.659-53.753-186.78-102.41s-93.725-109.405-118.369-177.096c-24.644-67.69-32.602-140.324-23.199-211.745 9.404-71.419 35.891-139.521 77.216-198.523 41.325-59.008 96.27-107.174 160.174-140.422s134.885-50.598 206.922-50.573v0z" />
|
||||
<glyph unicode="" glyph-name="arduino-search" d="M984.883 21.297l-272.696 272.696c63.208 77.401 94.257 176.128 86.728 275.773-7.533 99.645-53.065 192.585-127.19 259.604s-171.168 102.992-271.064 100.479c-99.897-2.512-195.009-43.317-265.67-113.978s-111.466-165.773-113.978-265.67c-2.512-99.898 33.46-196.942 100.479-271.062 67.019-74.124 159.959-119.661 259.604-127.19 99.643-7.533 198.375 23.516 275.771 86.724l272.696-272.696c3.624-3.651 7.929-6.549 12.68-8.526 4.746-1.977 9.835-2.996 14.982-2.996 5.142 0 10.231 1.020 14.982 2.996 4.746 1.977 9.056 4.875 12.675 8.526 3.651 3.624 6.549 7.934 8.526 12.68 1.981 4.746 2.996 9.839 2.996 14.982s-1.015 10.236-2.996 14.982c-1.977 4.746-4.875 9.056-8.526 12.675zM411.833 227.379c-61.639 0-121.894 18.276-173.145 52.522s-91.197 82.917-114.785 139.865c-23.588 56.948-29.76 119.61-17.735 180.065s41.707 115.986 85.293 159.571c43.585 43.585 99.117 73.268 159.571 85.293s123.12 5.854 180.063-17.735c56.948-23.588 105.623-63.533 139.865-114.784 34.246-51.251 52.527-111.506 52.527-173.145 0-82.655-32.835-161.926-91.283-220.374-58.448-58.444-137.715-91.278-220.371-91.278z" />
|
||||
<glyph unicode="" glyph-name="arduino-boards" horiz-adv-x="1178" d="M1107.2 931.657h-896c-11.881 0-23.277-4.72-31.678-13.122s-13.122-19.797-13.122-31.678v-268.8h-89.6c-11.881 0-23.277-4.72-31.678-13.122s-13.122-19.797-13.122-31.678v-268.8c0-11.884 4.72-23.276 13.122-31.677s19.797-13.123 31.678-13.123h89.6v-268.8c0-11.884 4.72-23.276 13.122-31.677s19.797-13.123 31.678-13.123h896c11.884 0 23.276 4.721 31.677 13.123s13.123 19.794 13.123 31.677v896c0 11.881-4.721 23.277-13.123 31.678s-19.794 13.122-31.677 13.122zM121.6 349.257v179.2h134.4v-179.2h-134.4zM1062.4 35.657h-89.6v44.8c0 11.884-4.721 23.276-13.123 31.677s-19.794 13.123-31.677 13.123c-11.884 0-23.276-4.721-31.677-13.123s-13.123-19.794-13.123-31.677v-44.8h-89.6v44.8c0 11.884-4.721 23.276-13.123 31.677s-19.794 13.123-31.677 13.123c-11.884 0-23.276-4.721-31.677-13.123s-13.123-19.794-13.123-31.677v-44.8h-89.6v44.8c0 11.884-4.721 23.276-13.123 31.677s-19.794 13.123-31.677 13.123c-11.884 0-23.276-4.721-31.677-13.123s-13.123-19.794-13.123-31.677v-44.8h-89.6v44.8c0 11.884-4.72 23.276-13.122 31.677s-19.797 13.123-31.678 13.123c-11.881 0-23.277-4.721-31.678-13.123s-13.122-19.794-13.122-31.677v-44.8h-89.6v224h44.8c11.881 0 23.277 4.721 31.678 13.123s13.122 19.794 13.122 31.677v268.8c0 11.881-4.72 23.277-13.122 31.678s-19.797 13.122-31.678 13.122h-44.8v224h89.6v-44.8c0-11.881 4.72-23.277 13.122-31.678s19.797-13.122 31.678-13.122c11.881 0 23.277 4.72 31.678 13.122s13.122 19.797 13.122 31.678v44.8h89.6v-44.8c0-11.881 4.721-23.277 13.123-31.678s19.794-13.122 31.677-13.122c11.884 0 23.276 4.72 31.677 13.122s13.123 19.797 13.123 31.678v44.8h89.6v-44.8c0-11.881 4.721-23.277 13.123-31.678s19.794-13.122 31.677-13.122c11.884 0 23.276 4.72 31.677 13.122s13.123 19.797 13.123 31.678v44.8h89.6v-44.8c0-11.881 4.721-23.277 13.123-31.678s19.794-13.122 31.677-13.122c11.884 0 23.276 4.72 31.677 13.122s13.123 19.797 13.123 31.678v44.8h89.6v-806.4zM928 618.057h-268.8c-11.884 0-23.276-4.72-31.677-13.122s-13.123-19.797-13.123-31.678v-268.8c0-11.884 4.721-23.276 13.123-31.677s19.794-13.123 31.677-13.123h268.8c11.884 0 23.276 4.721 31.677 13.123s13.123 19.794 13.123 31.677v268.8c0 11.881-4.721 23.277-13.123 31.678s-19.794 13.122-31.677 13.122zM883.2 349.257h-179.2v179.2h179.2v-179.2z" />
|
||||
<glyph unicode="" glyph-name="arduino-library" d="M1006.669 49.097l-164.271 625.707c-2.778 9.338-9.097 17.219-17.604 21.963-8.512 4.743-18.539 5.972-27.942 3.424l-135.518-33.973v220.64c0 9.901-3.934 19.397-10.935 26.399s-16.495 10.935-26.398 10.935h-149.333c-9.903 0-19.396-3.933-26.398-10.935s-10.935-16.497-10.935-26.399v-112h-149.333v74.667c0 9.901-3.933 19.397-10.935 26.399s-16.497 10.935-26.399 10.935h-186.667c-9.901 0-19.397-3.933-26.399-10.935s-10.935-16.497-10.935-26.399v-858.667c0-9.903 3.933-19.396 10.935-26.398s16.497-10.935 26.399-10.935h560c9.903 0 19.396 3.934 26.398 10.935s10.935 16.495 10.935 26.398v435.682l114.987-437.922c2.116-8.213 6.967-15.462 13.751-20.553 6.788-5.090 15.104-7.714 23.582-7.445 3.226-0.363 6.481-0.363 9.707 0l157.918 41.438c9.566 2.483 17.758 8.661 22.775 17.173 2.475 4.527 3.985 9.519 4.437 14.66 0.448 5.141-0.171 10.317-1.822 15.206zM213.333 28.19h-112v784h112v-784zM437.333 28.19h-149.333v672h149.333v-672zM586.667 28.19h-74.667v821.333h74.667v-821.333zM839.040 43.87l-145.225 553.28 85.867 22.773 145.225-554.4-85.867-21.653z" />
|
||||
<glyph unicode="" glyph-name="arduino-folder" horiz-adv-x="1252" d="M1173.333 737.523h-527.15l-184.175 184.675c-4.651 4.614-10.167 8.263-16.232 10.741s-12.559 3.733-19.11 3.695h-348.444c-13.202 0-25.863-5.244-35.198-14.58s-14.58-21.996-14.58-35.198v-895.999c0-13.204 5.244-25.862 14.58-35.197s21.997-14.581 35.198-14.581h1095.111c13.204 0 25.862 5.245 35.197 14.581s14.581 21.993 14.581 35.197v696.888c0 13.202-5.245 25.863-14.581 35.198s-21.993 14.58-35.197 14.58zM128 837.079h278.258l99.556-99.556h-377.813v99.556zM1123.556 40.635h-995.556v597.333h995.556v-597.333z" />
|
||||
<glyph unicode="" glyph-name="arduino-debugger" horiz-adv-x="1071" d="M634.224 287.761c-8.983-0.009-17.72 2.956-24.841 8.425-7.126 5.474-12.241 13.149-14.55 21.83s-1.685 17.883 1.778 26.168c3.463 8.29 9.57 15.202 17.366 19.661l304.621 173.966-488.052 278.888v-296.387c0-10.801-4.291-21.16-11.929-28.799s-17.997-11.929-28.799-11.929c-10.801 0-21.16 4.291-28.799 11.929s-11.929 17.997-11.929 28.799v366.545c-0.004 7.135 1.867 14.146 5.426 20.33s8.681 11.324 14.852 14.905c6.171 3.581 13.175 5.477 20.31 5.499s14.15-1.832 20.343-5.376l610.91-349.045c6.232-3.561 11.413-8.707 15.020-14.917 3.603-6.209 5.502-13.261 5.502-20.441s-1.899-14.232-5.502-20.441c-3.607-6.21-8.788-11.356-15.020-14.917l-366.545-209.326c-6.135-3.523-13.089-5.376-20.163-5.367zM512 153.766c10.803 0 21.16 4.291 28.798 11.93s11.93 17.994 11.93 28.798c0 10.803-4.291 21.16-11.93 28.798s-17.994 11.93-28.798 11.93h-43.176c-1.987 17.389-5.532 34.56-10.587 51.316l41.949 41.951c3.798 3.793 6.81 8.304 8.867 13.265 2.053 4.962 3.109 10.277 3.109 15.649s-1.057 10.687-3.109 15.649c-2.057 4.962-5.069 9.467-8.867 13.265s-8.304 6.81-13.265 8.867c-4.962 2.053-10.277 3.114-15.649 3.114s-10.688-1.061-15.65-3.114c-4.961-2.057-9.47-5.069-13.267-8.867l-21.585-21.583c-14.553 22.109-34.216 40.387-57.327 53.285-23.11 12.902-48.988 20.052-75.444 20.838-26.456-0.787-52.334-7.936-75.444-20.838s-42.774-31.181-57.327-53.29l-21.585 21.588c-7.669 7.671-18.070 11.976-28.915 11.976s-21.247-4.305-28.916-11.976c-7.669-7.666-11.978-18.069-11.978-28.914s4.308-21.248 11.977-28.914l41.949-41.951c-5.055-16.756-8.599-33.927-10.589-51.316h-43.171c-10.801 0-21.161-4.291-28.799-11.93s-11.929-17.994-11.929-28.798c0-10.803 4.291-21.16 11.929-28.798s17.997-11.93 28.799-11.93h43.173c1.991-17.389 5.534-34.56 10.589-51.316l-1.222-1.224-40.727-40.727c-7.631-7.685-11.913-18.078-11.913-28.914 0-10.831 4.282-21.225 11.913-28.914 7.72-7.568 18.102-11.813 28.915-11.813s21.194 4.245 28.915 11.813l21.585 21.588c14.553-22.109 34.216-40.387 57.327-53.29s48.989-20.052 75.445-20.838c26.456 0.787 52.334 7.936 75.444 20.838s42.774 31.181 57.327 53.29l21.585-21.588c7.72-7.573 18.102-11.813 28.916-11.813 10.813 0 21.192 4.24 28.914 11.813 7.629 7.689 11.911 18.083 11.911 28.914 0 10.836-4.282 21.229-11.911 28.914l-41.95 41.951c5.055 16.756 8.6 33.927 10.588 51.316h43.176zM288 357.402c37.058 0 69.644-32.991 87.564-81.455h-175.127c17.92 48.463 50.506 81.455 87.564 81.455zM288 31.584c-55.389 0-101.818 74.533-101.818 162.909h203.636c0-88.376-46.429-162.909-101.818-162.909z" />
|
||||
<glyph unicode="" glyph-name="arduino-search" d="M1011.905-2.98l-286.249 286.249c66.349 81.248 98.942 184.882 91.034 289.478-7.903 104.597-55.702 202.157-133.511 272.506-77.804 70.35-179.671 108.111-284.533 105.473s-204.701-45.47-278.874-119.643c-74.172-74.172-117.006-174.012-119.643-278.874s35.123-206.729 105.473-284.537c70.35-77.804 167.91-125.604 272.506-133.506 104.597-7.907 208.231 24.685 289.479 91.034l286.249-286.249c3.8-3.832 8.323-6.874 13.305-8.95s10.328-3.145 15.727-3.145c5.398 0 10.745 1.071 15.727 3.145 4.986 2.075 9.506 5.117 13.31 8.95 3.832 3.804 6.874 8.323 8.95 13.31 2.075 4.982 3.145 10.328 3.145 15.727s-1.071 10.739-3.145 15.727c-2.075 4.982-5.117 9.506-8.95 13.305v0zM410.372 213.345c-64.702 0-127.952 19.184-181.75 55.132-53.798 35.944-95.728 87.038-120.49 146.816s-31.239 125.554-18.616 189.013c12.623 63.459 43.78 121.751 89.532 167.502s104.043 76.909 167.502 89.532c63.459 12.623 129.235 6.145 189.013-18.616s110.868-66.691 146.816-120.489c35.948-53.798 55.132-117.048 55.132-181.75 0-86.766-34.467-169.972-95.815-231.325-61.353-61.349-144.564-95.815-231.326-95.815v0z" />
|
||||
<glyph unicode="" glyph-name="arduino-boards" horiz-adv-x="1215" d="M997.684 221.968c0-11.506-4.572-22.538-12.707-30.67s-19.165-12.707-30.67-12.707h-433.777c-11.506 0-22.538 4.572-30.673 12.707s-12.705 19.165-12.705 30.67 4.571 22.538 12.705 30.67c8.136 8.134 19.166 12.707 30.673 12.707h433.777c11.506 0 22.538-4.572 30.67-12.707s12.707-19.165 12.707-30.67zM1201.991 599.789l-74.173 73.742v199.104c0 11.503-4.572 22.539-12.707 30.673s-19.165 12.705-30.67 12.705h-910.933c-11.503 0-22.539-4.571-30.673-12.705s-12.705-19.168-12.705-30.673v-130.133h-86.756c-11.504 0-22.539-4.571-30.673-12.705s-12.705-19.168-12.705-30.673v-216.89c0-11.503 4.571-22.539 12.705-30.673s19.168-12.705 30.673-12.705h86.756v-433.777c0-11.506 4.571-22.538 12.705-30.67s19.168-12.707 30.673-12.707h910.933c5.71-0.034 11.368 1.062 16.653 3.216 5.285 2.161 10.092 5.342 14.143 9.365l86.756 86.756c4.020 4.052 7.203 8.859 9.365 14.143 2.157 5.285 3.253 10.94 3.216 16.653v477.156c0.034 5.708-1.062 11.369-3.216 16.654-2.161 5.285-5.342 10.092-9.365 14.145zM86.751 525.614v130.133h216.89v-130.133h-216.89zM1127.818 109.617l-61.159-61.159h-849.774v390.4h130.133c11.503 0 22.539 4.571 30.673 12.705s12.705 19.168 12.705 30.673v216.89c0 11.503-4.571 22.539-12.705 30.673s-19.168 12.705-30.673 12.705h-130.133v86.756h824.177v-173.51c-0.034-5.708 1.062-11.369 3.216-16.654 2.161-5.285 5.342-10.092 9.365-14.145l74.173-73.742v-441.589z" />
|
||||
<glyph unicode="" glyph-name="arduino-library" d="M1021.954 32.412l-171.299 652.491c-2.901 9.738-9.491 17.956-18.363 22.903-8.876 4.946-19.333 6.228-29.138 3.571l-141.319-35.427v230.085c0 10.325-4.102 20.227-11.403 27.529s-17.201 11.403-27.528 11.403h-155.725c-10.327 0-20.226-4.101-27.529-11.403-7.301-7.302-11.403-17.203-11.403-27.529v-116.794h-155.725v77.863c0 10.325-4.101 20.227-11.403 27.529s-17.203 11.403-27.529 11.403h-194.658c-10.325 0-20.227-4.101-27.529-11.403s-11.403-17.203-11.403-27.529v-895.424c0-10.327 4.101-20.226 11.403-27.528s17.203-11.403 27.529-11.403h583.972c10.327 0 20.226 4.102 27.528 11.403s11.403 17.201 11.403 27.528v454.332l119.909-456.668c2.207-8.565 7.265-16.124 14.34-21.433 7.079-5.308 15.751-8.044 24.591-7.764 3.364-0.379 6.758-0.379 10.123 0l164.678 43.212c9.975 2.589 18.518 9.032 23.75 17.908 2.581 4.721 4.156 9.926 4.627 15.288 0.467 5.361-0.178 10.759-1.9 15.857v0zM194.659 10.61h-116.794v817.56h116.794v-817.56zM428.248 10.61h-155.725v700.766h155.725v-700.766zM583.973 10.61h-77.863v856.491h77.863v-856.491zM847.15 26.961l-151.442 576.964 89.543 23.748 151.442-578.132-89.543-22.58z" />
|
||||
<glyph unicode="" glyph-name="arduino-folder" horiz-adv-x="1252" d="M1189.198 746.056h-542.21l-189.437 189.951c-4.784 4.746-10.457 8.499-16.696 11.048s-12.918 3.84-19.656 3.801h-358.398c-13.579 0-26.602-5.394-36.204-14.997s-14.997-22.624-14.997-36.204v-921.597c0-13.581 5.394-26.601 14.997-36.203s22.624-14.998 36.204-14.998h1126.397c13.581 0 26.601 5.395 36.203 14.998s14.998 22.621 14.998 36.203v716.798c0 13.579-5.395 26.602-14.998 36.204s-22.621 14.997-36.203 14.997zM114.001 848.457h286.208l102.4-102.4h-388.606v102.4zM1137.998 29.259h-1023.998v614.398h1023.998v-614.398z" />
|
||||
<glyph unicode="" glyph-name="arduino-debugger" d="M613.86 287.753c-8.983-0.005-17.72 2.956-24.841 8.429-7.126 5.474-12.241 13.144-14.55 21.825s-1.685 17.883 1.778 26.173c3.463 8.29 9.57 15.202 17.366 19.661l304.621 173.965-488.052 278.887v-296.386c0-10.801-4.291-21.16-11.929-28.799-7.638-7.636-17.997-11.927-28.799-11.927s-21.16 4.291-28.799 11.927c-7.638 7.638-11.929 17.997-11.929 28.799v366.545c-0.004 7.135 1.867 14.146 5.426 20.33s8.681 11.324 14.852 14.905c6.171 3.581 13.175 5.477 20.31 5.499s14.15-1.832 20.343-5.376l610.91-349.045c6.232-3.561 11.413-8.707 15.020-14.917 3.603-6.21 5.502-13.261 5.502-20.441s-1.899-14.232-5.502-20.441c-3.607-6.21-8.788-11.356-15.020-14.917l-366.545-209.324c-6.135-3.528-13.089-5.381-20.163-5.371zM491.636 153.763c10.803 0 21.16 4.291 28.798 11.93s11.93 17.994 11.93 28.798c0 10.803-4.291 21.16-11.93 28.798s-17.994 11.93-28.798 11.93h-43.173c-1.991 17.389-5.534 34.56-10.589 51.316l41.949 41.951c3.798 3.793 6.81 8.304 8.867 13.265 2.053 4.962 3.109 10.277 3.109 15.649s-1.057 10.687-3.109 15.649c-2.057 4.962-5.069 9.467-8.867 13.265s-8.304 6.81-13.265 8.867c-4.961 2.053-10.279 3.114-15.649 3.114s-10.688-1.061-15.649-3.114c-4.961-2.057-9.47-5.069-13.267-8.867l-21.585-21.583c-14.553 22.109-34.216 40.387-57.327 53.285-23.11 12.902-48.988 20.052-75.444 20.838-26.456-0.787-52.334-7.936-75.444-20.838s-42.774-31.181-57.327-53.29l-21.585 21.588c-7.669 7.671-18.070 11.976-28.915 11.976s-21.247-4.305-28.916-11.976c-7.669-7.666-11.978-18.069-11.978-28.914s4.308-21.248 11.977-28.914l41.949-41.951c-5.055-16.756-8.599-33.927-10.589-51.316h-43.171c-10.802 0-21.161-4.291-28.799-11.93s-11.929-17.994-11.929-28.798c0-10.803 4.291-21.16 11.929-28.798s17.997-11.93 28.799-11.93h43.173c1.991-17.389 5.534-34.56 10.589-51.316l-1.222-1.224-40.727-40.727c-7.631-7.685-11.913-18.078-11.913-28.914 0-10.831 4.282-21.225 11.913-28.914 7.72-7.568 18.102-11.813 28.915-11.813s21.194 4.245 28.915 11.813l21.585 21.588c14.553-22.109 34.216-40.387 57.327-53.29s48.989-20.052 75.445-20.838c26.456 0.787 52.334 7.936 75.444 20.838s42.774 31.181 57.327 53.29l21.585-21.588c7.72-7.573 18.102-11.813 28.915-11.813s21.194 4.24 28.916 11.813c7.629 7.689 11.911 18.083 11.911 28.914 0 10.836-4.282 21.229-11.911 28.914l-41.95 41.951c5.055 16.756 8.599 33.927 10.589 51.316h43.174zM267.636 357.399c37.058 0 69.644-32.991 87.564-81.455h-175.127c17.92 48.463 50.506 81.455 87.564 81.455zM267.636 31.581c-55.389 0-101.818 74.533-101.818 162.909h203.636c0-88.376-46.429-162.909-101.818-162.909z" />
|
||||
<glyph unicode="" glyph-name="arduino-technology-3dimensionscube" d="M864 822.857h-576c-8.484-0.062-16.618-3.385-22.72-9.28l-128-128c-5.969-6.052-9.305-14.219-9.28-22.72v-576c0.024-8.48 3.404-16.602 9.4-22.598s14.121-9.376 22.6-9.402h576c8.486 0.038 16.634 3.36 22.72 9.28l128 128c5.894 6.099 9.216 14.234 9.28 22.72v576c-0.026 8.479-3.405 16.605-9.402 22.6s-14.118 9.375-22.598 9.4zM704 118.857h-512v512h512v-512zM722.56 694.857h-485.12l63.68 64h485.44l-64-64zM832 227.977l-64-63.68v485.12l64 64v-485.44z" />
|
||||
<glyph unicode="" glyph-name="arduino-technology-usb" d="M848 726.857v-96c0-8.487-3.373-16.627-9.37-22.627-6.003-6.001-14.144-9.373-22.63-9.373h-16v-96c-0.019-5.909-1.67-11.699-4.781-16.725-3.104-5.027-7.539-9.096-12.819-11.755l-238.4-119.36v-242.88c16.845-7.354 30.644-20.282 39.079-36.608 8.435-16.333 10.989-35.066 7.233-53.056s-13.59-34.144-27.852-45.734c-14.262-11.597-32.081-17.92-50.46-17.92s-36.198 6.323-50.46 17.92c-14.262 11.59-24.097 27.744-27.852 45.734s-1.201 36.723 7.233 53.056c8.435 16.326 22.234 29.254 39.079 36.608v82.88l-238.4 119.36c-5.277 2.659-9.715 6.728-12.822 11.755s-4.76 10.816-4.778 16.725v102.72c-16.845 7.352-30.644 20.279-39.079 36.609s-10.988 35.066-7.233 53.057c3.755 17.992 13.59 34.141 27.852 45.734s32.081 17.921 50.46 17.921c18.38 0 36.198-6.328 50.46-17.921s24.097-27.743 27.852-45.734c3.756-17.992 1.201-36.727-7.233-53.057s-22.234-29.257-39.079-36.609v-82.88l192-96v524.16h-32c-6.372-0.032-12.609 1.839-17.91 5.374s-9.428 8.572-11.85 14.466c-2.41 5.858-3.028 12.3-1.775 18.509s4.321 11.907 8.815 16.371l64 64c2.975 2.999 6.514 5.38 10.413 7.005s8.083 2.461 12.307 2.461c4.225 0 8.407-0.836 12.307-2.461s7.439-4.005 10.413-7.005l64-64c4.44-4.5 7.448-10.214 8.644-16.422s0.526-12.63-1.924-18.458c-2.401-5.844-6.477-10.846-11.716-14.377s-11.406-5.432-17.724-5.463h-32v-364.16l192 96v76.16h-16c-8.486 0-16.627 3.372-22.63 9.373-5.997 6.001-9.37 14.14-9.37 22.627v96c0 8.487 3.373 16.627 9.37 22.627 6.003 6.001 14.144 9.373 22.63 9.373h96c8.486 0 16.627-3.372 22.63-9.373 5.997-6.001 9.37-14.14 9.37-22.627z" />
|
||||
<glyph unicode="" glyph-name="arduino-technology-connection" d="M512 118.857c35.346 0 64 28.653 64 64s-28.654 64-64 64c-35.346 0-64-28.653-64-64s28.654-64 64-64zM647.699 286.537c-8.442 0.122-16.493 3.571-22.401 9.6-14.863 14.9-32.519 26.721-51.957 34.787s-40.277 12.218-61.323 12.218c-21.046 0-41.884-4.152-61.323-12.218s-37.094-19.887-51.957-34.787c-5.996-5.958-14.106-9.306-22.56-9.306s-16.564 3.347-22.56 9.306c-5.96 5.997-9.306 14.106-9.306 22.559s3.345 16.564 9.306 22.56c20.801 20.803 45.495 37.304 72.673 48.563s56.308 17.053 85.727 17.053c29.418 0 58.548-5.795 85.726-17.053s51.875-27.761 72.675-48.563c4.512-4.476 7.59-10.194 8.838-16.426 1.254-6.232 0.614-12.695-1.818-18.562-2.438-5.875-6.573-10.886-11.866-14.4-5.299-3.514-11.52-5.37-17.875-5.331zM919.373 558.218c-4.269-0.195-8.538 0.47-12.55 1.954s-7.686 3.757-10.81 6.686c-101.965 101.613-240.045 158.669-383.997 158.669-143.951 0-282.035-57.056-384-158.669-6.026-5.983-14.181-9.328-22.673-9.298s-16.623 3.432-22.607 9.458c-5.983 6.026-9.327 14.181-9.298 22.673s3.432 16.623 9.458 22.607c114.009 113.924 268.588 177.918 429.76 177.918 161.175 0 315.754-63.994 429.757-177.918 3.002-2.975 5.382-6.514 7.008-10.413s2.458-8.083 2.458-12.307c0-4.225-0.832-8.407-2.458-12.307s-4.006-7.439-7.008-10.413c-3.078-2.89-6.701-5.14-10.656-6.623-3.949-1.483-8.16-2.168-12.384-2.017zM783.706 422.541c-4.211-0.024-8.384 0.783-12.288 2.375-3.898 1.592-7.443 3.939-10.432 6.905-32.691 32.703-71.501 58.646-114.221 76.346-42.715 17.7-88.501 26.81-134.74 26.81s-92.025-9.11-134.742-26.81c-42.717-17.7-81.529-43.643-114.218-76.346-6.122-5.242-13.996-7.982-22.049-7.671s-15.693 3.65-21.393 9.349c-5.699 5.699-9.037 13.338-9.348 21.392s2.428 15.928 7.67 22.050c78.009 77.968 183.788 121.767 294.080 121.767s216.072-43.799 294.081-121.767c5.958-5.996 9.306-14.106 9.306-22.56s-3.347-16.564-9.306-22.56c-5.958-5.912-14.003-9.245-22.4-9.28z" />
|
||||
<glyph unicode="" glyph-name="arduino-technology-bluetooth" d="M512.006-41.137c-4.198-0.109-8.362 0.768-12.16 2.56-5.844 2.4-10.846 6.477-14.377 11.712-3.53 5.242-5.431 11.405-5.463 17.728v370.877l-169.28-169.597c-2.984-2.989-6.525-5.35-10.424-6.97-3.898-1.613-8.077-2.445-12.296-2.445s-8.397 0.832-12.296 2.445c-3.898 1.619-7.441 3.981-10.424 6.97-2.984 2.982-5.35 6.522-6.965 10.419s-2.445 8.077-2.445 12.301c0 4.218 0.831 8.397 2.445 12.294s3.981 7.437 6.965 10.426l201.6 201.277-201.6 201.28c-6.026 6.026-9.411 14.198-9.411 22.72s3.385 16.694 9.411 22.72c6.026 6.026 14.198 9.411 22.72 9.411s16.694-3.386 22.72-9.411l169.28-169.6v370.88c0.032 6.318 1.933 12.485 5.463 17.724s8.533 9.316 14.377 11.716c5.828 2.451 12.25 3.12 18.458 1.924s11.922-4.204 16.422-8.644l224.001-224c3.002-2.975 5.382-6.514 7.002-10.413 1.626-3.9 2.464-8.082 2.464-12.307s-0.838-8.407-2.464-12.307c-1.619-3.9-4-7.439-7.002-10.413l-201.601-201.28 201.601-201.277c3.002-2.976 5.382-6.515 7.002-10.419 1.626-3.898 2.464-8.077 2.464-12.301 0-4.23-0.838-8.41-2.464-12.307-1.619-3.904-4-7.443-7.002-10.413l-224.001-224c-2.99-2.97-6.536-5.318-10.435-6.906-3.899-1.594-8.074-2.4-12.285-2.374zM544.006 361.74v-293.757l146.881 146.88-146.881 146.877zM544.006 809.74v-293.76l146.881 146.88-146.881 146.88z" />
|
||||
<glyph unicode="" glyph-name="fa-check" d="M416.006 150.857c-4.211-0.026-8.386 0.787-12.285 2.374-3.899 1.594-7.445 3.942-10.435 6.906l-224 224.002c-6.026 6.026-9.411 14.198-9.411 22.72s3.385 16.694 9.411 22.72c6.026 6.026 14.198 9.411 22.72 9.411s16.694-3.386 22.72-9.411l201.28-201.602 425.281 425.602c6.022 6.026 14.195 9.411 22.72 9.411 8.518 0 16.691-3.386 22.72-9.411 6.022-6.026 9.408-14.198 9.408-22.72s-3.386-16.694-9.408-22.72l-448.001-448.002c-2.99-2.963-6.536-5.312-10.435-6.906-3.899-1.587-8.074-2.4-12.285-2.374z" />
|
||||
<glyph unicode="" glyph-name="arduino-verify" horiz-adv-x="1489" d="M558.545-73.143c-23.818 0-47.637 9.095-65.819 27.276l-465.454 465.453c-36.363 36.363-36.363 95.273 0 131.636s95.273 36.363 131.637 0l399.636-399.636 772.003 772c36.361 36.363 95.269 36.363 131.631 0s36.361-95.273 0-131.637l-837.815-837.815c-18.182-18.181-42-27.276-65.818-27.276z" />
|
||||
<glyph unicode="" glyph-name="arduino-upload" horiz-adv-x="1161" d="M1072.469 424.348l-409.603-409.598c-13.65-12.971-30.717-19.804-48.467-19.804s-34.817 6.833-48.467 19.804c-26.625 26.617-26.625 70.315 0 96.932l293.551 292.866h-791.217c-37.55 0-68.267 30.717-68.267 68.267s30.717 68.267 68.267 68.267h791.217l-293.551 292.866c-26.625 26.616-26.625 70.317 0 96.934 26.616 26.634 70.317 26.634 96.933 0l409.603-409.6c26.624-26.616 26.624-70.317 0-96.934v0z" />
|
||||
<glyph unicode="" glyph-name="arduino-monitor" horiz-adv-x="1536" d="M651.891 59.977c-92.835 0-179.095 28.493-250.5 77.197l-129.659-129.658c-22.494-22.496-58.964-22.496-81.458 0s-22.494 58.963 0 81.459l124.954 124.954c-67.75 78.157-108.777 180.090-108.777 291.489 0 245.759 199.68 445.439 445.44 445.439s445.44-199.679 445.44-445.439c0-245.761-199.68-445.441-445.44-445.441zM651.891 797.257c-161.28 0-291.84-130.559-291.84-291.839s130.56-291.841 291.84-291.841c160.512 0 291.84 130.561 291.84 291.841 0 160.511-130.56 291.839-291.84 291.839zM1149.562 472.766c0-35.423 28.717-64.138 64.141-64.138s64.134 28.716 64.134 64.138c0 35.423-28.71 64.139-64.134 64.139s-64.141-28.716-64.141-64.139zM64.064 408.62c-35.382 0-64.064 28.682-64.064 64.063s28.682 64.064 64.064 64.064c35.381 0 64.064-28.682 64.064-64.064s-28.683-64.063-64.064-64.063zM1458.707 408.628c-35.418 0-64.134 28.716-64.134 64.138s28.717 64.139 64.134 64.139c35.424 0 64.141-28.716 64.141-64.139s-28.717-64.138-64.141-64.138zM652.659 424.010c-44.961 0-81.408 36.447-81.408 81.407s36.447 81.408 81.408 81.408c44.96 0 81.408-36.447 81.408-81.408s-36.448-81.407-81.408-81.407z" />
|
||||
<glyph unicode="" glyph-name="arduino-sketch-tabs-menu" d="M511.998 347.425c50.495 0 91.432 40.936 91.432 91.432s-40.936 91.432-91.432 91.432c-50.495 0-91.432-40.936-91.432-91.432s40.936-91.432 91.432-91.432zM923.433 347.425c50.494 0 91.432 40.936 91.432 91.432s-40.937 91.432-91.432 91.432c-50.494 0-91.432-40.936-91.432-91.432s40.937-91.432 91.432-91.432zM100.565 347.425c50.495 0 91.432 40.936 91.432 91.432s-40.936 91.432-91.432 91.432c-50.495 0-91.432-40.936-91.432-91.432s40.936-91.432 91.432-91.432z" />
|
||||
<glyph unicode="" glyph-name="arduino-plotter" horiz-adv-x="862" d="M323.368-19.351c-20.263 0-39 11.42-48.21 29.788l-146.789 293.581h-74.474c-29.789 0-53.895 24.107-53.895 53.895s24.105 53.895 53.895 53.895h107.789c20.421 0 39.053-11.528 48.21-29.788l96.527-193.056 180.263 720.949c5.842 23.579 26.737 40.263 51 40.842 23.947 1.579 45.893-15.158 52.894-38.421l150.162-500.526h67.681c29.788 0 53.895-24.107 53.895-53.895s-24.107-53.895-53.895-53.895h-107.789c-23.789 0-44.787 15.629-51.631 38.422l-105.316 351.104-168.052-672.053c-5.474-21.897-23.948-38.055-46.368-40.529-2-0.21-3.947-0.313-5.895-0.313h-0.001z" />
|
||||
<glyph unicode="" glyph-name="music" horiz-adv-x="878" d="M877.714 822.857v-640c0-80.571-120.571-109.714-182.857-109.714s-182.857 29.143-182.857 109.714 120.571 109.714 182.857 109.714c37.714 0 75.429-6.857 109.714-22.286v306.857l-438.857-135.429v-405.143c0-80.571-120.571-109.714-182.857-109.714s-182.857 29.143-182.857 109.714 120.571 109.714 182.857 109.714c37.714 0 75.429-6.857 109.714-22.286v552.571c0 24 16 45.143 38.857 52.571l475.429 146.286c5.143 1.714 10.286 2.286 16 2.286 30.286 0 54.857-24.571 54.857-54.857z" />
|
||||
<glyph unicode="" glyph-name="search" horiz-adv-x="951" d="M658.286 475.428c0 141.143-114.857 256-256 256s-256-114.857-256-256 114.857-256 256-256 256 114.857 256 256zM950.857 0c0-40-33.143-73.143-73.143-73.143-19.429 0-38.286 8-51.429 21.714l-196 195.429c-66.857-46.286-146.857-70.857-228-70.857-222.286 0-402.286 180-402.286 402.286s180 402.286 402.286 402.286 402.286-180 402.286-402.286c0-81.143-24.571-161.143-70.857-228l196-196c13.143-13.143 21.143-32 21.143-51.429z" />
|
||||
<glyph unicode="" glyph-name="envelope-o" d="M950.857 91.428v438.857c-12-13.714-25.143-26.286-39.429-37.714-81.714-62.857-164-126.857-243.429-193.143-42.857-36-96-80-155.429-80h-1.143c-59.429 0-112.571 44-155.429 80-79.429 66.286-161.714 130.286-243.429 193.143-14.286 11.429-27.429 24-39.429 37.714v-438.857c0-9.714 8.571-18.286 18.286-18.286h841.143c9.714 0 18.286 8.571 18.286 18.286zM950.857 692c0 14.286 3.429 39.429-18.286 39.429h-841.143c-9.714 0-18.286-8.571-18.286-18.286 0-65.143 32.571-121.714 84-162.286 76.571-60 153.143-120.571 229.143-181.143 30.286-24.571 85.143-77.143 125.143-77.143h1.143c40 0 94.857 52.571 125.143 77.143 76 60.571 152.571 121.143 229.143 181.143 37.143 29.143 84 92.571 84 141.143zM1024 713.143v-621.714c0-50.286-41.143-91.429-91.429-91.429h-841.143c-50.286 0-91.429 41.143-91.429 91.429v621.714c0 50.286 41.143 91.429 91.429 91.429h841.143c50.286 0 91.429-41.143 91.429-91.429z" />
|
||||
@@ -24,7 +34,6 @@
|
||||
<glyph unicode="" glyph-name="th-large" horiz-adv-x="951" d="M438.857 365.714v-219.429c0-40-33.143-73.143-73.143-73.143h-292.571c-40 0-73.143 33.143-73.143 73.143v219.429c0 40 33.143 73.143 73.143 73.143h292.571c40 0 73.143-33.143 73.143-73.143zM438.857 804.571v-219.429c0-40-33.143-73.143-73.143-73.143h-292.571c-40 0-73.143 33.143-73.143 73.143v219.429c0 40 33.143 73.143 73.143 73.143h292.571c40 0 73.143-33.143 73.143-73.143zM950.857 365.714v-219.429c0-40-33.143-73.143-73.143-73.143h-292.571c-40 0-73.143 33.143-73.143 73.143v219.429c0 40 33.143 73.143 73.143 73.143h292.571c40 0 73.143-33.143 73.143-73.143zM950.857 804.571v-219.429c0-40-33.143-73.143-73.143-73.143h-292.571c-40 0-73.143 33.143-73.143 73.143v219.429c0 40 33.143 73.143 73.143 73.143h292.571c40 0 73.143-33.143 73.143-73.143z" />
|
||||
<glyph unicode="" glyph-name="th" d="M292.571 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM658.286 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857z" />
|
||||
<glyph unicode="" glyph-name="th-list" d="M292.571 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM292.571 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 237.714v-109.714c0-30.286-24.571-54.857-54.857-54.857h-548.571c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h548.571c30.286 0 54.857-24.571 54.857-54.857zM292.571 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-182.857c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h182.857c30.286 0 54.857-24.571 54.857-54.857zM1024 530.286v-109.714c0-30.286-24.571-54.857-54.857-54.857h-548.571c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h548.571c30.286 0 54.857-24.571 54.857-54.857zM1024 822.857v-109.714c0-30.286-24.571-54.857-54.857-54.857h-548.571c-30.286 0-54.857 24.571-54.857 54.857v109.714c0 30.286 24.571 54.857 54.857 54.857h548.571c30.286 0 54.857-24.571 54.857-54.857z" />
|
||||
<glyph unicode="" glyph-name="check" d="M954.857 627.428c0-14.286-5.714-28.571-16-38.857l-491.429-491.429c-10.286-10.286-24.571-16-38.857-16s-28.571 5.714-38.857 16l-284.571 284.571c-10.286 10.286-16 24.571-16 38.857s5.714 28.571 16 38.857l77.714 77.714c10.286 10.286 24.571 16 38.857 16s28.571-5.714 38.857-16l168-168.571 374.857 375.429c10.286 10.286 24.571 16 38.857 16s28.571-5.714 38.857-16l77.714-77.714c10.286-10.286 16-24.571 16-38.857z" />
|
||||
<glyph unicode="" glyph-name="close, remove, times" horiz-adv-x="805" d="M725.322 168.514c3.477-3.448 6.237-7.547 8.118-12.069 1.885-4.515 2.853-9.364 2.853-14.259s-0.967-9.744-2.853-14.266c-1.881-4.515-4.641-8.623-8.118-12.069-3.448-3.472-7.547-6.232-12.069-8.118-4.515-1.881-9.364-2.848-14.259-2.848s-9.744 0.967-14.266 2.848c-4.522 1.885-8.623 4.646-12.069 8.118l-270.371 270.375-270.372-270.375c-3.448-3.472-7.549-6.232-12.069-8.118-4.519-1.881-9.366-2.848-14.263-2.848s-9.744 0.967-14.263 2.848c-4.519 1.885-8.622 4.646-12.069 8.118-3.474 3.448-6.235 7.555-8.118 12.069-1.884 4.522-2.853 9.37-2.853 14.266s0.97 9.744 2.853 14.259c1.884 4.522 4.643 8.623 8.118 12.069l270.372 270.375-270.372 270.372c-3.456 3.456-6.201 7.565-8.072 12.082s-2.835 9.36-2.835 14.25c0 4.891 0.964 9.732 2.835 14.25s4.617 8.626 8.072 12.081c3.456 3.456 7.564 6.201 12.081 8.072s9.361 2.835 14.25 2.835c4.891 0 9.732-0.964 14.25-2.835s8.626-4.617 12.081-8.072l270.372-270.372 270.371 270.372c6.984 6.983 16.455 10.909 26.335 10.909 9.875 0 19.347-3.923 26.33-10.909s10.909-16.456 10.909-26.333c0-9.877-3.923-19.348-10.909-26.333l-270.371-270.372 270.371-270.375z" />
|
||||
<glyph unicode="" glyph-name="search-plus" horiz-adv-x="951" d="M585.143 493.714v-36.571c0-9.714-8.571-18.286-18.286-18.286h-128v-128c0-9.714-8.571-18.286-18.286-18.286h-36.571c-9.714 0-18.286 8.571-18.286 18.286v128h-128c-9.714 0-18.286 8.571-18.286 18.286v36.571c0 9.714 8.571 18.286 18.286 18.286h128v128c0 9.714 8.571 18.286 18.286 18.286h36.571c9.714 0 18.286-8.571 18.286-18.286v-128h128c9.714 0 18.286-8.571 18.286-18.286zM658.286 475.428c0 141.143-114.857 256-256 256s-256-114.857-256-256 114.857-256 256-256 256 114.857 256 256zM950.857 0c0-40.571-32.571-73.143-73.143-73.143-19.429 0-38.286 8-51.429 21.714l-196 195.429c-66.857-46.286-146.857-70.857-228-70.857-222.286 0-402.286 180-402.286 402.286s180 402.286 402.286 402.286 402.286-180 402.286-402.286c0-81.143-24.571-161.143-70.857-228l196-196c13.143-13.143 21.143-32 21.143-51.429z" />
|
||||
<glyph unicode="" glyph-name="search-minus" horiz-adv-x="951" d="M585.143 493.714v-36.571c0-9.714-8.571-18.286-18.286-18.286h-329.143c-9.714 0-18.286 8.571-18.286 18.286v36.571c0 9.714 8.571 18.286 18.286 18.286h329.143c9.714 0 18.286-8.571 18.286-18.286zM658.286 475.428c0 141.143-114.857 256-256 256s-256-114.857-256-256 114.857-256 256-256 256 114.857 256 256zM950.857 0c0-40.571-32.571-73.143-73.143-73.143-19.429 0-38.286 8-51.429 21.714l-196 195.429c-66.857-46.286-146.857-70.857-228-70.857-222.286 0-402.286 180-402.286 402.286s180 402.286 402.286 402.286 402.286-180 402.286-402.286c0-81.143-24.571-161.143-70.857-228l196-196c13.143-13.143 21.143-32 21.143-51.429z" />
|
||||
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 156 KiB |
@@ -27,9 +27,9 @@
|
||||
}
|
||||
|
||||
.ide-updater-dialog .changelog-container {
|
||||
color: var(--theia-dropdown-foreground);
|
||||
background-color: var(--theia-dropdown-background);
|
||||
border: 1px solid var(--theia-tree-indentGuidesStroke);
|
||||
color: var(--theia-editor-foreground);
|
||||
background-color: var(--theia-editor-background);
|
||||
border: 1px solid var(--theia-editorWidget-border);
|
||||
border-radius: 2px;
|
||||
font-size: 12px;
|
||||
height: 180px;
|
||||
@@ -39,7 +39,7 @@
|
||||
}
|
||||
|
||||
.ide-updater-dialog .changelog-container a {
|
||||
color: #018184;
|
||||
color: var(--theia-textLink-foreground);
|
||||
}
|
||||
|
||||
.ide-updater-dialog .changelog-container a:hover {
|
||||
@@ -48,13 +48,13 @@
|
||||
}
|
||||
|
||||
.ide-updater-dialog .changelog-container code {
|
||||
background: #ecf1f1;
|
||||
background: var(--theia-textBlockQuote-background);
|
||||
border-radius: 2px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.ide-updater-dialog .changelog-container a code {
|
||||
color: #018184;
|
||||
color: var(--theia-textLink-foreground);
|
||||
}
|
||||
|
||||
.ide-updater-dialog .buttons-container {
|
||||
|
@@ -18,6 +18,7 @@
|
||||
@import './fonts.css';
|
||||
@import './custom-codicon.css';
|
||||
@import './progress-bar.css';
|
||||
@import './settings-step-input.css';
|
||||
|
||||
.theia-input.warning:focus {
|
||||
outline-width: 1px;
|
||||
@@ -60,25 +61,51 @@
|
||||
/* Overrule the default Theia CSS button styles. */
|
||||
button.theia-button,
|
||||
.theia-button {
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
}
|
||||
|
||||
button.theia-button:hover,
|
||||
.theia-button:hover {
|
||||
border: 1px solid var(--theia-focusBorder);
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-family: 'Open Sans',sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
letter-spacing: .01em;
|
||||
line-height: 24px;
|
||||
outline: none;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-width: 2px;
|
||||
border-radius: 32px;
|
||||
text-transform: uppercase;
|
||||
transition: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
button.theia-button {
|
||||
height: 31px;
|
||||
height: 28px;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.theia-button:active,
|
||||
.theia-button:focus {
|
||||
box-shadow: 0 0 0 2px var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
button.theia-button.secondary {
|
||||
background-color: var(--theia-secondaryButton-background);
|
||||
color: var(--theia-secondaryButton-foreground);
|
||||
border: 2px solid var(--theia-secondaryButton-foreground);
|
||||
}
|
||||
|
||||
button.theia-button.main {
|
||||
button.theia-button[disabled], .theia-button[disabled] {
|
||||
opacity: 0.5;
|
||||
color: var(--theia-button-foreground);
|
||||
background-color: var(--theia-button-background);
|
||||
}
|
||||
|
||||
button.secondary[disabled], .theia-button.secondary[disabled] {
|
||||
color: var(--theia-secondaryButton-foreground);
|
||||
background-color: var(--theia-secondaryButton-background);
|
||||
}
|
||||
|
||||
/* To make the progress-bar slightly thicker, and use the color from the status bar */
|
||||
@@ -109,20 +136,22 @@ button.theia-button.main {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* restore the old Theia spinner */
|
||||
/* https://github.com/eclipse-theia/theia/pull/10761#issuecomment-1131476318 */
|
||||
.old-theia-preload {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 50000;
|
||||
background: var(--theia-editor-background);
|
||||
background-image: var(--theia-preloader);
|
||||
background-size: 60px 60px;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-position: center;
|
||||
transition: opacity 0.8s;
|
||||
}
|
||||
|
||||
/* High Contrast Theme rules */
|
||||
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
|
||||
.hc-black.hc-theia.theia-hc button.theia-button:hover,
|
||||
.hc-black.hc-theia.theia-hc .theia-button:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc button.theia-button,
|
||||
.hc-black.hc-theia.theia-hc .theia-button,
|
||||
.hc-black.hc-theia.theia-hc button.theia-button.secondary {
|
||||
border: 1px solid var(--theia-button-border);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .theia-notification-list-item:hover:not(:focus) {
|
||||
background-color: var(--theia-notifications-background);
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
@@ -127,12 +127,12 @@ https://github.com/arduino/arduino-pro-ide/issues/82 */
|
||||
}
|
||||
|
||||
.component-list-item:hover .footer > * {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
margin: 5px 0px 0px 10px;
|
||||
}
|
||||
|
||||
.component-list-item:hover .footer > label {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
align-self: center;
|
||||
margin: 5px 0px 0px 10px;
|
||||
}
|
||||
@@ -145,3 +145,14 @@ https://github.com/arduino/arduino-pro-ide/issues/82 */
|
||||
.component-list-item a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* High Contrast Theme rules */
|
||||
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
|
||||
.hc-black.hc-theia.theia-hc .component-list-item .header .installed:hover:before {
|
||||
background-color: transparent;
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .component-list-item .header .installed:before {
|
||||
border: 1px solid var(--theia-button-border);
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-tool-item {
|
||||
margin-left: 3px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-tool-item .toggle-serial-monitor,
|
||||
@@ -18,18 +18,30 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background: var(--theia-arduino-toolbar-background);
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-tool-item .arduino-upload-sketch--toolbar,
|
||||
.p-TabBar-toolbar .item.arduino-tool-item .arduino-verify-sketch--toolbar,
|
||||
.p-TabBar-toolbar .item.arduino-tool-item .arduino-start-debug {
|
||||
background: var(--theia-arduino-toolbar-button-background);
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-tool-item.enabled:hover > div {
|
||||
background: var(--theia-arduino-toolbar-hoverBackground);
|
||||
background: var(--theia-arduino-toolbar-button-hoverBackground);
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-tool-item.enabled:hover > div.toggle-serial-monitor,
|
||||
.p-TabBar-toolbar .item.arduino-tool-item.enabled:hover > div.toggle-serial-plotter {
|
||||
background-color: var(--theia-arduino-toolbar-button-secondary-hoverBackground);
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.arduino-verify-sketch--toolbar,
|
||||
.arduino-upload-sketch--toolbar {
|
||||
border-radius: 12px;
|
||||
.arduino-upload-sketch--toolbar,
|
||||
.arduino-start-debug {
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.item.arduino-tool-item.toggled {
|
||||
@@ -38,88 +50,67 @@
|
||||
border: none;
|
||||
}
|
||||
|
||||
.item.arduino-tool-item.toggled .arduino-verify-sketch--toolbar {
|
||||
.item.arduino-tool-item.toggled .arduino-verify-sketch--toolbar,
|
||||
.item.arduino-tool-item.toggled .arduino-upload-sketch--toolbar {
|
||||
background-color: var(--theia-arduino-toolbar-toggleBackground) !important;
|
||||
}
|
||||
|
||||
.arduino-tool-icon {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-color: var(--theia-titleBar-activeBackground);
|
||||
-webkit-mask: url(../icons/mask-buttons.svg);
|
||||
mask: url(../icons/mask-buttons.svg);
|
||||
-webkit-mask-size: 800%;
|
||||
mask-size: 800%;
|
||||
}
|
||||
|
||||
.arduino-save-sketch--toolbar-icon {
|
||||
-webkit-mask-position: 59px -4px;
|
||||
mask-position: 59px -4px;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.arduino-verify-sketch--toolbar-icon {
|
||||
-webkit-mask-position: 188px -4px;
|
||||
mask-position: 188px -4px;
|
||||
-webkit-mask: url(../icons/verify.svg) center no-repeat;
|
||||
background-color: var(--theia-titleBar-activeBackground);
|
||||
}
|
||||
|
||||
.arduino-upload-sketch--toolbar-icon {
|
||||
-webkit-mask-position: 156px -4px;
|
||||
mask-position: 156px -4px;
|
||||
}
|
||||
|
||||
.arduino-new-sketch--toolbar-icon {
|
||||
-webkit-mask-position: 124px -4px;
|
||||
mask-position: 124px -4px;
|
||||
}
|
||||
|
||||
.arduino-open-sketch--toolbar-icon {
|
||||
-webkit-mask-position: 92px -4px;
|
||||
mask-position: 92px -4px;
|
||||
-webkit-mask: url(../icons/upload.svg) center no-repeat;
|
||||
background-color: var(--theia-titleBar-activeBackground);
|
||||
}
|
||||
|
||||
.toggle-serial-monitor-icon {
|
||||
-webkit-mask-position: 28px -4px;
|
||||
mask-position: 28px -4px;
|
||||
-webkit-mask: url(../icons/monitor.svg) center no-repeat;
|
||||
background-color: var(--theia-arduino-toolbar-button-secondary-label);
|
||||
}
|
||||
|
||||
.toggle-serial-plotter-icon {
|
||||
-webkit-mask: url(../icons/plotter.svg) center no-repeat;
|
||||
background-color: var(--theia-arduino-toolbar-button-secondary-label);
|
||||
}
|
||||
|
||||
.arduino-start-debug-icon {
|
||||
-webkit-mask: url('../icons/debug-dark.svg') 50%;
|
||||
mask: url('../icons/debug-dark.svg') 50%;
|
||||
-webkit-mask: url('../icons/debug-dark.svg') 50% 60%;
|
||||
-webkit-mask-size: 70%;
|
||||
mask-size: 70%;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--theia-ui-button-font-color);
|
||||
}
|
||||
background-color: var(--theia-titleBar-activeBackground);
|
||||
|
||||
.arduino-start-debug {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
#arduino-toolbar-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar.theia-arduino-toolbar {
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 0 12px;
|
||||
padding: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#theia-top-panel .p-TabBar-toolbar {
|
||||
padding-left: 4px !important; /* moves the `verify`, upload and other toolbar items to the left */
|
||||
}
|
||||
|
||||
.p-Widget .p-MenuBar {
|
||||
padding-left: 1px !important; /* moves the menubar: `File`, `Edit`, etc to the left */
|
||||
:root {
|
||||
--theia-private-menubar-height: 40px; /* set the topbar height */
|
||||
}
|
||||
|
||||
#theia-top-panel .p-TabBar-toolbar.theia-arduino-toolbar.right {
|
||||
justify-content: flex-start;
|
||||
min-width: 190px;
|
||||
}
|
||||
|
||||
#theia-top-panel .p-TabBar-toolbar.theia-arduino-toolbar.left {
|
||||
@@ -128,7 +119,6 @@
|
||||
}
|
||||
|
||||
.arduino-toolbar-tooltip {
|
||||
margin-left: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--theia-titleBar-activeForeground);
|
||||
@@ -161,6 +151,10 @@
|
||||
align-items: center;
|
||||
color: var(--theia-titleBar-activeBackground);
|
||||
}
|
||||
.p-TabBar.theia-app-sides .p-TabBar-tabIcon.fa-arduino-folder,
|
||||
.p-TabBar.theia-app-sides .p-TabBar-tabIcon.fa-arduino-boards {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.monaco-editor .margin {
|
||||
border-right: 2px solid var(--theia-sideBar-background);
|
||||
@@ -177,33 +171,75 @@
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#arduino-open-sketch-control--toolbar--container {
|
||||
background-color: var(--theia-arduino-toolbar-background);
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
#arduino-open-sketch-control--toolbar {
|
||||
height: unset;
|
||||
width: unset;
|
||||
line-height: unset;
|
||||
color: var(--theia-titleBar-activeBackground);
|
||||
padding: 5px 8px; /* based on pure heuristics */
|
||||
}
|
||||
|
||||
/* Output */
|
||||
.theia-output .editor-container {
|
||||
background-color: var(--theia-arduino-output-background);
|
||||
background-color: var(--theia-terminal-background);
|
||||
}
|
||||
|
||||
.theia-output .monaco-editor .lines-content.monaco-editor-background {
|
||||
background-color: var(--theia-arduino-output-background);
|
||||
background-color: var(--theia-terminal-background);
|
||||
}
|
||||
|
||||
.theia-output .monaco-editor .lines-content.monaco-editor-background .view-lines .view-line .mtk1:not(.theia-output-error):not(.theia-output-warning) {
|
||||
color: var(--theia-arduino-output-foreground);
|
||||
color: var(--theia-terminal-foreground);
|
||||
}
|
||||
|
||||
.theia-output .monaco-editor .margin {
|
||||
border-right: none;
|
||||
background-color: var(--theia-arduino-output-background);
|
||||
background-color: var(--theia-terminal-background);
|
||||
}
|
||||
|
||||
|
||||
/* High Contrast Theme rules */
|
||||
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
|
||||
.hc-black.hc-theia.theia-hc .p-TabBar-toolbar .item.arduino-tool-item.enabled:hover > div {
|
||||
background: var(--theia-arduino-toolbar-button-background);
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .p-TabBar-toolbar .item.arduino-tool-item.enabled:hover > div.toggle-serial-plotter,
|
||||
.hc-black.hc-theia.theia-hc .p-TabBar-toolbar .item.arduino-tool-item.enabled:hover > div.toggle-serial-monitor {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .item.arduino-tool-item.toggled .arduino-verify-sketch--toolbar,
|
||||
.hc-black.hc-theia.theia-hc .item.arduino-tool-item.toggled .arduino-upload-sketch--toolbar {
|
||||
background-color: var(--theia-arduino-toolbar-button-background) !important;
|
||||
outline: 1px solid var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .arduino-boards-dropdown-item:hover {
|
||||
background: var(--theia-dropdown-background);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .arduino-boards-dropdown-item:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc #theia-main-content-panel .p-TabBar .p-TabBar-tab.p-mod-current {
|
||||
outline: 1px solid var(--theia-focusBorder);
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc #theia-main-content-panel .p-TabBar .p-TabBar-tab:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable > .p-TabBar-tabCloseIcon:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .quick-input-list .monaco-list-row.focused {
|
||||
outline: 1px dotted var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .quick-input-list .monaco-list-row:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .quick-input-widget {
|
||||
outline: 1px solid var(--theia-contrastBorder);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
}
|
||||
|
||||
.progress-bar--outer {
|
||||
background: #e5e5e5;
|
||||
background: var(--theia-editorWidget-background);
|
||||
border-radius: 11px;
|
||||
height: 6px;
|
||||
position: relative;
|
||||
@@ -13,7 +13,7 @@
|
||||
.progress-bar--inner {
|
||||
transition: width 1s;
|
||||
height: 100%;
|
||||
background: #008184;
|
||||
background: var(--theia-progressBar-background);
|
||||
border-radius: 11px;
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,20 @@
|
||||
.arduino-settings-dialog {
|
||||
width: 740px;
|
||||
#arduino-settings-dialog-container > .dialogBlock {
|
||||
height: 531px;;
|
||||
max-width: 740px !important;
|
||||
width: calc(100% - 96px);
|
||||
}
|
||||
|
||||
#arduino-settings-dialog-container > .dialogBlock > .dialogContent {
|
||||
justify-content: flex-start;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#arduino-settings-dialog-container > .dialogBlock > .dialogControl {
|
||||
padding: 16px 0 26px;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .content {
|
||||
padding: 5px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .flex-line {
|
||||
@@ -26,8 +36,13 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .column-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .stretch {
|
||||
width: 100% !important;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .flex-line .theia-button.shrink {
|
||||
@@ -50,14 +65,31 @@
|
||||
.additional-urls-dialog .link:hover {
|
||||
color: var(--theia-textLink-activeForeground);
|
||||
}
|
||||
.arduino-settings-dialog .react-tabs__tab-panel {
|
||||
padding-bottom: 25px;
|
||||
|
||||
.arduino-settings-dialog .react-tabs__tab--selected {
|
||||
background: var(--theia-editorWidget-background);
|
||||
border-color: var(--theia-tab-activeBorder);
|
||||
color: var(--theia-tab-activeForeground);
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .react-tabs__tab-list {
|
||||
border-color: var(--theia-tab-activeBorder);
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .react-tabs__tab-panel {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.arduino-settings-dialog .react-tabs__tab-list {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.additional-urls-dialog textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-Widget.dialogOverlay .dialogBlock .dialogContent.additional-urls-dialog {
|
||||
display: block;
|
||||
}
|
||||
|
@@ -0,0 +1,46 @@
|
||||
.settings-step-input-container {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.settings-step-input-element::-webkit-inner-spin-button,
|
||||
.settings-step-input-element::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.settings-step-input-buttons-container {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50%;
|
||||
transform: translate(0px, -50%);
|
||||
height: calc(100% - 4px);
|
||||
width: 14px;
|
||||
padding: 2px;
|
||||
background: var(--theia-input-background);
|
||||
}
|
||||
|
||||
.settings-step-input-container:hover > .settings-step-input-buttons-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.settings-step-input-up-button {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
.settings-step-input-button {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
height: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.settings-step-input-button:hover {
|
||||
background: rgba(128, 128, 128, 0.8);
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M27 6H5.00002C4.73504 6.00077 4.48113 6.10637 4.29376 6.29374C4.10639 6.48111 4.00079 6.73502 4.00002 7V19H28V7C27.9993 6.73502 27.8937 6.48111 27.7063 6.29374C27.5189 6.10637 27.265 6.00077 27 6ZM9.29002 10.29L10.29 9.29C10.4786 9.10297 10.7336 8.99826 10.9992 8.9988C11.2648 8.99934 11.5193 9.10509 11.7071 9.29289C11.8949 9.4807 12.0007 9.73526 12.0012 10.0008C12.0018 10.2664 11.8971 10.5214 11.71 10.71L10.71 11.71C10.5204 11.8959 10.2655 12 10 12C9.73452 12 9.4796 11.8959 9.29002 11.71C9.10267 11.5212 8.99754 11.266 8.99754 11C8.99754 10.734 9.10267 10.4788 9.29002 10.29ZM16.71 11.71L12.71 15.71C12.5204 15.8959 12.2655 16 12 16C11.7345 16 11.4796 15.8959 11.29 15.71C11.1027 15.5212 10.9975 15.266 10.9975 15C10.9975 14.734 11.1027 14.4788 11.29 14.29L15.29 10.29C15.4786 10.103 15.7336 9.99826 15.9992 9.9988C16.2648 9.99934 16.5193 10.1051 16.7071 10.2929C16.8949 10.4807 17.0007 10.7353 17.0012 11.0008C17.0018 11.2664 16.8971 11.5214 16.71 11.71Z" fill="black"/>
|
||||
<path d="M30.89 25.4516C30.8063 25.616 30.679 25.7543 30.5221 25.8513C30.3651 25.9482 30.1845 26.0003 30 26.0016H2.00002C1.81552 26.0003 1.63493 25.9482 1.47798 25.8513C1.32102 25.7543 1.19374 25.616 1.11002 25.4516C1.02538 25.2856 0.988954 25.0993 1.00486 24.9137C1.02077 24.7281 1.08838 24.5507 1.20002 24.4016L3.75002 21.0016H28.25L30.8 24.4016C30.9117 24.5507 30.9793 24.7281 30.9952 24.9137C31.0111 25.0993 30.9747 25.2856 30.89 25.4516Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,11 +1,5 @@
|
||||
<svg width="20" height="14" viewBox="0 0 20 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M19.2492 12.2509L17.4992 9.9197V1.37595C17.4987 1.21033 17.4327 1.05164 17.3156 0.934533C17.1985 0.817426 17.0398 0.751424 16.8742 0.750946H3.12422C2.95861 0.751441 2.79992 0.817448 2.68282 0.934551C2.56572 1.05165 2.49971 1.21034 2.49922 1.37595V9.9197L0.749217 12.2509C0.679462 12.3442 0.637219 12.455 0.627276 12.571C0.617334 12.687 0.640091 12.8035 0.692967 12.9072C0.745302 13.0099 0.824858 13.0964 0.922952 13.157C1.02105 13.2176 1.13391 13.2501 1.24922 13.2509H18.7492C18.8645 13.2501 18.9774 13.2176 19.0755 13.157C19.1736 13.0964 19.2531 13.0099 19.3055 12.9072C19.3583 12.8035 19.3811 12.687 19.3712 12.571C19.3612 12.455 19.319 12.3442 19.2492 12.2509ZM3.74922 2.00095H16.2492V9.50095H3.74922V2.00095ZM2.49922 12.0009L3.43672 10.7509H16.5617L17.4992 12.0009H2.49922Z"
|
||||
fill="#616161" />
|
||||
<path
|
||||
d="M7.49987 7.62501C7.37627 7.62498 7.25546 7.58831 7.15271 7.51964C7.04995 7.45096 6.96986 7.35336 6.92257 7.23917C6.87527 7.12498 6.8629 6.99934 6.887 6.87812C6.91111 6.7569 6.97061 6.64554 7.05799 6.55814L9.55799 4.05814C9.67587 3.94429 9.83374 3.88129 9.99762 3.88271C10.1615 3.88414 10.3182 3.94987 10.4341 4.06575C10.55 4.18163 10.6157 4.33839 10.6172 4.50226C10.6186 4.66613 10.5556 4.82401 10.4417 4.94189L7.94174 7.44189C7.88379 7.50002 7.81491 7.54612 7.73908 7.57755C7.66325 7.60898 7.58195 7.62511 7.49987 7.62501Z"
|
||||
fill="#616161" />
|
||||
<path
|
||||
d="M6.24987 5.12501C6.12627 5.12498 6.00546 5.08831 5.90271 5.01964C5.79995 4.95096 5.71986 4.85336 5.67257 4.73917C5.62527 4.62498 5.6129 4.49934 5.637 4.37812C5.66111 4.2569 5.72061 4.14554 5.80799 4.05814L6.43299 3.43314C6.55087 3.31929 6.70874 3.25629 6.87262 3.25771C7.03649 3.25914 7.19325 3.32487 7.30913 3.44075C7.42501 3.55663 7.49074 3.71339 7.49216 3.87726C7.49359 4.04113 7.43059 4.19901 7.31674 4.31688L6.69174 4.94189C6.63379 5.00002 6.56491 5.04612 6.48908 5.07755C6.41325 5.10898 6.33195 5.12511 6.24987 5.12501Z"
|
||||
fill="#616161" />
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M30.7985 24.4015L27.9985 20.6715V7.00153C27.9977 6.73654 27.8921 6.48264 27.7048 6.29526C27.5174 6.10789 27.2635 6.00229 26.9985 6.00153H4.9985C4.73353 6.00232 4.47964 6.10793 4.29227 6.29529C4.10491 6.48266 3.99929 6.73655 3.9985 7.00153V20.6715L1.1985 24.4015C1.0869 24.5507 1.01931 24.7281 1.0034 24.9137C0.98749 25.0992 1.0239 25.2856 1.1085 25.4515C1.19224 25.6159 1.31953 25.7542 1.47648 25.8512C1.63343 25.9482 1.81401 26.0002 1.9985 26.0015H29.9985C30.183 26.0002 30.3636 25.9482 30.5205 25.8512C30.6775 25.7542 30.8048 25.6159 30.8885 25.4515C30.9731 25.2856 31.0095 25.0992 30.9936 24.9137C30.9777 24.7281 30.9101 24.5507 30.7985 24.4015ZM5.9985 8.00153H25.9985V20.0015H5.9985V8.00153ZM3.9985 24.0015L5.4985 22.0015H26.4985L27.9985 24.0015H3.9985Z" fill="black"/>
|
||||
<path d="M12 17C11.8023 17 11.609 16.9413 11.4445 16.8314C11.2801 16.7216 11.152 16.5654 11.0763 16.3827C11.0007 16.2 10.9808 15.999 11.0194 15.805C11.058 15.6111 11.1532 15.4329 11.293 15.293L15.293 11.293C15.4816 11.1109 15.7342 11.0101 15.9964 11.0124C16.2586 11.0146 16.5094 11.1198 16.6948 11.3052C16.8802 11.4906 16.9854 11.7414 16.9877 12.0036C16.99 12.2658 16.8892 12.5184 16.707 12.707L12.707 16.707C12.6143 16.8001 12.5041 16.8738 12.3827 16.9241C12.2614 16.9744 12.1313 17.0002 12 17Z" fill="black"/>
|
||||
<path d="M10 13C9.80225 13 9.60895 12.9413 9.44454 12.8314C9.28013 12.7216 9.15199 12.5654 9.07632 12.3827C9.00065 12.2 8.98085 11.999 9.01942 11.805C9.05798 11.6111 9.15319 11.4329 9.293 11.293L10.293 10.293C10.4816 10.1109 10.7342 10.0101 10.9964 10.0124C11.2586 10.0146 11.5094 10.1198 11.6948 10.3052C11.8802 10.4906 11.9854 10.7414 11.9877 11.0036C11.99 11.2658 11.8892 11.5184 11.707 11.707L10.707 12.707C10.6143 12.8001 10.5041 12.8738 10.3827 12.9241C10.2614 12.9744 10.1313 13.0002 10 13Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -1,38 +1,58 @@
|
||||
.sketchbook-tab-icon {
|
||||
-webkit-mask: url('./sketchbook.svg');
|
||||
mask: url('./sketchbook.svg');
|
||||
-webkit-mask: url('./sketchbook.svg');
|
||||
mask: url('./sketchbook.svg');
|
||||
}
|
||||
|
||||
.sketch-folder-icon {
|
||||
background: url('./sketch-folder-icon.svg') center center no-repeat;
|
||||
background-position-x: 1px;
|
||||
width: var(--theia-icon-size);
|
||||
height: var(--theia-icon-size);
|
||||
background: url('./sketch-folder-icon.svg') center center no-repeat;
|
||||
background-position-x: 1px;
|
||||
width: var(--theia-icon-size);
|
||||
height: var(--theia-icon-size);
|
||||
}
|
||||
|
||||
.p-TabBar-tabIcon.sketchbook-tree-icon {
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./sketchbook-tree-icon.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
width: 19px !important;
|
||||
height: var(--theia-icon-size);
|
||||
-webkit-mask-size: 100%;
|
||||
}
|
||||
|
||||
.p-mod-current
|
||||
.sketchbook-tree-icon {
|
||||
background: url('./sketchbook-tree-icon.svg') center center no-repeat;
|
||||
width: 19px !important;
|
||||
height: var(--theia-icon-size);
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./sketchbook-tree-icon-filled.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
-webkit-mask-size: 100%;
|
||||
}
|
||||
|
||||
.sketchbook-trees-container {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sketchbook-tree__opts {
|
||||
background: url('./sketchbook-opts-icon.svg') center center no-repeat;
|
||||
background-color: var(--theia-foreground);
|
||||
-webkit-mask: url(./sketchbook-opts-icon.svg);
|
||||
-webkit-mask-position: center;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
width: var(--theia-icon-size);
|
||||
height: var(--theia-icon-size);
|
||||
}
|
||||
|
||||
.active-sketch {
|
||||
font-weight: 500;
|
||||
background-color: var(--theia-button-disabledBackground) !important;
|
||||
color: var(--theia-list-inactiveSelectionForeground) !important;
|
||||
background-color: var(--theia-list-activeSelectionBackground) !important;
|
||||
color: var(--theia-list-activeSelectionForeground) !important;
|
||||
|
||||
}
|
||||
|
||||
#arduino-sketchbook-tree-widget .theia-TreeNode {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#arduino-sketchbook-tree-widget .theia-TreeNodeSegmentGrow {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -44,4 +64,26 @@
|
||||
.theia-TreeNode:hover .sketchbook-commands-icons,
|
||||
.theia-TreeNode.theia-mod-selected .sketchbook-commands-icons {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.theia-Tree:focus .theia-TreeNode.theia-mod-selected,
|
||||
.theia-Tree .ReactVirtualized__List:focus .theia-TreeNode.theia-mod-selected {
|
||||
background: var(--theia-list-inactiveSelectionBackground);
|
||||
color: var(--theia-list-inactiveSelectionForeground) !important;
|
||||
}
|
||||
|
||||
|
||||
/* High Contrast Theme rules */
|
||||
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
|
||||
.hc-black.hc-theia.theia-hc .theia-TreeNode:hover {
|
||||
outline: 1px dashed var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .theia-Tree .theia-TreeNode.theia-mod-selected {
|
||||
outline: 1px dotted var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.hc-black.hc-theia.theia-hc .theia-Tree:focus .theia-TreeNode.theia-mod-selected,
|
||||
.hc-black.hc-theia.theia-hc .theia-Tree .ReactVirtualized__List:focus .theia-TreeNode.theia-mod-selected {
|
||||
outline: 1px solid var(--theia-focusBorder);
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@
|
||||
}
|
||||
|
||||
.user-fields-dialog-content .field-label {
|
||||
color: #2c353a;
|
||||
color: var(--theia-editorWidget-foreground);
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
@@ -29,4 +29,4 @@
|
||||
|
||||
.user-fields-dialog-content .button-container {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
@@ -10,28 +10,35 @@ import {
|
||||
import {
|
||||
ApplicationShell as TheiaApplicationShell,
|
||||
DockPanel,
|
||||
DockPanelRenderer as TheiaDockPanelRenderer,
|
||||
Panel,
|
||||
TabBar,
|
||||
Widget,
|
||||
SHELL_TABBAR_CONTEXT_MENU,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { Sketch } from '../../../common/protocol';
|
||||
import { SaveAsSketch } from '../../contributions/save-as-sketch';
|
||||
import { CurrentSketch, SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
|
||||
import {
|
||||
CurrentSketch,
|
||||
SketchesServiceClientImpl,
|
||||
} from '../../../common/protocol/sketches-service-client-impl';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { ToolbarAwareTabBar } from './tab-bars';
|
||||
|
||||
@injectable()
|
||||
export class ApplicationShell extends TheiaApplicationShell {
|
||||
@inject(CommandService)
|
||||
protected readonly commandService: CommandService;
|
||||
private readonly commandService: CommandService;
|
||||
|
||||
@inject(MessageService)
|
||||
protected readonly messageService: MessageService;
|
||||
private readonly messageService: MessageService;
|
||||
|
||||
@inject(SketchesServiceClientImpl)
|
||||
protected readonly sketchesServiceClient: SketchesServiceClientImpl;
|
||||
private readonly sketchesServiceClient: SketchesServiceClientImpl;
|
||||
|
||||
@inject(ConnectionStatusService)
|
||||
protected readonly connectionStatusService: ConnectionStatusService;
|
||||
private readonly connectionStatusService: ConnectionStatusService;
|
||||
|
||||
protected override track(widget: Widget): void {
|
||||
super.track(widget);
|
||||
@@ -43,7 +50,7 @@ export class ApplicationShell extends TheiaApplicationShell {
|
||||
this.sketchesServiceClient.currentSketch().then((sketch) => {
|
||||
if (CurrentSketch.isValid(sketch)) {
|
||||
if (!this.isSketchFile(widget.editor.uri, sketch.uri)) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (Sketch.isInSketch(widget.editor.uri, sketch)) {
|
||||
widget.title.closable = false;
|
||||
@@ -54,11 +61,11 @@ export class ApplicationShell extends TheiaApplicationShell {
|
||||
}
|
||||
|
||||
private isSketchFile(uri: URI, sketchUriString: string): boolean {
|
||||
const sketchUri = new URI(sketchUriString);
|
||||
if (uri.parent.isEqual(sketchUri)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
const sketchUri = new URI(sketchUriString);
|
||||
if (uri.parent.isEqual(sketchUri)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override async addWidget(
|
||||
@@ -120,15 +127,41 @@ export class ApplicationShell extends TheiaApplicationShell {
|
||||
}
|
||||
}
|
||||
|
||||
export class DockPanelRenderer extends TheiaDockPanelRenderer {
|
||||
override createTabBar(): TabBar<Widget> {
|
||||
const renderer = this.tabBarRendererFactory();
|
||||
// `ToolbarAwareTabBar` is from IDE2 and not from Theia. Check the imports.
|
||||
const tabBar = new ToolbarAwareTabBar(
|
||||
this.tabBarToolbarRegistry,
|
||||
this.tabBarToolbarFactory,
|
||||
this.breadcrumbsRendererFactory,
|
||||
{
|
||||
renderer,
|
||||
// Scroll bar options
|
||||
handlers: ['drag-thumb', 'keyboard', 'wheel', 'touch'],
|
||||
useBothWheelAxes: true,
|
||||
scrollXMarginOffset: 4,
|
||||
suppressScrollY: true,
|
||||
}
|
||||
);
|
||||
this.tabBarClasses.forEach((c) => tabBar.addClass(c));
|
||||
renderer.tabBar = tabBar;
|
||||
tabBar.disposed.connect(() => renderer.dispose());
|
||||
renderer.contextMenuPath = SHELL_TABBAR_CONTEXT_MENU;
|
||||
tabBar.currentChanged.connect(this.onCurrentTabChanged, this);
|
||||
return tabBar;
|
||||
}
|
||||
}
|
||||
|
||||
const originalHandleEvent = DockPanel.prototype.handleEvent;
|
||||
|
||||
DockPanel.prototype.handleEvent = function (event) {
|
||||
switch (event.type) {
|
||||
case 'p-dragenter':
|
||||
case 'p-dragleave':
|
||||
case 'p-dragover':
|
||||
case 'p-drop':
|
||||
return;
|
||||
case 'p-dragenter':
|
||||
case 'p-dragleave':
|
||||
case 'p-dragover':
|
||||
case 'p-drop':
|
||||
return;
|
||||
}
|
||||
originalHandleEvent.bind(this)(event);
|
||||
};
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
import { ArduinoDaemon } from '../../../common/protocol';
|
||||
import { NotificationCenter } from '../../notification-center';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import debounce = require('lodash.debounce');
|
||||
|
||||
@injectable()
|
||||
export class FrontendConnectionStatusService extends TheiaFrontendConnectionStatusService {
|
||||
@@ -30,16 +31,17 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat
|
||||
try {
|
||||
this.connectedPort = await this.daemon.tryGetPort();
|
||||
} catch {}
|
||||
this.notificationCenter.onDaemonStarted(
|
||||
this.notificationCenter.onDaemonDidStart(
|
||||
(port) => (this.connectedPort = port)
|
||||
);
|
||||
this.notificationCenter.onDaemonStopped(
|
||||
this.notificationCenter.onDaemonDidStop(
|
||||
() => (this.connectedPort = undefined)
|
||||
);
|
||||
this.wsConnectionProvider.onIncomingMessageActivity(() => {
|
||||
const refresh = debounce(() => {
|
||||
this.updateStatus(!!this.connectedPort);
|
||||
this.schedulePing();
|
||||
});
|
||||
}, this.options.offlineTimeout - 10);
|
||||
this.wsConnectionProvider.onIncomingMessageActivity(() => refresh());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +60,10 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon
|
||||
try {
|
||||
this.connectedPort = await this.daemon.tryGetPort();
|
||||
} catch {}
|
||||
this.notificationCenter.onDaemonStarted(
|
||||
this.notificationCenter.onDaemonDidStart(
|
||||
(port) => (this.connectedPort = port)
|
||||
);
|
||||
this.notificationCenter.onDaemonStopped(
|
||||
this.notificationCenter.onDaemonDidStop(
|
||||
() => (this.connectedPort = undefined)
|
||||
);
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ 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';
|
||||
import { SketchesService } from '../../../common/protocol';
|
||||
import { ArduinoCommands } from '../../arduino-commands';
|
||||
import { OpenSketchFiles } from '../../contributions/open-sketch-files';
|
||||
|
||||
@injectable()
|
||||
export class FrontendApplication extends TheiaFrontendApplication {
|
||||
@@ -25,33 +25,11 @@ export class FrontendApplication extends TheiaFrontendApplication {
|
||||
this.workspaceService.roots.then(async (roots) => {
|
||||
for (const root of roots) {
|
||||
await this.commandService.executeCommand(
|
||||
ArduinoCommands.OPEN_SKETCH_FILES.id,
|
||||
OpenSketchFiles.Commands.OPEN_SKETCH_FILES.id,
|
||||
root.resource
|
||||
);
|
||||
this.sketchesService.markAsRecentlyOpened(root.resource.toString()); // no await, will get the notification later and rebuild the menu
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override getStartupIndicator(
|
||||
host: HTMLElement
|
||||
): HTMLElement | undefined {
|
||||
let startupElement = this.doGetStartupIndicator(host, 'old-theia-preload'); // https://github.com/eclipse-theia/theia/pull/10761#issuecomment-1131476318
|
||||
if (!startupElement) {
|
||||
startupElement = this.doGetStartupIndicator(host, 'theia-preload'); // We show the new Theia spinner in dev mode.
|
||||
}
|
||||
return startupElement;
|
||||
}
|
||||
|
||||
private doGetStartupIndicator(
|
||||
host: HTMLElement,
|
||||
classNames: string
|
||||
): HTMLElement | undefined {
|
||||
const elements = host.getElementsByClassName(classNames);
|
||||
const first = elements[0];
|
||||
if (first instanceof HTMLElement) {
|
||||
return first;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
13
arduino-ide-extension/src/browser/theia/core/status-bar.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
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,8 +1,13 @@
|
||||
import { TabBar } from '@theia/core/shared/@phosphor/widgets';
|
||||
import type { TabBar } from '@theia/core/shared/@phosphor/widgets';
|
||||
import { Saveable } from '@theia/core/lib/browser/saveable';
|
||||
import { TabBarRenderer as TheiaTabBarRenderer } from '@theia/core/lib/browser/shell/tab-bars';
|
||||
import {
|
||||
TabBarRenderer as TheiaTabBarRenderer,
|
||||
ToolbarAwareTabBar as TheiaToolbarAwareTabBar,
|
||||
} from '@theia/core/lib/browser/shell/tab-bars';
|
||||
import debounce = require('lodash.debounce');
|
||||
|
||||
export class TabBarRenderer extends TheiaTabBarRenderer {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
override createTabClass(data: TabBar.IRenderData<any>): string {
|
||||
let className = super.createTabClass(data);
|
||||
if (!data.title.closable && Saveable.isDirty(data.title.owner)) {
|
||||
@@ -10,4 +15,22 @@ export class TabBarRenderer extends TheiaTabBarRenderer {
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
protected override handleContextMenuEvent = (): void => {
|
||||
// NOOP
|
||||
// Context menus are empty, so they have been removed
|
||||
};
|
||||
}
|
||||
|
||||
export class ToolbarAwareTabBar extends TheiaToolbarAwareTabBar {
|
||||
protected override async updateBreadcrumbs(): Promise<void> {
|
||||
// NOOP
|
||||
// IDE2 does not use breadcrumbs.
|
||||
}
|
||||
|
||||
private readonly doUpdateToolbar = debounce(() => super.updateToolbar(), 500);
|
||||
protected override updateToolbar(): void {
|
||||
// Unlike Theia, IDE2 debounces the toolbar updates with 500ms
|
||||
this.doUpdateToolbar();
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { EditorWidget } from '@theia/editor/lib/browser';
|
||||
import { LabelProvider } from '@theia/core/lib/browser';
|
||||
import type { NavigatableWidgetOptions } from '@theia/core/lib/browser';
|
||||
import { EditorWidgetFactory as TheiaEditorWidgetFactory } from '@theia/editor/lib/browser/editor-widget-factory';
|
||||
import {
|
||||
CurrentSketch,
|
||||
@@ -13,16 +13,16 @@ import { nls } from '@theia/core/lib/common';
|
||||
@injectable()
|
||||
export class EditorWidgetFactory extends TheiaEditorWidgetFactory {
|
||||
@inject(SketchesService)
|
||||
protected readonly sketchesService: SketchesService;
|
||||
private readonly sketchesService: SketchesService;
|
||||
|
||||
@inject(SketchesServiceClientImpl)
|
||||
protected readonly sketchesServiceClient: SketchesServiceClientImpl;
|
||||
private readonly sketchesServiceClient: SketchesServiceClientImpl;
|
||||
|
||||
@inject(LabelProvider)
|
||||
protected override readonly labelProvider: LabelProvider;
|
||||
|
||||
protected override async createEditor(uri: URI): Promise<EditorWidget> {
|
||||
const widget = await super.createEditor(uri);
|
||||
protected override async createEditor(
|
||||
uri: URI,
|
||||
options: NavigatableWidgetOptions
|
||||
): Promise<EditorWidget> {
|
||||
const widget = await super.createEditor(uri, options);
|
||||
return this.maybeUpdateCaption(widget);
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,15 @@
|
||||
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { Diagnostic } from 'vscode-languageserver-types';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { ILogger } from '@theia/core';
|
||||
import { Marker } from '@theia/markers/lib/common/marker';
|
||||
import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser/problem/problem-manager';
|
||||
import { ConfigService } from '../../../common/protocol/config-service';
|
||||
import debounce = require('lodash.debounce');
|
||||
|
||||
@injectable()
|
||||
export class ProblemManager extends TheiaProblemManager {
|
||||
@@ -37,4 +42,12 @@ export class ProblemManager extends TheiaProblemManager {
|
||||
}
|
||||
return super.setMarkers(uri, owner, data);
|
||||
}
|
||||
|
||||
private readonly debouncedFireOnDidChangeMakers = debounce(
|
||||
(uri: URI) => this.onDidChangeMarkersEmitter.fire(uri),
|
||||
500
|
||||
);
|
||||
protected override fireOnDidChangeMarkers(uri: URI): void {
|
||||
this.debouncedFireOnDidChangeMakers(uri);
|
||||
}
|
||||
}
|
||||
|