mirror of
				https://github.com/arduino/arduino-ide.git
				synced 2025-10-31 14:08:32 +00:00 
			
		
		
		
	Compare commits
	
		
			20 Commits
		
	
	
		
			experiment
			...
			dependabot
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 1a55a5c560 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 3d8f3fa3e3 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | c1e5fbc8a5 | ||
|   | ee4f74d566 | ||
|   | 0f9f0d07b7 | ||
|   | 2f0414a5a1 | ||
| ![github-actions[bot]](/assets/img/avatar_default.png)  | e3319dab1a | ||
|   | a669a43449 | ||
|   | 56ab874177 | ||
|   | e36f393682 | ||
|   | 4d52bb2843 | ||
|   | 39c8db8e90 | ||
|   | 8aa3c28c50 | ||
|   | d293595b89 | ||
|   | 4b0982ccb3 | ||
|   | 9b15695c60 | ||
| ![github-actions[bot]](/assets/img/avatar_default.png)  | 0dff87e29c | ||
|   | 7dafe7b0d3 | ||
|   | 859d29d41a | ||
|   | d298b3ffc9 | 
| @@ -14,7 +14,6 @@ module.exports = { | ||||
|     '.browser_modules/*', | ||||
|     'docs/*', | ||||
|     'scripts/*', | ||||
|     'browser-app/*', | ||||
|     'electron-app/lib/*', | ||||
|     'electron-app/src-gen/*', | ||||
|     'electron-app/gen-webpack*.js', | ||||
|   | ||||
							
								
								
									
										36
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -172,6 +172,7 @@ jobs: | ||||
|       is-nightly: ${{ steps.determination.outputs.is-nightly }} | ||||
|       channel-name: ${{ steps.determination.outputs.channel-name }} | ||||
|       publish-to-s3: ${{ steps.determination.outputs.publish-to-s3 }} | ||||
|     environment: production | ||||
|     permissions: {} | ||||
|     steps: | ||||
|       - name: Determine the type of build | ||||
| @@ -294,6 +295,7 @@ jobs: | ||||
|       SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0/x86/signtool.exe" | ||||
|       WIN_CERT_PASSWORD: ${{ secrets[matrix.config.certificate-password-secret] }} | ||||
|       WIN_CERT_CONTAINER_NAME: ${{ secrets[matrix.config.certificate-container] }} | ||||
|       PUPPETEER_SKIP_DOWNLOAD: true | ||||
|  | ||||
|     strategy: | ||||
|       matrix: | ||||
| @@ -315,7 +317,7 @@ jobs: | ||||
|           if not exist "${{ matrix.config.working-directory }}" mklink /d "${{ matrix.config.working-directory }}" "C:\actions-runner\_work\arduino-ide\arduino-ide" | ||||
|  | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|  | ||||
|       - name: Install Node.js | ||||
| @@ -338,7 +340,7 @@ jobs: | ||||
|  | ||||
|       - name: Install Python 3.x | ||||
|         if: fromJSON(matrix.config.container) == null && runner.name != 'WINDOWS-SIGN-PC' | ||||
|         uses: actions/setup-python@v5 | ||||
|         uses: actions/setup-python@v6 | ||||
|         with: | ||||
|           python-version: '3.11.x' | ||||
|  | ||||
| @@ -439,10 +441,10 @@ jobs: | ||||
|           echo "CHANNEL_FILES_PATH=${{ runner.temp }}/channel-files" >> "$GITHUB_ENV" | ||||
|  | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Download staged-for-merge channel file artifacts | ||||
|         uses: actions/download-artifact@v4 | ||||
|         uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           merge-multiple: true | ||||
|           path: ${{ env.CHANNEL_FILES_PATH }} | ||||
| @@ -471,6 +473,12 @@ jobs: | ||||
|           repo-token: ${{ secrets.GITHUB_TOKEN }} | ||||
|           version: 3.x | ||||
|  | ||||
|       - name: Install dependencies (Linux only) | ||||
|         if: runner.os == 'Linux' | ||||
|         run: | | ||||
|           sudo apt-get update | ||||
|           sudo apt-get install -y libx11-dev libxkbfile-dev libsecret-1-dev | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         run: yarn | ||||
|  | ||||
| @@ -505,7 +513,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Download job transfer artifact that contains ${{ matrix.artifact.name }} tester build | ||||
|         uses: actions/download-artifact@v4 | ||||
|         uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           name: ${{ env.JOB_TRANSFER_ARTIFACT_PREFIX }}${{ matrix.artifact.job-transfer-artifact-suffix }} | ||||
|           path: ${{ env.BUILD_ARTIFACTS_FOLDER }} | ||||
| @@ -525,7 +533,7 @@ jobs: | ||||
|       BODY: ${{ steps.changelog.outputs.BODY }} | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|         with: | ||||
|           fetch-depth: 0 # To fetch all history for all branches and tags. | ||||
|  | ||||
| @@ -588,11 +596,11 @@ jobs: | ||||
|  | ||||
|     permissions: | ||||
|       id-token: write | ||||
|       contents: read  | ||||
|       contents: read | ||||
|  | ||||
|     steps: | ||||
|       - name: Download all job transfer artifacts | ||||
|         uses: actions/download-artifact@v4 | ||||
|         uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           merge-multiple: true | ||||
|           path: ${{ env.ARTIFACTS_FOLDER }} | ||||
| @@ -601,8 +609,8 @@ jobs: | ||||
|       - name: Configure AWS Credentials for Nightly [S3] | ||||
|         uses: aws-actions/configure-aws-credentials@v4 | ||||
|         with: | ||||
|           role-to-assume: ${{ secrets.AWS_ROLE_ARN }}  | ||||
|           aws-region: us-east-1  | ||||
|           role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | ||||
|           aws-region: us-east-1 | ||||
|  | ||||
|       - name: Publish Nightly [S3] | ||||
|         run: | | ||||
| @@ -631,11 +639,11 @@ jobs: | ||||
|  | ||||
|     permissions: | ||||
|       id-token: write | ||||
|       contents: read | ||||
|       contents: write | ||||
|  | ||||
|     steps: | ||||
|       - name: Download all job transfer artifacts | ||||
|         uses: actions/download-artifact@v4 | ||||
|         uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           merge-multiple: true | ||||
|           path: ${{ env.ARTIFACTS_FOLDER }} | ||||
| @@ -660,8 +668,8 @@ jobs: | ||||
|         if: needs.build-type-determination.outputs.publish-to-s3 == 'true' | ||||
|         uses: aws-actions/configure-aws-credentials@v4 | ||||
|         with: | ||||
|           role-to-assume: ${{ secrets.AWS_ROLE_ARN }}  | ||||
|           aws-region: us-east-1  | ||||
|           role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | ||||
|           aws-region: us-east-1 | ||||
|  | ||||
|       - name: Publish Release [S3] | ||||
|         if: needs.build-type-determination.outputs.publish-to-s3 == 'true' | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/check-containers.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/check-containers.yml
									
									
									
									
										vendored
									
									
								
							| @@ -40,7 +40,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Build and push to local registry | ||||
|         uses: docker/build-push-action@v6 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/check-i18n-task.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/check-i18n-task.yml
									
									
									
									
										vendored
									
									
								
							| @@ -56,7 +56,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Install Node.js 18.17 | ||||
|         uses: actions/setup-node@v4 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/check-javascript.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/check-javascript.yml
									
									
									
									
										vendored
									
									
								
							| @@ -65,7 +65,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Setup Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/check-yarn.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/check-yarn.yml
									
									
									
									
										vendored
									
									
								
							| @@ -64,7 +64,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Setup Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
|   | ||||
							
								
								
									
										8
									
								
								.github/workflows/compose-full-changelog.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/compose-full-changelog.yml
									
									
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ jobs: | ||||
|        | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Install Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
| @@ -29,6 +29,12 @@ jobs: | ||||
|           node-version: ${{ env.NODE_VERSION }} | ||||
|           registry-url: 'https://registry.npmjs.org' | ||||
|  | ||||
|       - name: Install Dependencies (Linux only) | ||||
|         if: runner.os == 'Linux' | ||||
|         run: | | ||||
|           sudo apt-get update | ||||
|           sudo apt-get install -y libx11-dev libxkbfile-dev libsecret-1-dev | ||||
|  | ||||
|       - name: Get Tag | ||||
|         id: tag_name | ||||
|         run: | | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/i18n-nightly-push.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/i18n-nightly-push.yml
									
									
									
									
										vendored
									
									
								
							| @@ -14,7 +14,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Install Node.js 18.17 | ||||
|         uses: actions/setup-node@v4 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/i18n-weekly-pull.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/i18n-weekly-pull.yml
									
									
									
									
										vendored
									
									
								
							| @@ -14,7 +14,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Install Node.js 18.17 | ||||
|         uses: actions/setup-node@v4 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/push-container-images.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/push-container-images.yml
									
									
									
									
										vendored
									
									
								
							| @@ -43,7 +43,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Log in to the Container registry | ||||
|         uses: docker/login-action@v3 | ||||
|   | ||||
							
								
								
									
										6
									
								
								.github/workflows/sync-labels.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/sync-labels.yml
									
									
									
									
										vendored
									
									
								
							| @@ -27,7 +27,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Download JSON schema for labels configuration file | ||||
|         id: download-schema | ||||
| @@ -106,10 +106,10 @@ jobs: | ||||
|           echo "flag=--dry-run" >> $GITHUB_OUTPUT | ||||
|  | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Download configuration file artifacts | ||||
|         uses: actions/download-artifact@v4 | ||||
|         uses: actions/download-artifact@v5 | ||||
|         with: | ||||
|           merge-multiple: true | ||||
|           pattern: ${{ env.CONFIGURATIONS_ARTIFACT_PREFIX }}* | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/workflows/test-javascript.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/test-javascript.yml
									
									
									
									
										vendored
									
									
								
							| @@ -82,7 +82,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Setup Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
| @@ -92,7 +92,7 @@ jobs: | ||||
|  | ||||
|       # See: https://github.com/eclipse-theia/theia/blob/master/doc/Developing.md#prerequisites | ||||
|       - name: Install Python | ||||
|         uses: actions/setup-python@v5 | ||||
|         uses: actions/setup-python@v6 | ||||
|         with: | ||||
|           python-version: '3.11.x' | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/themes-weekly-pull.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/themes-weekly-pull.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,7 +16,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         uses: actions/checkout@v5 | ||||
|  | ||||
|       - name: Install Node.js | ||||
|         uses: actions/setup-node@v4 | ||||
|   | ||||
							
								
								
									
										31
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							| @@ -80,37 +80,6 @@ | ||||
|       "port": 9222, | ||||
|       "webRoot": "${workspaceFolder}/electron-app" | ||||
|     }, | ||||
|     { | ||||
|       "type": "node", | ||||
|       "request": "launch", | ||||
|       "name": "App (Browser)", | ||||
|       "program": "${workspaceRoot}/browser-app/src-gen/backend/main.js", | ||||
|       "args": [ | ||||
|         "--hostname=0.0.0.0", | ||||
|         "--port=3000", | ||||
|         "--no-cluster", | ||||
|         "--no-app-auto-install", | ||||
|         "--plugins=local-dir:plugins" | ||||
|       ], | ||||
|       "windows": { | ||||
|         "env": { | ||||
|           "NODE_ENV": "development", | ||||
|           "NODE_PRESERVE_SYMLINKS": "1" | ||||
|         } | ||||
|       }, | ||||
|       "env": { | ||||
|         "NODE_ENV": "development" | ||||
|       }, | ||||
|       "sourceMaps": true, | ||||
|       "outFiles": [ | ||||
|         "${workspaceRoot}/browser-app/src-gen/backend/*.js", | ||||
|         "${workspaceRoot}/browser-app/lib/**/*.js", | ||||
|         "${workspaceRoot}/arduino-ide-extension/lib/**/*.js" | ||||
|       ], | ||||
|       "smartStep": true, | ||||
|       "internalConsoleOptions": "openOnSessionStart", | ||||
|       "outputCapture": "std" | ||||
|     },     | ||||
|     { | ||||
|       "type": "node", | ||||
|       "request": "launch", | ||||
|   | ||||
							
								
								
									
										30
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							| @@ -15,17 +15,6 @@ | ||||
|         "clear": false | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "label": "Arduino IDE - Start Browser App", | ||||
|       "type": "shell", | ||||
|       "command": "yarn --cwd ./browser-app start", | ||||
|       "group": "build", | ||||
|       "presentation": { | ||||
|         "reveal": "always", | ||||
|         "panel": "new", | ||||
|         "clear": true | ||||
|       } | ||||
|     },     | ||||
|     { | ||||
|       "label": "Watch Extension", | ||||
|       "type": "shell", | ||||
| @@ -37,17 +26,6 @@ | ||||
|         "clear": false | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "label": "Arduino IDE - Watch Browser App", | ||||
|       "type": "shell", | ||||
|       "command": "yarn --cwd ./browser-app watch", | ||||
|       "group": "build", | ||||
|       "presentation": { | ||||
|         "reveal": "always", | ||||
|         "panel": "new", | ||||
|         "clear": false | ||||
|       } | ||||
|     },     | ||||
|     { | ||||
|       "label": "Watch App", | ||||
|       "type": "shell", | ||||
| @@ -59,14 +37,6 @@ | ||||
|         "clear": false | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "label": "Arduino IDE - Watch All [Browser]", | ||||
|       "type": "shell", | ||||
|       "dependsOn": [ | ||||
|         "Arduino IDE - Watch IDE Extension", | ||||
|         "Arduino IDE - Watch Browser App" | ||||
|       ] | ||||
|     },     | ||||
|     { | ||||
|       "label": "Watch All", | ||||
|       "type": "shell", | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "arduino-ide-extension", | ||||
|   "version": "2.3.5", | ||||
|   "version": "2.3.7", | ||||
|   "description": "An extension for Theia building the Arduino IDE", | ||||
|   "license": "AGPL-3.0-or-later", | ||||
|   "scripts": { | ||||
| @@ -24,28 +24,29 @@ | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@grpc/grpc-js": "^1.8.14", | ||||
|     "@theia/application-package": "1.41.0", | ||||
|     "@theia/core": "1.41.0", | ||||
|     "@theia/debug": "1.41.0", | ||||
|     "@theia/editor": "1.41.0", | ||||
|     "@theia/electron": "1.41.0", | ||||
|     "@theia/filesystem": "1.41.0", | ||||
|     "@theia/keymaps": "1.41.0", | ||||
|     "@theia/markers": "1.41.0", | ||||
|     "@theia/messages": "1.41.0", | ||||
|     "@theia/monaco": "1.41.0", | ||||
|     "@theia/monaco-editor-core": "1.72.3", | ||||
|     "@theia/navigator": "1.41.0", | ||||
|     "@theia/outline-view": "1.41.0", | ||||
|     "@theia/output": "1.41.0", | ||||
|     "@theia/plugin-ext": "1.41.0", | ||||
|     "@theia/plugin-ext-vscode": "1.41.0", | ||||
|     "@theia/preferences": "1.41.0", | ||||
|     "@theia/scm": "1.41.0", | ||||
|     "@theia/search-in-workspace": "1.41.0", | ||||
|     "@theia/terminal": "1.41.0", | ||||
|     "@theia/typehierarchy": "1.41.0", | ||||
|     "@theia/workspace": "1.41.0", | ||||
|     "@theia/application-package": "1.57.0", | ||||
|     "@theia/core": "1.57.0", | ||||
|     "@theia/debug": "1.57.0", | ||||
|     "@theia/editor": "1.57.0", | ||||
|     "@theia/electron": "1.57.0", | ||||
|     "@theia/filesystem": "1.57.0", | ||||
|     "@theia/keymaps": "1.57.0", | ||||
|     "@theia/markers": "1.57.0", | ||||
|     "@theia/messages": "1.57.0", | ||||
|     "@theia/monaco": "1.57.0", | ||||
|     "@theia/monaco-editor-core": "1.83.101", | ||||
|     "@theia/navigator": "1.57.0", | ||||
|     "@theia/outline-view": "1.57.0", | ||||
|     "@theia/output": "1.57.0", | ||||
|     "@theia/plugin-ext": "1.57.0", | ||||
|     "@theia/plugin-ext-vscode": "1.57.0", | ||||
|     "@theia/preferences": "1.57.0", | ||||
|     "@theia/scm": "1.57.0", | ||||
|     "@theia/search-in-workspace": "1.57.0", | ||||
|     "@theia/terminal": "1.57.0", | ||||
|     "@theia/test": "1.57.0", | ||||
|     "@theia/typehierarchy": "1.57.0", | ||||
|     "@theia/workspace": "1.57.0", | ||||
|     "@tippyjs/react": "^4.2.5", | ||||
|     "@types/auth0-js": "^9.21.3", | ||||
|     "@types/btoa": "^1.2.3", | ||||
| @@ -57,7 +58,6 @@ | ||||
|     "@types/node-fetch": "^2.5.7", | ||||
|     "@types/p-queue": "^2.3.1", | ||||
|     "@types/ps-tree": "^1.1.0", | ||||
|     "@types/react-tabs": "^2.3.2", | ||||
|     "@types/temp": "^0.8.34", | ||||
|     "arduino-serial-plotter-webapp": "0.2.0", | ||||
|     "async-mutex": "^0.3.0", | ||||
| @@ -99,7 +99,7 @@ | ||||
|     "react-markdown": "^8.0.0", | ||||
|     "react-perfect-scrollbar": "^1.5.8", | ||||
|     "react-select": "^5.6.0", | ||||
|     "react-tabs": "^3.1.2", | ||||
|     "react-tabs": "^6.1.0", | ||||
|     "react-window": "^1.8.6", | ||||
|     "semver": "^7.3.2", | ||||
|     "string-natural-compare": "^2.0.3", | ||||
| @@ -126,7 +126,7 @@ | ||||
|     "mockdate": "^3.0.5", | ||||
|     "moment": "^2.24.0", | ||||
|     "ncp": "^2.0.0", | ||||
|     "rimraf": "^2.6.1" | ||||
|     "rimraf": "^5.0.0" | ||||
|   }, | ||||
|   "optionalDependencies": { | ||||
|     "@pingghost/protoc": "^1.0.2", | ||||
| @@ -158,13 +158,21 @@ | ||||
|       "frontend": "lib/browser/arduino-ide-frontend-module" | ||||
|     }, | ||||
|     { | ||||
|       "frontend": "lib/browser/theia/core/browser-menu-module", | ||||
|       "frontendElectron": "lib/electron-browser/theia/core/electron-menu-module" | ||||
|     }, | ||||
|     { | ||||
|       "frontendElectron": "lib/electron-browser/theia/core/electron-window-module" | ||||
|     }, | ||||
|     { | ||||
|       "frontendElectron": "lib/electron-browser/electron-arduino-module" | ||||
|     }, | ||||
|     { | ||||
|       "electronMain": "lib/electron-main/arduino-electron-main-module" | ||||
|     } | ||||
|   ], | ||||
|   "arduino": { | ||||
|     "arduino-cli": { | ||||
|       "version": "1.1.1" | ||||
|       "version": "1.2.0" | ||||
|     }, | ||||
|     "arduino-fwuploader": { | ||||
|       "version": "2.4.1" | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; | ||||
| import { ColorRegistry } from '@theia/core/lib/browser/color-registry'; | ||||
| import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; | ||||
| import { | ||||
|   TabBarToolbarContribution, | ||||
|   TabBarToolbarRegistry, | ||||
| @@ -23,6 +24,7 @@ import { | ||||
| import { MessageService } from '@theia/core/lib/common/message-service'; | ||||
| import { nls } from '@theia/core/lib/common/nls'; | ||||
| import { isHighContrast } from '@theia/core/lib/common/theme'; | ||||
| import { ElectronWindowPreferences } from '@theia/core/lib/electron-browser/window/electron-window-preferences'; | ||||
| import { | ||||
|   inject, | ||||
|   injectable, | ||||
| @@ -60,11 +62,11 @@ export class ArduinoFrontendContribution | ||||
|   @inject(CommandRegistry) | ||||
|   private readonly commandRegistry: CommandRegistry; | ||||
|  | ||||
|   // @inject(ElectronWindowPreferences) | ||||
|   // private readonly electronWindowPreferences: ElectronWindowPreferences; | ||||
|   @inject(ElectronWindowPreferences) | ||||
|   private readonly electronWindowPreferences: ElectronWindowPreferences; | ||||
|  | ||||
|   // @inject(FrontendApplicationStateService) | ||||
|   // private readonly appStateService: FrontendApplicationStateService; | ||||
|   @inject(FrontendApplicationStateService) | ||||
|   private readonly appStateService: FrontendApplicationStateService; | ||||
|  | ||||
|   @postConstruct() | ||||
|   protected init(): void { | ||||
| @@ -80,24 +82,24 @@ export class ArduinoFrontendContribution | ||||
|   } | ||||
|  | ||||
|   onStart(): void { | ||||
|     // this.electronWindowPreferences.onPreferenceChanged((event) => { | ||||
|     //   if (event.newValue !== event.oldValue) { | ||||
|     //     switch (event.preferenceName) { | ||||
|     //       case 'window.zoomLevel': | ||||
|     //         if (typeof event.newValue === 'number') { | ||||
|     //           window.electronTheiaCore.setZoomLevel(event.newValue || 0); | ||||
|     //         } | ||||
|     //         break; | ||||
|     //     } | ||||
|     //   } | ||||
|     // }); | ||||
|     // this.appStateService.reachedState('ready').then(() => | ||||
|     //   this.electronWindowPreferences.ready.then(() => { | ||||
|     //     const zoomLevel = | ||||
|     //       this.electronWindowPreferences.get('window.zoomLevel'); | ||||
|     //     window.electronTheiaCore.setZoomLevel(zoomLevel); | ||||
|     //   }) | ||||
|     // ); | ||||
|     this.electronWindowPreferences.onPreferenceChanged((event) => { | ||||
|       if (event.newValue !== event.oldValue) { | ||||
|         switch (event.preferenceName) { | ||||
|           case 'window.zoomLevel': | ||||
|             if (typeof event.newValue === 'number') { | ||||
|               window.electronTheiaCore.setZoomLevel(event.newValue || 0); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|     this.appStateService.reachedState('ready').then(() => | ||||
|       this.electronWindowPreferences.ready.then(() => { | ||||
|         const zoomLevel = | ||||
|           this.electronWindowPreferences.get('window.zoomLevel'); | ||||
|         window.electronTheiaCore.setZoomLevel(zoomLevel); | ||||
|       }) | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   registerToolbarItems(registry: TabBarToolbarRegistry): void { | ||||
|   | ||||
| @@ -1,18 +1,12 @@ | ||||
| import '../../src/browser/style/index.css'; | ||||
| import { | ||||
|   Container, | ||||
|   ContainerModule, | ||||
|   interfaces, | ||||
| } from '@theia/core/shared/inversify'; | ||||
| import { Container, ContainerModule } from '@theia/core/shared/inversify'; | ||||
| import { WidgetFactory } from '@theia/core/lib/browser/widget-manager'; | ||||
| import { CommandContribution } from '@theia/core/lib/common/command'; | ||||
| import { bindViewContribution } from '@theia/core/lib/browser/shell/view-contribution'; | ||||
| import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; | ||||
| import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging/ws-connection-provider'; | ||||
| import { | ||||
|   FrontendApplicationContribution, | ||||
|   FrontendApplication as TheiaFrontendApplication, | ||||
| } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplication as TheiaFrontendApplication } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { LibraryListWidget } from './library/library-list-widget'; | ||||
| import { ArduinoFrontendContribution } from './arduino-frontend-contribution'; | ||||
| import { | ||||
| @@ -57,8 +51,6 @@ import { | ||||
|   DockPanelRenderer as TheiaDockPanelRenderer, | ||||
|   TabBarRendererFactory, | ||||
|   ContextMenuRenderer, | ||||
|   createTreeContainer, | ||||
|   TreeWidget, | ||||
| } from '@theia/core/lib/browser'; | ||||
| import { MenuContribution } from '@theia/core/lib/common/menu'; | ||||
| import { | ||||
| @@ -97,7 +89,6 @@ import { | ||||
|   ArduinoDaemonPath, | ||||
|   ArduinoDaemon, | ||||
| } from '../common/protocol/arduino-daemon'; | ||||
| import { EditorCommandContribution as TheiaEditorCommandContribution } from '@theia/editor/lib/browser'; | ||||
| import { | ||||
|   FrontendConnectionStatusService, | ||||
|   ApplicationConnectionStatusContribution, | ||||
| @@ -186,7 +177,6 @@ import { | ||||
| import { About } from './contributions/about'; | ||||
| import { IconThemeService } from '@theia/core/lib/browser/icon-theme-service'; | ||||
| import { TabBarRenderer } from './theia/core/tab-bars'; | ||||
| import { EditorCommandContribution } from './theia/editor/editor-command'; | ||||
| import { NavigatorTabBarDecorator as TheiaNavigatorTabBarDecorator } from '@theia/navigator/lib/browser/navigator-tab-bar-decorator'; | ||||
| import { NavigatorTabBarDecorator } from './theia/navigator/navigator-tab-bar-decorator'; | ||||
| import { Debug, DebugDisabledStatusMessageSource } from './contributions/debug'; | ||||
| @@ -265,12 +255,17 @@ import { | ||||
| } from './dialogs/user-fields/user-fields-dialog'; | ||||
| import { nls } from '@theia/core/lib/common'; | ||||
| import { IDEUpdaterCommands } from './ide-updater/ide-updater-commands'; | ||||
| import { IDEUpdater, IDEUpdaterClient } from '../common/protocol/ide-updater'; | ||||
| import { | ||||
|   IDEUpdater, | ||||
|   IDEUpdaterClient, | ||||
|   IDEUpdaterPath, | ||||
| } from '../common/protocol/ide-updater'; | ||||
| import { IDEUpdaterClientImpl } from './ide-updater/ide-updater-client-impl'; | ||||
| import { | ||||
|   IDEUpdaterDialog, | ||||
|   IDEUpdaterDialogProps, | ||||
| } from './dialogs/ide-updater/ide-updater-dialog'; | ||||
| import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-source'; | ||||
| import { MonitorModel } from './monitor-model'; | ||||
| import { MonitorManagerProxyClientImpl } from './monitor-manager-proxy-client-impl'; | ||||
| import { EditorManager as TheiaEditorManager } from '@theia/editor/lib/browser/editor-manager'; | ||||
| @@ -290,7 +285,6 @@ import { PreferenceTreeGenerator } from './theia/preferences/preference-tree-gen | ||||
| import { PreferenceTreeGenerator as TheiaPreferenceTreeGenerator } from '@theia/preferences/lib/browser/util/preference-tree-generator'; | ||||
| import { AboutDialog } from './theia/core/about-dialog'; | ||||
| import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog'; | ||||
| import { SurveyNotificationService } from '../common/protocol/survey-service'; | ||||
| import { WindowContribution } from './theia/core/window-contribution'; | ||||
| import { WindowContribution as TheiaWindowContribution } from '@theia/core/lib/browser/window-contribution'; | ||||
| import { CoreErrorHandler } from './contributions/core-error-handler'; | ||||
| @@ -373,21 +367,13 @@ import { DebugSessionWidget } from '@theia/debug/lib/browser/view/debug-session- | ||||
| import { DebugConfigurationWidget } from './theia/debug/debug-configuration-widget'; | ||||
| import { DebugConfigurationWidget as TheiaDebugConfigurationWidget } from '@theia/debug/lib/browser/view/debug-configuration-widget'; | ||||
| import { DebugToolBar } from '@theia/debug/lib/browser/view/debug-toolbar-widget'; | ||||
| import { | ||||
|   PluginTree, | ||||
|   PluginTreeModel, | ||||
|   TreeViewWidgetOptions, | ||||
|   VIEW_ITEM_CONTEXT_MENU, | ||||
| } from '@theia/plugin-ext/lib/main/browser/view/tree-view-widget'; | ||||
| import { TreeViewDecoratorService } from '@theia/plugin-ext/lib/main/browser/view/tree-view-decorator-service'; | ||||
| import { PLUGIN_VIEW_DATA_FACTORY_ID } from '@theia/plugin-ext/lib/main/browser/view/plugin-view-registry'; | ||||
| import { TreeViewWidget } from './theia/plugin-ext/tree-view-widget'; | ||||
|  | ||||
| import { | ||||
|   VersionWelcomeDialog, | ||||
|   VersionWelcomeDialogProps, | ||||
| } from './dialogs/version-welcome-dialog'; | ||||
| import { DialogService } from './dialog-service'; | ||||
| import { AppInfo, AppService } from './app-service'; | ||||
| import { TestViewContribution as TheiaTestViewContribution } from '@theia/test/lib/browser/view/test-view-contribution'; | ||||
| import { TestViewContribution } from './theia/test/test-view-contribution'; | ||||
|  | ||||
| // Hack to fix copy/cut/paste issue after electron version update in Theia. | ||||
| // https://github.com/eclipse-theia/theia/issues/12487 | ||||
| @@ -568,16 +554,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|     WorkspaceVariableContribution | ||||
|   ); | ||||
|  | ||||
|   bind(SurveyNotificationService).toConstantValue( | ||||
|     {} as SurveyNotificationService | ||||
|   ); | ||||
|   //   return ElectronIpcConnectionProvider.createProxy( | ||||
|   //     context.container, | ||||
|   //     SurveyNotificationServicePath | ||||
|   //   ); | ||||
|   // }) | ||||
|   // .inSingletonScope(); | ||||
|  | ||||
|   // Layout and shell customizations. | ||||
|   rebind(TheiaOutlineViewContribution) | ||||
|     .to(OutlineViewContribution) | ||||
| @@ -851,13 +827,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
|   // Workaround for https://github.com/eclipse-theia/theia/issues/8722 | ||||
|   // Do not trigger a save on IDE startup if `"editor.autoSave": "on"` was set as a preference. | ||||
|   // Note: `"editor.autoSave" was renamed to `"files.autoSave" and `"on"` was replaced with three | ||||
|   // different cases, but we treat `!== 'off'` as auto save enabled. (https://github.com/eclipse-theia/theia/issues/10812) | ||||
|   bind(EditorCommandContribution).toSelf().inSingletonScope(); | ||||
|   rebind(TheiaEditorCommandContribution).toService(EditorCommandContribution); | ||||
|  | ||||
|   // Silent the badge decoration in the Explorer view. | ||||
|   bind(NavigatorTabBarDecorator).toSelf().inSingletonScope(); | ||||
|   rebind(TheiaNavigatorTabBarDecorator).toService(NavigatorTabBarDecorator); | ||||
| @@ -1034,16 +1003,16 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|   // Frontend binding for the IDE Updater service | ||||
|   bind(IDEUpdaterClientImpl).toSelf().inSingletonScope(); | ||||
|   bind(IDEUpdaterClient).toService(IDEUpdaterClientImpl); | ||||
|   bind(IDEUpdater).toConstantValue({} as IDEUpdater); | ||||
|   // .toDynamicValue((context) => { | ||||
|   //   const client = context.container.get(IDEUpdaterClientImpl); | ||||
|   //   return ElectronIpcConnectionProvider.createProxy( | ||||
|   //     context.container, | ||||
|   //     IDEUpdaterPath, | ||||
|   //     client | ||||
|   //   ); | ||||
|   // }) | ||||
|   // .inSingletonScope(); | ||||
|   bind(IDEUpdater) | ||||
|     .toDynamicValue((context) => { | ||||
|       const client = context.container.get(IDEUpdaterClientImpl); | ||||
|       return ElectronIpcConnectionProvider.createProxy( | ||||
|         context.container, | ||||
|         IDEUpdaterPath, | ||||
|         client | ||||
|       ); | ||||
|     }) | ||||
|     .inSingletonScope(); | ||||
|  | ||||
|   bind(HostedPluginSupportImpl).toSelf().inSingletonScope(); | ||||
|   bind(HostedPluginSupport).toService(HostedPluginSupportImpl); | ||||
| @@ -1107,68 +1076,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|     TerminalFrontendContribution | ||||
|   ); | ||||
|  | ||||
|   bindViewsWelcome_TheiaGH14309({ bind, widget: TreeViewWidget }); | ||||
|  | ||||
|   bind(DialogService).toConstantValue(<DialogService>{}); | ||||
|   bind(AppService).toConstantValue(<AppService>{ | ||||
|     quit() { | ||||
|       console.log('Quitting application...'); | ||||
|       // Implement quit logic here | ||||
|     }, | ||||
|     async info() { | ||||
|       return { | ||||
|         name: 'MyApp', | ||||
|         version: '1.0.0', | ||||
|         description: 'An example application', | ||||
|         appVersion: '1.0.0', | ||||
|         cliVersion: '1.0.0', | ||||
|         buildDate: new Date().toISOString(), | ||||
|       } as AppInfo; | ||||
|     }, | ||||
|     registerStartupTasksHandler(_) { | ||||
|       console.log('registerStartupTasksHandler', _); | ||||
|       return { dispose: () => {} }; | ||||
|     }, | ||||
|     scheduleDeletion(_) { | ||||
|       console.log(`Scheduled deletion for sketch}`, _); | ||||
|       // Implement deletion logic | ||||
|     }, | ||||
|   }); | ||||
|   // Hides the Test Explorer from the side-bar | ||||
|   bind(TestViewContribution).toSelf().inSingletonScope(); | ||||
|   rebind(TheiaTestViewContribution).toService(TestViewContribution); | ||||
| }); | ||||
|  | ||||
| // Align the viewsWelcome rendering with VS Code (https://github.com/eclipse-theia/theia/issues/14309) | ||||
| // Copied from Theia code but with customized TreeViewWidget with the customized viewsWelcome rendering | ||||
| // https://github.com/eclipse-theia/theia/blob/0c5f69455d9ee355b1a7ca510ffa63d2b20f0c77/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts#L159-L181 | ||||
| function bindViewsWelcome_TheiaGH14309({ | ||||
|   bind, | ||||
|   widget, | ||||
| }: { | ||||
|   bind: interfaces.Bind; | ||||
|   widget: interfaces.Newable<TreeWidget>; | ||||
| }) { | ||||
|   bind(WidgetFactory) | ||||
|     .toDynamicValue(({ container }) => ({ | ||||
|       id: PLUGIN_VIEW_DATA_FACTORY_ID, | ||||
|       createWidget: (options: TreeViewWidgetOptions) => { | ||||
|         const props = { | ||||
|           contextMenuPath: VIEW_ITEM_CONTEXT_MENU, | ||||
|           expandOnlyOnExpansionToggleClick: true, | ||||
|           expansionTogglePadding: 22, | ||||
|           globalSelection: true, | ||||
|           leftPadding: 8, | ||||
|           search: true, | ||||
|           multiSelect: options.multiSelect, | ||||
|         }; | ||||
|         const child = createTreeContainer(container, { | ||||
|           props, | ||||
|           tree: PluginTree, | ||||
|           model: PluginTreeModel, | ||||
|           widget, | ||||
|           decoratorService: TreeViewDecoratorService, | ||||
|         }); | ||||
|         child.bind(TreeViewWidgetOptions).toConstantValue(options); | ||||
|         return child.get(TreeWidget); | ||||
|       }, | ||||
|     })) | ||||
|     .inSingletonScope(); | ||||
| } | ||||
|   | ||||
| @@ -280,14 +280,6 @@ const properties: ArduinoPreferenceSchemaProperties = { | ||||
|     ), | ||||
|     default: 'https://auth.arduino.cc/login#/register', | ||||
|   }, | ||||
|   'arduino.survey.notification': { | ||||
|     type: 'boolean', | ||||
|     description: nls.localize( | ||||
|       'arduino/preferences/survey.notification', | ||||
|       'True if users should be notified if a survey is available. True by default.' | ||||
|     ), | ||||
|     default: true, | ||||
|   }, | ||||
|   'arduino.cli.daemon.debug': { | ||||
|     type: 'boolean', | ||||
|     description: nls.localize( | ||||
| @@ -355,7 +347,6 @@ export interface ArduinoConfiguration { | ||||
|   'arduino.auth.domain': string; | ||||
|   'arduino.auth.audience': string; | ||||
|   'arduino.auth.registerUri': string; | ||||
|   'arduino.survey.notification': boolean; | ||||
|   'arduino.cli.daemon.debug': boolean; | ||||
|   'arduino.sketch.inoBlueprint': string; | ||||
|   'arduino.checkForUpdates': boolean; | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import { Emitter } from '@theia/core/lib/common/event'; | ||||
| import { JsonRpcProxy } from '@theia/core/lib/common/messaging/proxy-factory'; | ||||
| import { WindowService } from '@theia/core/lib/browser/window/window-service'; | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { | ||||
|   CommandRegistry, | ||||
|   CommandContribution, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { MessageService } from '@theia/core/lib/common/message-service'; | ||||
| import { MessageType } from '@theia/core/lib/common/message-service-protocol'; | ||||
|   | ||||
| @@ -98,6 +98,7 @@ export class BoardsConfigDialog extends ReactDialog<BoardsConfigDialogState> { | ||||
|   } | ||||
|  | ||||
|   override async open( | ||||
|     disposeOnResolve = true, | ||||
|     params?: EditBoardsConfigActionParams | ||||
|   ): Promise<BoardsConfig | undefined> { | ||||
|     this._searchSet = undefined; | ||||
| @@ -119,7 +120,7 @@ export class BoardsConfigDialog extends ReactDialog<BoardsConfigDialogState> { | ||||
|         this._searchSet = params.searchSet.slice(); | ||||
|       } | ||||
|     } | ||||
|     return super.open(); | ||||
|     return super.open(disposeOnResolve); | ||||
|   } | ||||
|  | ||||
|   protected override onAfterAttach(msg: Message): void { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; | ||||
| import { StorageService } from '@theia/core/lib/browser/storage-service'; | ||||
| import type { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; | ||||
| import { StorageService } from '@theia/core/lib/browser/storage-service'; | ||||
| import { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { Emitter, Event } from '@theia/core/lib/common/event'; | ||||
|   | ||||
| @@ -70,7 +70,7 @@ export class CheckForIDEUpdates extends Contribution { | ||||
|           SKIP_IDE_VERSION | ||||
|         ); | ||||
|         if (versionToSkip === updateInfo.version) return; | ||||
|         this.updaterDialog.open(updateInfo); | ||||
|         this.updaterDialog.open(true, updateInfo); | ||||
|       }) | ||||
|       .catch((e) => { | ||||
|         this.messageService.error( | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import { Installable } from '../../common/protocol/installable'; | ||||
| import { ExecuteWithProgress } from '../../common/protocol/progressible'; | ||||
| import { BoardsListWidgetFrontendContribution } from '../boards/boards-widget-frontend-contribution'; | ||||
| import { LibraryListWidgetFrontendContribution } from '../library/library-widget-frontend-contribution'; | ||||
| import { WindowServiceExt } from '../theia/core/window-service-ext'; | ||||
| import type { ListWidget } from '../widgets/component-list/list-widget'; | ||||
| import { Command, CommandRegistry, Contribution } from './contribution'; | ||||
|  | ||||
| @@ -52,8 +53,8 @@ const Updatable = { type: 'Updatable' } as const; | ||||
|  | ||||
| @injectable() | ||||
| export class CheckForUpdates extends Contribution { | ||||
|   // @inject(WindowServiceExt) | ||||
|   // private readonly windowService: WindowServiceExt; | ||||
|   @inject(WindowServiceExt) | ||||
|   private readonly windowService: WindowServiceExt; | ||||
|   @inject(ResponseServiceClient) | ||||
|   private readonly responseService: ResponseServiceClient; | ||||
|   @inject(BoardsService) | ||||
| @@ -71,16 +72,16 @@ export class CheckForUpdates extends Contribution { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   // override async onReady(): Promise<void> { | ||||
|   //   const checkForUpdates = this.preferences['arduino.checkForUpdates']; | ||||
|   //   if (checkForUpdates) { | ||||
|   //     this.windowService.isFirstWindow().then((firstWindow) => { | ||||
|   //       if (firstWindow) { | ||||
|   //         this.checkForUpdates(); | ||||
|   //       } | ||||
|   //     }); | ||||
|   //   } | ||||
|   // } | ||||
|   override async onReady(): Promise<void> { | ||||
|     const checkForUpdates = this.preferences['arduino.checkForUpdates']; | ||||
|     if (checkForUpdates) { | ||||
|       this.windowService.isFirstWindow().then((firstWindow) => { | ||||
|         if (firstWindow) { | ||||
|           this.checkForUpdates(); | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private async checkForUpdates(silent = true) { | ||||
|     const [boardsPackages, libraryPackages] = await Promise.all([ | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| import { Dialog } from '@theia/core/lib/browser/dialogs'; | ||||
| import type { | ||||
|   FrontendApplication, | ||||
|   OnWillStopAction, | ||||
| } from '@theia/core/lib/browser/frontend-application'; | ||||
| import type { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; | ||||
| import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell'; | ||||
| import { nls } from '@theia/core/lib/common/nls'; | ||||
| import type { MaybePromise } from '@theia/core/lib/common/types'; | ||||
| import { toArray } from '@theia/core/shared/@phosphor/algorithm'; | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor'; | ||||
| import { ArduinoMenus } from '../menu/arduino-menus'; | ||||
| import { CurrentSketch } from '../sketches-service-client-impl'; | ||||
| import { WindowServiceExt } from '../theia/core/window-service-ext'; | ||||
| import { | ||||
|   Command, | ||||
|   CommandRegistry, | ||||
| @@ -27,8 +26,8 @@ import { SaveAsSketch } from './save-as-sketch'; | ||||
|  */ | ||||
| @injectable() | ||||
| export class Close extends SketchContribution { | ||||
|   // @inject(WindowServiceExt) | ||||
|   // private readonly windowServiceExt: WindowServiceExt; | ||||
|   @inject(WindowServiceExt) | ||||
|   private readonly windowServiceExt: WindowServiceExt; | ||||
|  | ||||
|   private shell: ApplicationShell | undefined; | ||||
|  | ||||
| @@ -58,7 +57,7 @@ export class Close extends SketchContribution { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         // return this.windowServiceExt.close(); | ||||
|         return this.windowServiceExt.close(); | ||||
|       }, | ||||
|     }); | ||||
|   } | ||||
|   | ||||
| @@ -779,7 +779,7 @@ export class CompilerErrors | ||||
|       return undefined; | ||||
|     } else { | ||||
|       return this.editorManager | ||||
|         .getByUri(new URI(uriOrWidget)) | ||||
|         .getByUri(new URI(uriOrWidget.toString())) | ||||
|         .then((editor) => { | ||||
|           if (editor) { | ||||
|             return this.monacoEditor(editor); | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| import { ClipboardService } from '@theia/core/lib/browser/clipboard-service'; | ||||
| import { | ||||
|   FrontendApplication, | ||||
|   FrontendApplicationContribution, | ||||
| } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; | ||||
| import { | ||||
|   KeybindingContribution, | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| import { nls } from '@theia/core/lib/common'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution'; | ||||
| import { ClipboardService } from '@theia/core/lib/browser/clipboard-service'; | ||||
| import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service'; | ||||
| import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices'; | ||||
| import { ICodeEditorService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/codeEditorService'; | ||||
| import type { ICodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser'; | ||||
| import type { StandaloneCodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; | ||||
| import { | ||||
|   Contribution, | ||||
|   Command, | ||||
| @@ -10,17 +14,11 @@ import { | ||||
|   CommandRegistry, | ||||
| } from './contribution'; | ||||
| import { ArduinoMenus } from '../menu/arduino-menus'; | ||||
| import { nls } from '@theia/core/lib/common'; | ||||
| import type { ICodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser'; | ||||
| import type { StandaloneCodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor'; | ||||
|  | ||||
| // TODO: [macOS]: to remove `Start Dictation...` and `Emoji & Symbol` see this thread: https://github.com/electron/electron/issues/8283#issuecomment-269522072 | ||||
| // Depends on https://github.com/eclipse-theia/theia/pull/7964 | ||||
| @injectable() | ||||
| export class EditContributions extends Contribution { | ||||
|   @inject(MonacoEditorService) | ||||
|   private readonly codeEditorService: MonacoEditorService; | ||||
|  | ||||
|   @inject(ClipboardService) | ||||
|   private readonly clipboardService: ClipboardService; | ||||
|  | ||||
| @@ -208,9 +206,10 @@ ${value} | ||||
|   protected async current(): Promise< | ||||
|     ICodeEditor | StandaloneCodeEditor | undefined | ||||
|   > { | ||||
|     const codeEditorService = StandaloneServices.get(ICodeEditorService); | ||||
|     return ( | ||||
|       this.codeEditorService.getFocusedCodeEditor() || | ||||
|       this.codeEditorService.getActiveCodeEditor() || | ||||
|       codeEditorService.getFocusedCodeEditor() || | ||||
|       codeEditorService.getActiveCodeEditor() || | ||||
|       undefined | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -12,7 +12,7 @@ export class OpenBoardsConfig extends Contribution { | ||||
|   override registerCommands(registry: CommandRegistry): void { | ||||
|     registry.registerCommand(OpenBoardsConfig.Commands.OPEN_DIALOG, { | ||||
|       execute: async (params?: EditBoardsConfigActionParams) => | ||||
|         this.boardsConfigDialog.open(params), | ||||
|         this.boardsConfigDialog.open(true, params), | ||||
|     }); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,78 +0,0 @@ | ||||
| import { MessageService } from '@theia/core'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { LocalStorageService } from '@theia/core/lib/browser'; | ||||
| import { nls } from '@theia/core/lib/common'; | ||||
| import { WindowService } from '@theia/core/lib/browser/window/window-service'; | ||||
| import { ArduinoPreferences } from '../arduino-preferences'; | ||||
| import { SurveyNotificationService } from '../../common/protocol/survey-service'; | ||||
|  | ||||
| const SURVEY_MESSAGE = nls.localize( | ||||
|   'arduino/survey/surveyMessage', | ||||
|   'Please help us improve by answering this super short survey. We value our community and would like to get to know our supporters a little better.' | ||||
| ); | ||||
| const DO_NOT_SHOW_AGAIN = nls.localize( | ||||
|   'arduino/survey/dismissSurvey', | ||||
|   "Don't show again" | ||||
| ); | ||||
| const GO_TO_SURVEY = nls.localize( | ||||
|   'arduino/survey/answerSurvey', | ||||
|   'Answer survey' | ||||
| ); | ||||
|  | ||||
| const SURVEY_BASE_URL = 'https://surveys.hotjar.com/'; | ||||
| const surveyId = '17887b40-e1f0-4bd6-b9f0-a37f229ccd8b'; | ||||
|  | ||||
| @injectable() | ||||
| export class SurveyNotification implements FrontendApplicationContribution { | ||||
|   @inject(MessageService) | ||||
|   private readonly messageService: MessageService; | ||||
|  | ||||
|   @inject(LocalStorageService) | ||||
|   private readonly localStorageService: LocalStorageService; | ||||
|  | ||||
|   @inject(WindowService) | ||||
|   private readonly windowService: WindowService; | ||||
|  | ||||
|   @inject(ArduinoPreferences) | ||||
|   private readonly arduinoPreferences: ArduinoPreferences; | ||||
|  | ||||
|   @inject(SurveyNotificationService) | ||||
|   private readonly surveyNotificationService: SurveyNotificationService; | ||||
|  | ||||
|   onStart(): void { | ||||
|     this.arduinoPreferences.ready.then(async () => { | ||||
|       if ( | ||||
|         (await this.surveyNotificationService.isFirstInstance()) && | ||||
|         this.arduinoPreferences.get('arduino.survey.notification') | ||||
|       ) { | ||||
|         const surveyAnswered = await this.localStorageService.getData( | ||||
|           this.surveyKey(surveyId) | ||||
|         ); | ||||
|         if (surveyAnswered !== undefined) { | ||||
|           return; | ||||
|         } | ||||
|         const answer = await this.messageService.info( | ||||
|           SURVEY_MESSAGE, | ||||
|           DO_NOT_SHOW_AGAIN, | ||||
|           GO_TO_SURVEY | ||||
|         ); | ||||
|         switch (answer) { | ||||
|           case GO_TO_SURVEY: | ||||
|             this.windowService.openNewWindow(SURVEY_BASE_URL + surveyId, { | ||||
|               external: true, | ||||
|             }); | ||||
|             this.localStorageService.setData(this.surveyKey(surveyId), true); | ||||
|             break; | ||||
|           case DO_NOT_SHOW_AGAIN: | ||||
|             this.localStorageService.setData(this.surveyKey(surveyId), false); | ||||
|             break; | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   private surveyKey(id: string): string { | ||||
|     return `answered_survey:${id}`; | ||||
|   } | ||||
| } | ||||
| @@ -3,12 +3,13 @@ import { nls } from '@theia/core/lib/common/nls'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { CoreService, IndexType } from '../../common/protocol'; | ||||
| import { NotificationCenter } from '../notification-center'; | ||||
| import { WindowServiceExt } from '../theia/core/window-service-ext'; | ||||
| import { Command, CommandRegistry, Contribution } from './contribution'; | ||||
|  | ||||
| @injectable() | ||||
| export class UpdateIndexes extends Contribution { | ||||
|   // @inject(WindowServiceExt) | ||||
|   // private readonly windowService: WindowServiceExt; | ||||
|   @inject(WindowServiceExt) | ||||
|   private readonly windowService: WindowServiceExt; | ||||
|   @inject(LocalStorageService) | ||||
|   private readonly localStorage: LocalStorageService; | ||||
|   @inject(CoreService) | ||||
| @@ -52,28 +53,30 @@ export class UpdateIndexes extends Contribution { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     const summary = await this.coreService.indexUpdateSummaryBeforeInit(); | ||||
|     if (summary.message) { | ||||
|       this.messageService.error(summary.message); | ||||
|     if (await this.windowService.isFirstWindow()) { | ||||
|       const summary = await this.coreService.indexUpdateSummaryBeforeInit(); | ||||
|       if (summary.message) { | ||||
|         this.messageService.error(summary.message); | ||||
|       } | ||||
|       const typesToCheck = IndexType.All.filter((type) => !(type in summary)); | ||||
|       if (Object.keys(summary).length) { | ||||
|         console.debug( | ||||
|           `[update-indexes]: Detected an index update summary before the core gRPC client initialization. Updating local storage with ${JSON.stringify( | ||||
|             summary | ||||
|           )}` | ||||
|         ); | ||||
|       } else { | ||||
|         console.debug( | ||||
|           '[update-indexes]: No index update summary was available before the core gRPC client initialization. Checking the status of the all the index types.' | ||||
|         ); | ||||
|       } | ||||
|       await Promise.allSettled([ | ||||
|         ...Object.entries(summary).map(([type, updatedAt]) => | ||||
|           this.setLastUpdateDateTime(type as IndexType, updatedAt) | ||||
|         ), | ||||
|         this.updateIndexes(typesToCheck), | ||||
|       ]); | ||||
|     } | ||||
|     const typesToCheck = IndexType.All.filter((type) => !(type in summary)); | ||||
|     if (Object.keys(summary).length) { | ||||
|       console.debug( | ||||
|         `[update-indexes]: Detected an index update summary before the core gRPC client initialization. Updating local storage with ${JSON.stringify( | ||||
|           summary | ||||
|         )}` | ||||
|       ); | ||||
|     } else { | ||||
|       console.debug( | ||||
|         '[update-indexes]: No index update summary was available before the core gRPC client initialization. Checking the status of the all the index types.' | ||||
|       ); | ||||
|     } | ||||
|     await Promise.allSettled([ | ||||
|       ...Object.entries(summary).map(([type, updatedAt]) => | ||||
|         this.setLastUpdateDateTime(type as IndexType, updatedAt) | ||||
|       ), | ||||
|       this.updateIndexes(typesToCheck), | ||||
|     ]); | ||||
|   } | ||||
|  | ||||
|   private async updateIndexes( | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { Emitter, Event } from '@theia/core/lib/common/event'; | ||||
| import URI from '@theia/core/lib/common/uri'; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import { | ||||
|   Disposable, | ||||
|   DisposableCollection, | ||||
| } from '@theia/core/lib/common/disposable'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { | ||||
|   Stat, | ||||
|   FileType, | ||||
|   | ||||
| @@ -261,6 +261,7 @@ export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> { | ||||
|   } | ||||
|  | ||||
|   override async open( | ||||
|     disposeOnResolve = true, | ||||
|     data: UpdateInfo | undefined = undefined | ||||
|   ): Promise<UpdateInfo | undefined> { | ||||
|     if (data && data.version) { | ||||
| @@ -271,7 +272,7 @@ export class IDEUpdaterDialog extends ReactDialog<UpdateInfo | undefined> { | ||||
|         error: undefined, | ||||
|       }); | ||||
|       this.updateInfo = data; | ||||
|       return super.open(); | ||||
|       return super.open(disposeOnResolve); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -30,7 +30,7 @@ export class IDEUpdaterCommands implements CommandContribution { | ||||
|     try { | ||||
|       const updateInfo = await this.updater.checkForUpdates(initialCheck); | ||||
|       if (!!updateInfo) { | ||||
|         this.updaterDialog.open(updateInfo); | ||||
|         this.updaterDialog.open(true, updateInfo); | ||||
|       } else { | ||||
|         this.messageService.info( | ||||
|           nls.localize( | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import { | ||||
| import { Emitter } from '@theia/core/lib/common/event'; | ||||
| import { JsonRpcProxy } from '@theia/core/lib/common/messaging/proxy-factory'; | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { | ||||
|   IndexUpdateDidCompleteParams, | ||||
|   IndexUpdateDidFailParams, | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import { | ||||
|   Disposable, | ||||
|   DisposableCollection, | ||||
| } from '@theia/core/lib/common/disposable'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { Sketch, SketchesService } from '../common/protocol'; | ||||
| import { ConfigServiceClient } from './config/config-service-client'; | ||||
| import { | ||||
| @@ -74,6 +74,7 @@ export class SketchesServiceClientImpl | ||||
|     const sketchDirUri = this.configService.tryGetSketchDirUri(); | ||||
|     this.watchSketchbookDir(sketchDirUri); | ||||
|     const refreshCurrentSketch = async () => { | ||||
|       await this.workspaceService.ready; | ||||
|       const currentSketch = await this.loadCurrentSketch(); | ||||
|       const ideTempFolderUri = await this.getIdeTempFolderUriForSketch( | ||||
|         currentSketch | ||||
| @@ -287,7 +288,7 @@ export class SketchesServiceClientImpl | ||||
|    * `true` if the `uri` is not contained in any of the opened workspaces. Otherwise, `false`. | ||||
|    */ | ||||
|   isReadOnly(uri: URI | monaco.Uri | string): boolean { | ||||
|     const toCheck = uri instanceof URI ? uri : new URI(uri); | ||||
|     const toCheck = uri instanceof URI ? uri : new URI(uri.toString()); | ||||
|     if (toCheck.scheme === 'user-storage') { | ||||
|       return false; | ||||
|     } | ||||
|   | ||||
| @@ -98,16 +98,12 @@ | ||||
|     color: var(--theia-textLink-foreground); | ||||
| } | ||||
|  | ||||
| .account-icon { | ||||
| img.arduino-account-picture { | ||||
|     width: var(--theia-private-sidebar-icon-size); | ||||
|     height: var(--theia-private-sidebar-icon-size); | ||||
|     border-radius: 50%; | ||||
|     overflow: hidden; | ||||
| } | ||||
|  | ||||
| .account-icon > img { | ||||
|     max-width: 100%; | ||||
|     max-height: 100%; | ||||
|     border-radius: 50%; | ||||
| } | ||||
|  | ||||
| .connected-status-icon { | ||||
|   | ||||
| @@ -13,6 +13,8 @@ import { MessageService } from '@theia/core/lib/common/message-service'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { ApplicationConnectionStatusContribution } from './connection-status-service'; | ||||
| import { ToolbarAwareTabBar } from './tab-bars'; | ||||
| import { find } from '@theia/core/shared/@phosphor/algorithm'; | ||||
| import { OutputWidget } from '@theia/output/lib/browser/output-widget'; | ||||
|  | ||||
| @injectable() | ||||
| export class ApplicationShell extends TheiaApplicationShell { | ||||
| @@ -48,6 +50,38 @@ export class ApplicationShell extends TheiaApplicationShell { | ||||
|     return super.addWidget(widget, { ...options, ref }); | ||||
|   } | ||||
|  | ||||
|   override doRevealWidget(id: string): Widget | undefined { | ||||
|     let widget = find(this.mainPanel.widgets(), (w) => w.id === id); | ||||
|     if (!widget) { | ||||
|       widget = find(this.bottomPanel.widgets(), (w) => w.id === id); | ||||
|       if (widget) { | ||||
|         this.expandBottomPanel(); | ||||
|       } | ||||
|     } | ||||
|     if (widget) { | ||||
|       const tabBar = this.getTabBarFor(widget); | ||||
|       if (tabBar) { | ||||
|         tabBar.currentTitle = widget.title; | ||||
|       } | ||||
|     } | ||||
|     if (!widget) { | ||||
|       widget = this.leftPanelHandler.expand(id); | ||||
|     } | ||||
|     if (!widget) { | ||||
|       widget = this.rightPanelHandler.expand(id); | ||||
|     } | ||||
|     if (widget) { | ||||
|       // Prevent focusing the output widget when is updated | ||||
|       // See https://github.com/arduino/arduino-ide/issues/2679 | ||||
|       if (!(widget instanceof OutputWidget)) { | ||||
|         this.windowService.focus(); | ||||
|       } | ||||
|       return widget; | ||||
|     } else { | ||||
|       return this.secondaryWindowHandler.revealWidget(id); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   override handleEvent(): boolean { | ||||
|     // NOOP, dragging has been disabled | ||||
|     return false; | ||||
|   | ||||
| @@ -1,26 +0,0 @@ | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { | ||||
|   BrowserMainMenuFactory as TheiaBrowserMainMenuFactory, | ||||
|   MenuBarWidget, | ||||
| } from '@theia/core/lib/browser/menu/browser-menu-plugin'; | ||||
| import { MainMenuManager } from '../../../common/main-menu-manager'; | ||||
|  | ||||
| @injectable() | ||||
| export class BrowserMainMenuFactory | ||||
|   extends TheiaBrowserMainMenuFactory | ||||
|   implements MainMenuManager | ||||
| { | ||||
|   protected menuBar: MenuBarWidget | undefined; | ||||
|  | ||||
|   override createMenuBar(): MenuBarWidget { | ||||
|     this.menuBar = super.createMenuBar(); | ||||
|     return this.menuBar; | ||||
|   } | ||||
|  | ||||
|   update(): void { | ||||
|     if (this.menuBar) { | ||||
|       this.menuBar.clearMenus(); | ||||
|       this.fillMenuBar(this.menuBar); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,18 +0,0 @@ | ||||
| import '../../../../src/browser/style/browser-menu.css'; | ||||
| import { ContainerModule } from '@theia/core/shared/inversify'; | ||||
| import { | ||||
|   BrowserMenuBarContribution, | ||||
|   BrowserMainMenuFactory as TheiaBrowserMainMenuFactory, | ||||
| } from '@theia/core/lib/browser/menu/browser-menu-plugin'; | ||||
| import { MainMenuManager } from '../../../common/main-menu-manager'; | ||||
| import { ArduinoMenuContribution } from './browser-menu-plugin'; | ||||
| import { BrowserMainMenuFactory } from './browser-main-menu-factory'; | ||||
|  | ||||
| export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|   bind(BrowserMainMenuFactory).toSelf().inSingletonScope(); | ||||
|   bind(MainMenuManager).toService(BrowserMainMenuFactory); | ||||
|   rebind(TheiaBrowserMainMenuFactory).toService(BrowserMainMenuFactory); | ||||
|   rebind(BrowserMenuBarContribution) | ||||
|     .to(ArduinoMenuContribution) | ||||
|     .inSingletonScope(); | ||||
| }); | ||||
| @@ -1,20 +0,0 @@ | ||||
| import { DefaultWindowService as TheiaDefaultWindowService } from '@theia/core/lib/browser/window/default-window-service'; | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { WindowServiceExt } from './window-service-ext'; | ||||
|  | ||||
| @injectable() | ||||
| export class DefaultWindowService | ||||
|   extends TheiaDefaultWindowService | ||||
|   implements WindowServiceExt | ||||
| { | ||||
|   close(): void { | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
|   /** | ||||
|    * The default implementation always resolves to `true`. | ||||
|    * IDE2 does not use it. It's currently an electron-only app. | ||||
|    */ | ||||
|   async isFirstWindow(): Promise<boolean> { | ||||
|     return true; | ||||
|   } | ||||
| } | ||||
| @@ -2,7 +2,7 @@ import { | ||||
|   CommonCommands, | ||||
|   CommonFrontendContribution as TheiaCommonFrontendContribution, | ||||
| } from '@theia/core/lib/browser/common-frontend-contribution'; | ||||
| import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application'; | ||||
| import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import type { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; | ||||
| import type { CommandRegistry } from '@theia/core/lib/common/command'; | ||||
| import type { MenuModelRegistry } from '@theia/core/lib/common/menu'; | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { | ||||
|   ApplicationConnectionStatusContribution as TheiaApplicationConnectionStatusContribution, | ||||
|   ConnectionStatus, | ||||
|   ApplicationConnectionStatusContribution as TheiaApplicationConnectionStatusContribution, | ||||
|   FrontendConnectionStatusService as TheiaFrontendConnectionStatusService, | ||||
| } from '@theia/core/lib/browser/connection-status-service'; | ||||
| import type { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { WebSocketConnectionProvider } from '@theia/core/lib/browser/index'; | ||||
| import type { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { WebSocketConnectionSource } from '@theia/core/lib/browser/messaging/ws-connection-source'; | ||||
| import { StatusBarAlignment } from '@theia/core/lib/browser/status-bar/status-bar'; | ||||
| import { Disposable } from '@theia/core/lib/common/disposable'; | ||||
| import { Emitter, Event } from '@theia/core/lib/common/event'; | ||||
| @@ -114,8 +114,8 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat | ||||
|   private readonly daemonPort: DaemonPort; | ||||
|   @inject(IsOnline) | ||||
|   private readonly isOnline: IsOnline; | ||||
|   @inject(WebSocketConnectionProvider) | ||||
|   private readonly connectionProvider: WebSocketConnectionProvider; | ||||
|   @inject(WebSocketConnectionSource) | ||||
|   private readonly connectionSource: WebSocketConnectionSource; | ||||
|  | ||||
|   @postConstruct() | ||||
|   protected override init(): void { | ||||
| @@ -128,7 +128,7 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat | ||||
|   } | ||||
|  | ||||
|   protected override async performPingRequest(): Promise<void> { | ||||
|     if (!this.connectionProvider['socket'].connected) { | ||||
|     if (!this.connectionSource['socket'].connected) { | ||||
|       this.updateStatus(false); | ||||
|       return; | ||||
|     } | ||||
| @@ -171,8 +171,8 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon | ||||
|   private readonly notificationManager: NotificationManager; | ||||
|   @inject(CreateFeatures) | ||||
|   private readonly createFeatures: CreateFeatures; | ||||
|   @inject(WebSocketConnectionProvider) | ||||
|   private readonly connectionProvider: WebSocketConnectionProvider; | ||||
|   @inject(WebSocketConnectionSource) | ||||
|   private readonly connectionSource: WebSocketConnectionSource; | ||||
|  | ||||
|   private readonly offlineStatusDidChangeEmitter = new Emitter< | ||||
|     OfflineConnectionStatus | undefined | ||||
| @@ -202,7 +202,7 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon | ||||
|     const params = <OfflineMessageParams>{ | ||||
|       port: this.daemonPort.port, | ||||
|       online: this.isOnline.online, | ||||
|       backendConnected: this.connectionProvider['socket'].connected, // https://github.com/arduino/arduino-ide/issues/2081 | ||||
|       backendConnected: this.connectionSource['socket'].connected, // https://github.com/arduino/arduino-ide/issues/2081 | ||||
|     }; | ||||
|     this._offlineStatus = offlineConnectionStatusType(params); | ||||
|     const { text, tooltip } = offlineMessage(params); | ||||
|   | ||||
| @@ -1,21 +0,0 @@ | ||||
| import { DefaultWindowService as TheiaDefaultWindowService } from '@theia/core/lib/browser/window/default-window-service'; | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { WindowServiceExt } from './window-service-ext'; | ||||
|  | ||||
| @injectable() | ||||
| export class DefaultWindowService | ||||
|   extends TheiaDefaultWindowService | ||||
|   implements WindowServiceExt | ||||
| { | ||||
|   /** | ||||
|    * The default implementation always resolves to `true`. | ||||
|    * IDE2 does not use it. It's currently an electron-only app. | ||||
|    */ | ||||
|   async isFirstWindow(): Promise<boolean> { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   close() { | ||||
|     console.log('close'); | ||||
|   } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { SidebarBottomMenuWidget as TheiaSidebarBottomMenuWidget } from '@theia/core/lib/browser/shell/sidebar-bottom-menu-widget'; | ||||
| import type { SidebarMenu } from '@theia/core/lib/browser/shell/sidebar-menu-widget'; | ||||
| import type { SidebarMenuItem } from '@theia/core/lib/browser/shell/sidebar-menu-widget'; | ||||
| import type { MenuPath } from '@theia/core/lib/common/menu'; | ||||
| import { nls } from '@theia/core/lib/common/nls'; | ||||
| import { | ||||
| @@ -46,46 +46,45 @@ export class SidebarBottomMenuWidget extends TheiaSidebarBottomMenuWidget { | ||||
|     this.contextMenuRenderer.render(options); | ||||
|   } | ||||
|  | ||||
|   protected override render(): React.ReactNode { | ||||
|     return ( | ||||
|       <React.Fragment> | ||||
|         {this.menus.map((menu) => this.renderMenu(menu))} | ||||
|       </React.Fragment> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   private renderMenu(menu: SidebarMenu): React.ReactNode { | ||||
|   override renderItem(item: SidebarMenuItem): React.ReactNode { | ||||
|     // Removes the _Settings_ (cog) icon from the left sidebar | ||||
|     if (menu.id === 'settings-menu') { | ||||
|     if (item.menu.id === 'settings-menu') { | ||||
|       return undefined; | ||||
|     } | ||||
|     const arduinoAccount = menu.id === accountMenu.id; | ||||
|     const picture = | ||||
|     const arduinoAccount = item.menu.id === accountMenu.id; | ||||
|     const arduinoAccountPicture = | ||||
|       arduinoAccount && | ||||
|       this.connectionStatue.offlineStatus !== 'internet' && | ||||
|       this.createFeatures.session?.account.picture; | ||||
|     const className = typeof picture === 'string' ? undefined : menu.iconClass; | ||||
|  | ||||
|     return ( | ||||
|       <i | ||||
|         key={menu.id} | ||||
|         className={className} | ||||
|         title={menu.title} | ||||
|         onClick={(e) => this.onClick(e, menu.menuPath)} | ||||
|       <div | ||||
|         key={item.menu.id} | ||||
|         className="theia-sidebar-menu-item" | ||||
|         title={item.menu.title} | ||||
|         onClick={(e) => this.onClick(e, item.menu.menuPath)} | ||||
|         onMouseDown={this.onMouseDown} | ||||
|         onMouseEnter={(e) => this.onMouseEnter(e, item.menu.title)} | ||||
|         onMouseOut={this.onMouseOut} | ||||
|       > | ||||
|         {picture && ( | ||||
|           <div className="account-icon"> | ||||
|         {arduinoAccountPicture ? ( | ||||
|           <i> | ||||
|             <img | ||||
|               src={picture} | ||||
|               className="arduino-account-picture" | ||||
|               src={arduinoAccountPicture} | ||||
|               alt={nls.localize( | ||||
|                 'arduino/cloud/profilePicture', | ||||
|                 'Profile picture' | ||||
|               )} | ||||
|             /> | ||||
|           </div> | ||||
|           </i> | ||||
|         ) : ( | ||||
|           <i className={item.menu.iconClass} /> | ||||
|         )} | ||||
|       </i> | ||||
|         {item.badge && ( | ||||
|           <div className="theia-badge-decorator-sidebar">{item.badge}</div> | ||||
|         )} | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { DebugSessionConnection } from '@theia/debug/lib/browser/debug-session-connection'; | ||||
| import { DefaultDebugSessionFactory as TheiaDefaultDebugSessionFactory } from '@theia/debug/lib/browser/debug-session-contribution'; | ||||
| import { DebugSessionManager } from '@theia/debug/lib/browser/debug-session-manager'; | ||||
| import { DebugConfigurationSessionOptions } from '@theia/debug/lib/browser/debug-session-options'; | ||||
| import { | ||||
|   DebugAdapterPath, | ||||
| @@ -12,6 +13,7 @@ import { DebugSession } from './debug-session'; | ||||
| @injectable() | ||||
| export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory { | ||||
|   override get( | ||||
|     manager: DebugSessionManager, | ||||
|     sessionId: string, | ||||
|     options: DebugConfigurationSessionOptions, | ||||
|     parentSession?: DebugSession | ||||
| @@ -20,12 +22,12 @@ export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory | ||||
|       sessionId, | ||||
|       () => | ||||
|         new Promise<DebugChannel>((resolve) => | ||||
|           this.connectionProvider.openChannel( | ||||
|           this.connectionProvider.listen( | ||||
|             `${DebugAdapterPath}/${sessionId}`, | ||||
|             (wsChannel) => { | ||||
|             (_, wsChannel) => { | ||||
|               resolve(new ForwardingDebugChannel(wsChannel)); | ||||
|             }, | ||||
|             { reconnecting: false } | ||||
|             false | ||||
|           ) | ||||
|         ), | ||||
|       this.getTraceOutputChannel() | ||||
| @@ -35,6 +37,9 @@ export class DefaultDebugSessionFactory extends TheiaDefaultDebugSessionFactory | ||||
|       sessionId, | ||||
|       options, | ||||
|       parentSession, | ||||
|       this.testService, | ||||
|       options.testRun, | ||||
|       manager, | ||||
|       connection, | ||||
|       this.terminalService, | ||||
|       this.editorManager, | ||||
|   | ||||
| @@ -1,21 +0,0 @@ | ||||
| import { injectable, postConstruct } from '@theia/core/shared/inversify'; | ||||
| import { EditorCommandContribution as TheiaEditorCommandContribution } from '@theia/editor/lib/browser/editor-command'; | ||||
|  | ||||
| @injectable() | ||||
| export class EditorCommandContribution extends TheiaEditorCommandContribution { | ||||
|   @postConstruct() | ||||
|   protected override init(): void { | ||||
|     // Workaround for https://github.com/eclipse-theia/theia/issues/8722. | ||||
|     this.editorPreferences.onPreferenceChanged( | ||||
|       ({ preferenceName, newValue, oldValue }) => { | ||||
|         if (preferenceName === 'files.autoSave') { | ||||
|           const autoSaveWasOnBeforeChange = !oldValue || oldValue !== 'off'; | ||||
|           const autoSaveIsOnAfterChange = !newValue || newValue !== 'off'; | ||||
|           if (!autoSaveWasOnBeforeChange && autoSaveIsOnAfterChange) { | ||||
|             this.shell.saveAll(); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -1,19 +1,18 @@ | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { TextEditor } from '@theia/editor/lib/browser'; | ||||
| import { EditorContribution as TheiaEditorContribution } from '@theia/editor/lib/browser/editor-contribution'; | ||||
|  | ||||
| @injectable() | ||||
| export class EditorContribution extends TheiaEditorContribution { | ||||
|   protected override updateLanguageStatus( | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars | ||||
|     editor: TextEditor | undefined | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
|     ..._: Parameters<TheiaEditorContribution['updateLanguageStatus']> | ||||
|   ): void { | ||||
|     // NOOP | ||||
|   } | ||||
|  | ||||
|   protected override updateEncodingStatus( | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars | ||||
|     editor: TextEditor | undefined | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
|     ..._: Parameters<TheiaEditorContribution['updateEncodingStatus']> | ||||
|   ): void { | ||||
|     // https://github.com/arduino/arduino-ide/issues/1393 | ||||
|     // NOOP | ||||
|   | ||||
| @@ -36,7 +36,7 @@ export class FileResourceResolver extends TheiaFileResourceResolver { | ||||
|       ); | ||||
|     } | ||||
|     return new WriteQueuedFileResource(uri, this.fileService, { | ||||
|       isReadonly: stat?.isReadonly ?? false, | ||||
|       readOnly: stat?.isReadonly ?? false, | ||||
|       shouldOverwrite: () => this.shouldOverwrite(uri), | ||||
|       shouldOpenAsText: (error) => this.shouldOpenAsText(uri, error), | ||||
|     }); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import React from '@theia/core/shared/react'; | ||||
| import { NotificationComponent as TheiaNotificationComponent } from '@theia/messages/lib/browser/notification-component'; | ||||
| import { nls } from '@theia/core/lib/common'; | ||||
| import { codicon } from '@theia/core/lib/browser'; | ||||
| import { sanitize } from 'dompurify'; | ||||
|  | ||||
| export class NotificationComponent extends TheiaNotificationComponent { | ||||
|   override render(): React.ReactNode { | ||||
| @@ -20,7 +21,7 @@ export class NotificationComponent extends TheiaNotificationComponent { | ||||
|             /> | ||||
|             <div className="theia-notification-message"> | ||||
|               <span | ||||
|                 dangerouslySetInnerHTML={{ __html: message }} | ||||
|                 dangerouslySetInnerHTML={{ __html: sanitize(message) }} | ||||
|                 onClick={this.onMessageClick} | ||||
|               /> | ||||
|             </div> | ||||
|   | ||||
| @@ -117,7 +117,7 @@ export function maybeUpdateReadOnlyState( | ||||
|   const model = editor.document; | ||||
|   const oldReadOnly = model.readOnly; | ||||
|   const resource = model['resource']; | ||||
|   const newReadOnly = Boolean(resource.isReadonly) || isReadOnly(resource.uri); | ||||
|   const newReadOnly = Boolean(resource.readOnly) || isReadOnly(resource.uri); | ||||
|   if (oldReadOnly !== newReadOnly) { | ||||
|     editor.getControl().updateOptions({ readOnly: newReadOnly }); | ||||
|     if (newReadOnly) { | ||||
|   | ||||
| @@ -20,7 +20,7 @@ export class MonacoTextModelService extends TheiaMonacoTextModelService { | ||||
|       .getContributions() | ||||
|       .find(({ scheme }) => resource.uri.scheme === scheme); | ||||
|     const readOnly = | ||||
|       Boolean(resource.isReadonly) || | ||||
|       Boolean(resource.readOnly) || | ||||
|       this.sketchesServiceClient.isReadOnly(resource.uri); | ||||
|     return factory | ||||
|       ? factory.createModel(resource) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { ThemeService } from '@theia/core/lib/browser/theming'; | ||||
| import { | ||||
|   Disposable, | ||||
| @@ -22,6 +22,7 @@ import { MonacoThemeRegistry as TheiaMonacoThemeRegistry } from '@theia/monaco/l | ||||
| import type { ThemeMix } from '@theia/monaco/lib/browser/textmate/monaco-theme-types'; | ||||
| import { HostedPluginSupport } from '../../hosted/hosted-plugin-support'; | ||||
| import { ArduinoThemes, compatibleBuiltInTheme } from '../core/theming'; | ||||
| import { WindowServiceExt } from '../core/window-service-ext'; | ||||
|  | ||||
| type MonacoThemeRegistrationSource = | ||||
|   /** | ||||
| @@ -155,8 +156,8 @@ export class CleanupObsoleteThemes implements FrontendApplicationContribution { | ||||
|   private readonly themeService: ThemeService; | ||||
|   @inject(MessageService) | ||||
|   private readonly messageService: MessageService; | ||||
|   // @inject(WindowServiceExt) | ||||
|   // private readonly windowService: WindowServiceExt; | ||||
|   @inject(WindowServiceExt) | ||||
|   private readonly windowService: WindowServiceExt; | ||||
|  | ||||
|   onStart(): void { | ||||
|     this.hostedPlugin.didStart.then(() => this.cleanupObsoleteThemes()); | ||||
| @@ -171,7 +172,7 @@ export class CleanupObsoleteThemes implements FrontendApplicationContribution { | ||||
|     if (!obsoleteThemeIds.length) { | ||||
|       return; | ||||
|     } | ||||
|     const firstWindow = true; // await this.windowService.isFirstWindow(); | ||||
|     const firstWindow = await this.windowService.isFirstWindow(); | ||||
|     if (firstWindow) { | ||||
|       await this.removeObsoleteThemesFromIndexedDB(obsoleteThemeIds); | ||||
|       this.unregisterObsoleteThemes(obsoleteThemeIds); | ||||
|   | ||||
| @@ -1,11 +1,9 @@ | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import type { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { Emitter, Event } from '@theia/core/lib/common/event'; | ||||
| import { injectable, interfaces } from '@theia/core/shared/inversify'; | ||||
| import { | ||||
|   PluginContributions, | ||||
|   HostedPluginSupport as TheiaHostedPluginSupport, | ||||
| } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin'; | ||||
| import { HostedPluginSupport } from '../../hosted/hosted-plugin-support'; | ||||
| import { HostedPluginSupport as TheiaHostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin'; | ||||
| import type { PluginContributions } from '@theia/plugin-ext/lib/hosted/common/hosted-plugin'; | ||||
| import type { HostedPluginSupport } from '../../hosted/hosted-plugin-support'; | ||||
|  | ||||
| @injectable() | ||||
| export class HostedPluginSupportImpl | ||||
|   | ||||
| @@ -1,241 +0,0 @@ | ||||
| import { LabelIcon } from '@theia/core/lib/browser/label-parser'; | ||||
| import { OpenerService, open } from '@theia/core/lib/browser/opener-service'; | ||||
| import { codicon } from '@theia/core/lib/browser/widgets/widget'; | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { URI } from '@theia/core/lib/common/uri'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import React from '@theia/core/shared/react'; | ||||
| import { URI as CodeUri } from '@theia/core/shared/vscode-uri'; | ||||
| import { TreeViewWidget as TheiaTreeViewWidget } from '@theia/plugin-ext/lib/main/browser/view/tree-view-widget'; | ||||
|  | ||||
| // Copied back from https://github.com/eclipse-theia/theia/pull/14391 | ||||
| // Remove the patching when Arduino uses Eclipse Theia >1.55.0 | ||||
| // https://github.com/eclipse-theia/theia/blob/8d3c5a11af65448b6700bedd096f8d68f0675541/packages/core/src/browser/tree/tree-view-welcome-widget.tsx#L37-L54 | ||||
| // https://github.com/eclipse-theia/theia/blob/8d3c5a11af65448b6700bedd096f8d68f0675541/packages/core/src/browser/tree/tree-view-welcome-widget.tsx#L146-L298 | ||||
|  | ||||
| interface ViewWelcome { | ||||
|   readonly view: string; | ||||
|   readonly content: string; | ||||
|   readonly when?: string; | ||||
|   readonly enablement?: string; | ||||
|   readonly order: number; | ||||
| } | ||||
|  | ||||
| export interface IItem { | ||||
|   readonly welcomeInfo: ViewWelcome; | ||||
|   visible: boolean; | ||||
| } | ||||
|  | ||||
| export interface ILink { | ||||
|   readonly label: string; | ||||
|   readonly href: string; | ||||
|   readonly title?: string; | ||||
| } | ||||
|  | ||||
| type LinkedTextItem = string | ILink; | ||||
|  | ||||
| @injectable() | ||||
| export class TreeViewWidget extends TheiaTreeViewWidget { | ||||
|   @inject(OpenerService) | ||||
|   private readonly openerService: OpenerService; | ||||
|  | ||||
|   private readonly toDisposeBeforeUpdateViewWelcomeNodes = | ||||
|     new DisposableCollection(); | ||||
|  | ||||
|   protected override updateViewWelcomeNodes(): void { | ||||
|     this.viewWelcomeNodes = []; | ||||
|     this.toDisposeBeforeUpdateViewWelcomeNodes.dispose(); | ||||
|     const items = this.visibleItems.sort((a, b) => a.order - b.order); | ||||
|  | ||||
|     const enablementKeys: Set<string>[] = []; | ||||
|     // the plugin-view-registry will push the changes when there is a change in the `when` prop  which controls the visibility | ||||
|     // this listener is to update the enablement of the components in the view welcome | ||||
|     this.toDisposeBeforeUpdateViewWelcomeNodes.push( | ||||
|       this.contextService.onDidChange((event) => { | ||||
|         if (enablementKeys.some((keys) => event.affects(keys))) { | ||||
|           this.updateViewWelcomeNodes(); | ||||
|           this.update(); | ||||
|         } | ||||
|       }) | ||||
|     ); | ||||
|     // Note: VS Code does not support the `renderSecondaryButtons` prop in welcome content either. | ||||
|     for (const item of items) { | ||||
|       const { content } = item; | ||||
|       const enablement = isEnablementAware(item) ? item.enablement : undefined; | ||||
|       const itemEnablementKeys = enablement | ||||
|         ? this.contextService.parseKeys(enablement) | ||||
|         : undefined; | ||||
|       if (itemEnablementKeys) { | ||||
|         enablementKeys.push(itemEnablementKeys); | ||||
|       } | ||||
|       const lines = content.split('\n'); | ||||
|  | ||||
|       for (let line of lines) { | ||||
|         line = line.trim(); | ||||
|  | ||||
|         if (!line) { | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|         const linkedTextItems = this.parseLinkedText_patch14309(line); | ||||
|  | ||||
|         if ( | ||||
|           linkedTextItems.length === 1 && | ||||
|           typeof linkedTextItems[0] !== 'string' | ||||
|         ) { | ||||
|           const node = linkedTextItems[0]; | ||||
|           this.viewWelcomeNodes.push( | ||||
|             this.renderButtonNode_patch14309( | ||||
|               node, | ||||
|               this.viewWelcomeNodes.length, | ||||
|               enablement | ||||
|             ) | ||||
|           ); | ||||
|         } else { | ||||
|           const renderNode = (item: LinkedTextItem, index: number) => | ||||
|             typeof item == 'string' | ||||
|               ? this.renderTextNode_patch14309(item, index) | ||||
|               : this.renderLinkNode_patch14309(item, index, enablement); | ||||
|  | ||||
|           this.viewWelcomeNodes.push( | ||||
|             <p key={`p-${this.viewWelcomeNodes.length}`}> | ||||
|               {...linkedTextItems.flatMap(renderNode)} | ||||
|             </p> | ||||
|           ); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private renderButtonNode_patch14309( | ||||
|     node: ILink, | ||||
|     lineKey: string | number, | ||||
|     enablement: string | undefined | ||||
|   ): React.ReactNode { | ||||
|     return ( | ||||
|       <div key={`line-${lineKey}`} className="theia-WelcomeViewButtonWrapper"> | ||||
|         <button | ||||
|           title={node.title} | ||||
|           className="theia-button theia-WelcomeViewButton" | ||||
|           disabled={!this.isEnabledClick_patch14309(enablement)} | ||||
|           onClick={(e) => this.openLinkOrCommand_patch14309(e, node.href)} | ||||
|         > | ||||
|           {node.label} | ||||
|         </button> | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   private renderTextNode_patch14309( | ||||
|     node: string, | ||||
|     textKey: string | number | ||||
|   ): React.ReactNode { | ||||
|     return ( | ||||
|       <span key={`text-${textKey}`}> | ||||
|         {this.labelParser | ||||
|           .parse(node) | ||||
|           .map((segment, index) => | ||||
|             LabelIcon.is(segment) ? ( | ||||
|               <span key={index} className={codicon(segment.name)} /> | ||||
|             ) : ( | ||||
|               <span key={index}>{segment}</span> | ||||
|             ) | ||||
|           )} | ||||
|       </span> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   private renderLinkNode_patch14309( | ||||
|     node: ILink, | ||||
|     linkKey: string | number, | ||||
|     enablement: string | undefined | ||||
|   ): React.ReactNode { | ||||
|     return ( | ||||
|       <a | ||||
|         key={`link-${linkKey}`} | ||||
|         className={this.getLinkClassName_patch14309(node.href, enablement)} | ||||
|         title={node.title || ''} | ||||
|         onClick={(e) => this.openLinkOrCommand_patch14309(e, node.href)} | ||||
|       > | ||||
|         {node.label} | ||||
|       </a> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   private getLinkClassName_patch14309( | ||||
|     href: string, | ||||
|     enablement: string | undefined | ||||
|   ): string { | ||||
|     const classNames = ['theia-WelcomeViewCommandLink']; | ||||
|     // Only command-backed links can be disabled. All other, https:, file: remain enabled | ||||
|     if ( | ||||
|       href.startsWith('command:') && | ||||
|       !this.isEnabledClick_patch14309(enablement) | ||||
|     ) { | ||||
|       classNames.push('disabled'); | ||||
|     } | ||||
|     return classNames.join(' '); | ||||
|   } | ||||
|  | ||||
|   private isEnabledClick_patch14309(enablement: string | undefined): boolean { | ||||
|     return typeof enablement === 'string' | ||||
|       ? this.contextService.match(enablement) | ||||
|       : true; | ||||
|   } | ||||
|  | ||||
|   private openLinkOrCommand_patch14309 = ( | ||||
|     event: React.MouseEvent, | ||||
|     value: string | ||||
|   ): void => { | ||||
|     event.stopPropagation(); | ||||
|  | ||||
|     if (value.startsWith('command:')) { | ||||
|       const command = value.replace('command:', ''); | ||||
|       this.commands.executeCommand(command); | ||||
|     } else if (value.startsWith('file:')) { | ||||
|       const uri = value.replace('file:', ''); | ||||
|       open(this.openerService, new URI(CodeUri.file(uri).toString())); | ||||
|     } else { | ||||
|       this.windowService.openNewWindow(value, { external: true }); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   private parseLinkedText_patch14309(text: string): LinkedTextItem[] { | ||||
|     const result: LinkedTextItem[] = []; | ||||
|  | ||||
|     const linkRegex = | ||||
|       /\[([^\]]+)\]\(((?:https?:\/\/|command:|file:)[^\)\s]+)(?: (["'])(.+?)(\3))?\)/gi; | ||||
|     let index = 0; | ||||
|     let match: RegExpExecArray | null; | ||||
|  | ||||
|     while ((match = linkRegex.exec(text))) { | ||||
|       if (match.index - index > 0) { | ||||
|         result.push(text.substring(index, match.index)); | ||||
|       } | ||||
|  | ||||
|       const [, label, href, , title] = match; | ||||
|  | ||||
|       if (title) { | ||||
|         result.push({ label, href, title }); | ||||
|       } else { | ||||
|         result.push({ label, href }); | ||||
|       } | ||||
|  | ||||
|       index = match.index + match[0].length; | ||||
|     } | ||||
|  | ||||
|     if (index < text.length) { | ||||
|       result.push(text.substring(index)); | ||||
|     } | ||||
|  | ||||
|     return result; | ||||
|   } | ||||
| } | ||||
|  | ||||
| interface EnablementAware { | ||||
|   readonly enablement: string | undefined; | ||||
| } | ||||
|  | ||||
| function isEnablementAware(arg: unknown): arg is EnablementAware { | ||||
|   return !!arg && typeof arg === 'object' && 'enablement' in arg; | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| import { TestViewContribution as TheiaTestViewContribution } from '@theia/test/lib/browser/view/test-view-contribution'; | ||||
| import { injectable } from 'inversify'; | ||||
|  | ||||
| @injectable() | ||||
| export class TestViewContribution extends TheiaTestViewContribution { | ||||
|   override async initializeLayout(): Promise<void> { | ||||
|     // NOOP | ||||
|   } | ||||
| } | ||||
| @@ -19,13 +19,14 @@ import { | ||||
|   hasStartupTasks, | ||||
|   StartupTask, | ||||
| } from '../../../electron-common/startup-task'; | ||||
| import { WindowServiceExt } from '../core/window-service-ext'; | ||||
|  | ||||
| @injectable() | ||||
| export class WorkspaceService extends TheiaWorkspaceService { | ||||
|   @inject(SketchesService) | ||||
|   private readonly sketchesService: SketchesService; | ||||
|   // @inject(WindowServiceExt) | ||||
|   // private readonly windowServiceExt: WindowServiceExt; | ||||
|   @inject(WindowServiceExt) | ||||
|   private readonly windowServiceExt: WindowServiceExt; | ||||
|   @inject(ContributionProvider) | ||||
|   @named(StartupTaskProvider) | ||||
|   private readonly providers: ContributionProvider<StartupTaskProvider>; | ||||
| @@ -103,8 +104,7 @@ export class WorkspaceService extends TheiaWorkspaceService { | ||||
|   protected override reloadWindow(options?: WorkspaceInput): void { | ||||
|     const tasks = this.tasks(options); | ||||
|     this.setURLFragment(this._workspace?.resource.path.toString() || ''); | ||||
|     console.log(tasks); | ||||
|     // this.windowServiceExt.reload({ tasks }); | ||||
|     this.windowServiceExt.reload({ tasks }); | ||||
|   } | ||||
|  | ||||
|   protected override openNewWindow( | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import { | ||||
|   TabBarToolbarRegistry, | ||||
|   TabBarToolbarItem, | ||||
|   ReactTabBarToolbarItem, | ||||
|   RenderedToolbarItem, | ||||
| } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; | ||||
| import { CommandRegistry } from '@theia/core/lib/common/command'; | ||||
| import { ReactWidget } from '@theia/core/lib/browser'; | ||||
| @@ -14,7 +15,7 @@ export const ARDUINO_TOOLBAR_ITEM_CLASS = 'arduino-tool-item'; | ||||
| export namespace ArduinoToolbarComponent { | ||||
|   export interface Props { | ||||
|     side: 'left' | 'right'; | ||||
|     items: (TabBarToolbarItem | ReactTabBarToolbarItem)[]; | ||||
|     items: TabBarToolbarItem[]; | ||||
|     commands: CommandRegistry; | ||||
|     labelParser: LabelParser; | ||||
|     commandIsEnabled: (id: string) => boolean; | ||||
| @@ -34,7 +35,7 @@ export class ArduinoToolbarComponent extends React.Component< | ||||
|     this.state = { tooltip: '' }; | ||||
|   } | ||||
|  | ||||
|   protected renderItem = (item: TabBarToolbarItem) => { | ||||
|   protected renderItem = (item: RenderedToolbarItem) => { | ||||
|     let innerText = ''; | ||||
|     let className = `arduino-tool-icon ${item.id}-icon`; | ||||
|     if (item.text) { | ||||
| @@ -46,7 +47,8 @@ export class ArduinoToolbarComponent extends React.Component< | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     const command = this.props.commands.getCommand(item.command); | ||||
|     const command = | ||||
|       item.command && this.props.commands.getCommand(item.command); | ||||
|     const cls = `${ARDUINO_TOOLBAR_ITEM_CLASS} ${ | ||||
|       TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM | ||||
|     } ${command && this.props.commandIsEnabled(command.id) ? 'enabled' : ''} ${ | ||||
| @@ -80,7 +82,9 @@ export class ArduinoToolbarComponent extends React.Component< | ||||
|     const items = [ | ||||
|       <React.Fragment key={this.props.side + '-arduino-toolbar-tooltip'}> | ||||
|         {[...this.props.items].map((item) => | ||||
|           TabBarToolbarItem.is(item) ? this.renderItem(item) : item.render() | ||||
|           ReactTabBarToolbarItem.is(item) | ||||
|             ? item.render() | ||||
|             : this.renderItem(item) | ||||
|         )} | ||||
|       </React.Fragment>, | ||||
|     ]; | ||||
| @@ -94,10 +98,7 @@ export class ArduinoToolbarComponent extends React.Component< | ||||
| } | ||||
|  | ||||
| export class ArduinoToolbar extends ReactWidget { | ||||
|   protected items = new Map< | ||||
|     string, | ||||
|     TabBarToolbarItem | ReactTabBarToolbarItem | ||||
|   >(); | ||||
|   protected items = new Map<string, TabBarToolbarItem>(); | ||||
|  | ||||
|   constructor( | ||||
|     protected readonly tabBarToolbarRegistry: TabBarToolbarRegistry, | ||||
| @@ -112,9 +113,7 @@ export class ArduinoToolbar extends ReactWidget { | ||||
|     this.tabBarToolbarRegistry.onDidChange(() => this.updateToolbar()); | ||||
|   } | ||||
|  | ||||
|   protected updateItems( | ||||
|     items: Array<TabBarToolbarItem | ReactTabBarToolbarItem> | ||||
|   ): void { | ||||
|   protected updateItems(items: Array<TabBarToolbarItem>): void { | ||||
|     this.items.clear(); | ||||
|     const revItems = items | ||||
|       .sort(TabBarToolbarItem.PRIORITY_COMPARATOR) | ||||
| @@ -163,7 +162,7 @@ export class ArduinoToolbar extends ReactWidget { | ||||
|  | ||||
|   protected executeCommand = (e: React.MouseEvent<HTMLElement>) => { | ||||
|     const item = this.items.get(e.currentTarget.id); | ||||
|     if (TabBarToolbarItem.is(item)) { | ||||
|     if (item && item.command) { | ||||
|       this.commands.executeCommand(item.command, this, e.target); | ||||
|     } | ||||
|   }; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { | ||||
|   OpenerOptions, | ||||
|   OpenHandler, | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import { CommandRegistry } from '@theia/core/lib/common/command'; | ||||
| import { MenuModelRegistry } from '@theia/core/lib/common/menu'; | ||||
| import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service'; | ||||
| import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; | ||||
| import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution'; | ||||
| import { MainMenuManager } from '../../../common/main-menu-manager'; | ||||
| import { ArduinoPreferences } from '../../arduino-preferences'; | ||||
| import { SketchbookWidget } from './sketchbook-widget'; | ||||
|   | ||||
| @@ -1,10 +1,8 @@ | ||||
| // export const MainMenuManager = Symbol('MainMenuManager'); | ||||
| export class MainMenuManager { | ||||
| export const MainMenuManager = Symbol('MainMenuManager'); | ||||
| export interface MainMenuManager { | ||||
|   /** | ||||
|    * Call this method if you have changed the content of the main menu (updated a toggle flag, removed/added new groups or menu items) | ||||
|    * and you want to re-render it from scratch. Works for electron too. | ||||
|    */ | ||||
|   update() { | ||||
|     console.warn('MainMenuManager.update() is not implemented'); | ||||
|   } | ||||
|   update(): void; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +0,0 @@ | ||||
| export const SurveyNotificationServicePath = | ||||
|   '/services/survey-notification-service'; | ||||
| export const SurveyNotificationService = Symbol('SurveyNotificationService'); | ||||
|  | ||||
| export interface SurveyNotificationService { | ||||
|   isFirstInstance(): Promise<boolean>; | ||||
| } | ||||
| @@ -38,3 +38,26 @@ export function uint8ArrayToString(uint8Array: Uint8Array): string { | ||||
| export function stringToUint8Array(text: string): Uint8Array { | ||||
|   return Uint8Array.from(text, (char) => char.charCodeAt(0)); | ||||
| } | ||||
|  | ||||
| export function poolWhile( | ||||
|   whileCondition: () => boolean, | ||||
|   intervalMs: number, | ||||
|   timeoutMs: number | ||||
| ): Promise<void> { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     if (!whileCondition) { | ||||
|       resolve(); | ||||
|     } | ||||
|  | ||||
|     const start = Date.now(); | ||||
|     const interval = setInterval(() => { | ||||
|       if (!whileCondition()) { | ||||
|         clearInterval(interval); | ||||
|         resolve(); | ||||
|       } else if (Date.now() - start > timeoutMs) { | ||||
|         clearInterval(interval); | ||||
|         reject(new Error('Timed out while polling.')); | ||||
|       } | ||||
|     }, intervalMs); | ||||
|   }); | ||||
| } | ||||
|   | ||||
| @@ -38,33 +38,33 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { | ||||
|     this.preferencesService.onPreferenceChanged( | ||||
|       debounce((e) => { | ||||
|         if (e.preferenceName === 'window.menuBarVisibility') { | ||||
|           this.setMenuBar(); | ||||
|           this.doSetMenuBar(); | ||||
|         } | ||||
|         if (this._menu) { | ||||
|           for (const cmd of this._toggledCommands) { | ||||
|             const menuItem = this.findMenuById(this._menu, cmd); | ||||
|         if (this.menu) { | ||||
|           for (const cmd of this.toggledCommands) { | ||||
|             const menuItem = this.findMenuById(this.menu, cmd); | ||||
|             if (menuItem) { | ||||
|               menuItem.checked = this.commandRegistry.isToggled(cmd); | ||||
|             } | ||||
|           } | ||||
|           window.electronArduino.setMenu(this._menu); // calls the IDE2-specific implementation | ||||
|           window.electronArduino.setMenu(this.menu); // calls the IDE2-specific implementation | ||||
|         } | ||||
|       }, 10) | ||||
|     ); | ||||
|     this.keybindingRegistry.onKeybindingsChanged(() => { | ||||
|       this.setMenuBar(); | ||||
|       this.doSetMenuBar(); | ||||
|     }); | ||||
|     // #endregion Theia `postConstruct` | ||||
|     this.appStateService.reachedState('ready').then(() => { | ||||
|       this.appReady = true; | ||||
|       if (this.updateWhenReady) { | ||||
|         this.setMenuBar(); | ||||
|         this.doSetMenuBar(); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   override createElectronMenuBar(): MenuDto[] { | ||||
|     this._toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977 | ||||
|     this.toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977 | ||||
|     const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR); | ||||
|     const menu = this.fillMenuTemplate([], menuModel, [], { | ||||
|       rootMenuPath: MAIN_MENU_BAR, | ||||
| @@ -73,11 +73,11 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { | ||||
|       menu.unshift(this.createOSXMenu()); | ||||
|     } | ||||
|     const escapedMenu = this.escapeAmpersand(menu); | ||||
|     this._menu = escapedMenu; | ||||
|     this.menu = escapedMenu; | ||||
|     return escapedMenu; | ||||
|   } | ||||
|  | ||||
|   override async setMenuBar(): Promise<void> { | ||||
|   override async doSetMenuBar(): Promise<void> { | ||||
|     // Avoid updating menu items when the app is not ready. | ||||
|     // Getting the current electron window is not free and synchronous. | ||||
|     // Here, we defer all menu update requests, and fire one when the app is ready. | ||||
| @@ -124,17 +124,17 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { | ||||
|           ...args | ||||
|         ); | ||||
|         if ( | ||||
|           this._menu && | ||||
|           this.menu && | ||||
|           this.menuCommandExecutor.isVisible(menuPath, commandId, ...args) | ||||
|         ) { | ||||
|           const item = this.findMenuById(this._menu, commandId); | ||||
|           const item = this.findMenuById(this.menu, commandId); | ||||
|           if (item) { | ||||
|             item.checked = this.menuCommandExecutor.isToggled( | ||||
|               menuPath, | ||||
|               commandId, | ||||
|               ...args | ||||
|             ); | ||||
|             window.electronArduino.setMenu(this._menu); // overridden to call the IDE2-specific implementation. | ||||
|             window.electronArduino.setMenu(this.menu); // overridden to call the IDE2-specific implementation. | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| @@ -342,7 +342,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { | ||||
|       parentItems.push(menuItem); | ||||
|  | ||||
|       if (this.commandRegistry.getToggledHandler(commandId, ...args)) { | ||||
|         this._toggledCommands.add(commandId); | ||||
|         this.toggledCommands.add(commandId); | ||||
|       } | ||||
|     } | ||||
|     return parentItems; | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import { | ||||
|   hasStartupTasks, | ||||
|   StartupTasks, | ||||
| } from '../../../electron-common/startup-task'; | ||||
| import { WindowReloadOptions } from '@theia/core/lib/browser/window/window-service'; | ||||
|  | ||||
| @injectable() | ||||
| export class ElectronWindowService | ||||
| @@ -17,8 +18,12 @@ export class ElectronWindowService | ||||
|  | ||||
|   @postConstruct() | ||||
|   protected override init(): void { | ||||
|     // NOOP | ||||
|     // Overridden to avoid calling the zoom level listener in super. | ||||
|     // IDE2 listens on the zoom level changes in `ArduinoFrontendContribution#onStart` | ||||
|  | ||||
|     window.electronTheiaCore.onAboutToClose(() => { | ||||
|       this.connectionCloseService.markForClose(this.frontendIdProvider.getId()); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   async isFirstWindow(): Promise<boolean> { | ||||
| @@ -38,11 +43,11 @@ export class ElectronWindowService | ||||
|   } | ||||
|  | ||||
|   // Overridden to support optional task owner params and make `tsc` happy. | ||||
|   override reload(options?: StartupTasks): void { | ||||
|   override reload(options?: StartupTasks | WindowReloadOptions): void { | ||||
|     if (hasStartupTasks(options)) { | ||||
|       window.electronArduino.requestReload(options); | ||||
|     } else { | ||||
|       window.electronTheiaCore.requestReload(); | ||||
|       super.reload(options); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { JsonRpcConnectionHandler } from '@theia/core/lib/common/messaging/proxy-factory'; | ||||
| import { ElectronConnectionHandler } from '@theia/core/lib/electron-main/messaging/electron-connection-handler'; | ||||
| import { RpcConnectionHandler } from '@theia/core/lib/common/messaging/proxy-factory'; | ||||
| import { ElectronMainWindowService } from '@theia/core/lib/electron-common/electron-main-window-service'; | ||||
| import { ElectronConnectionHandler } from '@theia/core/lib/electron-common/messaging/electron-connection-handler'; | ||||
| import { TheiaMainApi } from '@theia/core/lib/electron-main/electron-api-main'; | ||||
| import { | ||||
|   ElectronMainApplication as TheiaElectronMainApplication, | ||||
|   ElectronMainApplicationContribution, | ||||
|   ElectronMainApplication as TheiaElectronMainApplication, | ||||
| } from '@theia/core/lib/electron-main/electron-main-application'; | ||||
| import { TheiaElectronWindow as DefaultTheiaElectronWindow } from '@theia/core/lib/electron-main/theia-electron-window'; | ||||
| import { ContainerModule } from '@theia/core/shared/inversify'; | ||||
| @@ -36,15 +36,12 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|   bind(ElectronConnectionHandler) | ||||
|     .toDynamicValue( | ||||
|       (context) => | ||||
|         new JsonRpcConnectionHandler<IDEUpdaterClient>( | ||||
|           IDEUpdaterPath, | ||||
|           (client) => { | ||||
|             const server = context.container.get<IDEUpdater>(IDEUpdater); | ||||
|             server.setClient(client); | ||||
|             client.onDidCloseConnection(() => server.disconnectClient(client)); | ||||
|             return server; | ||||
|           } | ||||
|         ) | ||||
|         new RpcConnectionHandler<IDEUpdaterClient>(IDEUpdaterPath, (client) => { | ||||
|           const server = context.container.get<IDEUpdater>(IDEUpdater); | ||||
|           server.setClient(client); | ||||
|           client.onDidCloseConnection(() => server.disconnectClient(client)); | ||||
|           return server; | ||||
|         }) | ||||
|     ) | ||||
|     .inSingletonScope(); | ||||
|  | ||||
|   | ||||
| @@ -11,16 +11,16 @@ import { | ||||
|   Disposable, | ||||
|   DisposableCollection, | ||||
| } from '@theia/core/lib/common/disposable'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { isOSX } from '@theia/core/lib/common/os'; | ||||
| import { Deferred } from '@theia/core/lib/common/promise-util'; | ||||
| import { isObject, MaybePromise, Mutable } from '@theia/core/lib/common/types'; | ||||
| import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token'; | ||||
| import { | ||||
|   ElectronMainExecutionParams, | ||||
|   ElectronMainCommandOptions, | ||||
|   ElectronMainApplication as TheiaElectronMainApplication, | ||||
| } from '@theia/core/lib/electron-main/electron-main-application'; | ||||
| import type { TheiaBrowserWindowOptions } from '@theia/core/lib/electron-main/theia-electron-window'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { URI } from '@theia/core/shared/vscode-uri'; | ||||
| import { log as logToFile, setup as setupFileLog } from 'node-log-rotate'; | ||||
| @@ -28,7 +28,9 @@ import { fork } from 'node:child_process'; | ||||
| import { promises as fs, readFileSync, rm, rmSync } from 'node:fs'; | ||||
| import type { AddressInfo } from 'node:net'; | ||||
| import { isAbsolute, join, resolve } from 'node:path'; | ||||
| import type { Argv } from 'yargs'; | ||||
| import { Sketch } from '../../common/protocol'; | ||||
| import { poolWhile } from '../../common/utils'; | ||||
| import { | ||||
|   AppInfo, | ||||
|   appInfoPropertyLiterals, | ||||
| @@ -129,6 +131,11 @@ const APP_STARTED_WITH_CONTENT_TRACE = | ||||
|   typeof process !== 'undefined' && | ||||
|   process.argv.indexOf('--content-trace') !== -1; | ||||
|  | ||||
| const createYargs: ( | ||||
|   argv?: string[], | ||||
|   cwd?: string | ||||
| ) => Argv = require('yargs/yargs'); | ||||
|  | ||||
| @injectable() | ||||
| export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|   @inject(IsTempSketch) | ||||
| @@ -171,29 +178,59 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|   private readonly scheduledDeletions: Disposable[] = []; | ||||
|  | ||||
|   override async start(config: FrontendApplicationConfig): Promise<void> { | ||||
|     // Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit") | ||||
|     // See: https://github.com/electron-userland/electron-builder/issues/2468 | ||||
|     // Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701 | ||||
|     console.log(`${config.applicationName} ${app.getVersion()}`); | ||||
|     app.on('ready', () => app.setName(config.applicationName)); | ||||
|     const cwd = process.cwd(); | ||||
|     this.attachFileAssociations(cwd); | ||||
|     this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native'; | ||||
|     this._config = await updateFrontendApplicationConfigFromPackageJson(config); | ||||
|     this._appInfo = updateAppInfo(this._appInfo, this._config); | ||||
|     this.hookApplicationEvents(); | ||||
|     const [port] = await Promise.all([this.startBackend(), app.whenReady()]); | ||||
|     this.startContentTracing(); | ||||
|     this._backendPort.resolve(port); | ||||
|     await Promise.all([ | ||||
|       this.attachElectronSecurityToken(port), | ||||
|       this.startContributions(), | ||||
|     ]); | ||||
|     return this.launch({ | ||||
|       secondInstance: false, | ||||
|       argv: this.processArgv.getProcessArgvWithoutBin(process.argv), | ||||
|       cwd, | ||||
|     }); | ||||
|     createYargs(this.argv, process.cwd()) | ||||
|       .command( | ||||
|         '$0 [file]', | ||||
|         false, | ||||
|         (cmd) => | ||||
|           cmd | ||||
|             .option('electronUserData', { | ||||
|               type: 'string', | ||||
|               describe: | ||||
|                 'The area where the electron main process puts its data', | ||||
|             }) | ||||
|             .positional('file', { type: 'string' }), | ||||
|         async (args) => { | ||||
|           if (args.electronUserData) { | ||||
|             console.info( | ||||
|               `using electron user data area : '${args.electronUserData}'` | ||||
|             ); | ||||
|             await fs.mkdir(args.electronUserData, { recursive: true }); | ||||
|             app.setPath('userData', args.electronUserData); | ||||
|           } | ||||
|           // Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit") | ||||
|           // See: https://github.com/electron-userland/electron-builder/issues/2468 | ||||
|           // Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701 | ||||
|           console.log(`${config.applicationName} ${app.getVersion()}`); | ||||
|           app.on('ready', () => app.setName(config.applicationName)); | ||||
|           const cwd = process.cwd(); | ||||
|           this.attachFileAssociations(cwd); | ||||
|           this.useNativeWindowFrame = | ||||
|             this.getTitleBarStyle(config) === 'native'; | ||||
|           this._config = await updateFrontendApplicationConfigFromPackageJson( | ||||
|             config | ||||
|           ); | ||||
|           this._appInfo = updateAppInfo(this._appInfo, this._config); | ||||
|           this.hookApplicationEvents(); | ||||
|           this.showInitialWindow(undefined); | ||||
|           const [port] = await Promise.all([ | ||||
|             this.startBackend(), | ||||
|             app.whenReady(), | ||||
|           ]); | ||||
|           this.startContentTracing(); | ||||
|           this._backendPort.resolve(port); | ||||
|           await Promise.all([ | ||||
|             this.attachElectronSecurityToken(port), | ||||
|             this.startContributions(), | ||||
|           ]); | ||||
|           this.handleMainCommand({ | ||||
|             file: args.file, | ||||
|             cwd, | ||||
|             secondInstance: false, | ||||
|           }); | ||||
|         } | ||||
|       ) | ||||
|       .parse(); | ||||
|   } | ||||
|  | ||||
|   private startContentTracing(): void { | ||||
| @@ -256,6 +293,16 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|           ); | ||||
|           if (sketchFolderPath) { | ||||
|             this.openFilePromise.reject(new InterruptWorkspaceRestoreError()); | ||||
|  | ||||
|             // open-file event is triggered before the app is ready and initialWindow is created. | ||||
|             // Wait for initialWindow to be set before opening the sketch on the first instance. | ||||
|             // See https://github.com/arduino/arduino-ide/pull/2693 | ||||
|             try { | ||||
|               await app.whenReady(); | ||||
|               if (!this.firstWindowId) { | ||||
|                 await poolWhile(() => !this.initialWindow, 100, 3000); | ||||
|               } | ||||
|             } catch {} | ||||
|             await this.openSketch(sketchFolderPath); | ||||
|           } | ||||
|         } | ||||
| @@ -284,8 +331,8 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected override async launch( | ||||
|     params: ElectronMainExecutionParams | ||||
|   protected override async handleMainCommand( | ||||
|     options: ElectronMainCommandOptions | ||||
|   ): Promise<void> { | ||||
|     try { | ||||
|       // When running on MacOS, we either have to wait until | ||||
| @@ -300,7 +347,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|       throw err; | ||||
|     } | ||||
|  | ||||
|     if (await this.launchFromArgs(params)) { | ||||
|     if (await this.launchFromArgs(options)) { | ||||
|       // Application has received a file in its arguments and will skip the default application launch | ||||
|       return; | ||||
|     } | ||||
| @@ -314,7 +361,10 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|         `Restoring workspace roots: ${workspaces.map(({ file }) => file)}` | ||||
|       ); | ||||
|       for (const workspace of workspaces) { | ||||
|         const resolvedPath = await this.resolvePath(workspace.file, params.cwd); | ||||
|         const resolvedPath = await this.resolvePath( | ||||
|           workspace.file, | ||||
|           options.cwd | ||||
|         ); | ||||
|         if (!resolvedPath) { | ||||
|           continue; | ||||
|         } | ||||
| @@ -337,15 +387,20 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|     } | ||||
|     this.startup = false; | ||||
|     if (useDefault) { | ||||
|       super.launch(params); | ||||
|       super.handleMainCommand(options); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private get argv(): string[] { | ||||
|     return this.processArgv.getProcessArgvWithoutBin(process.argv).slice(); | ||||
|   } | ||||
|  | ||||
|   private async launchFromArgs( | ||||
|     params: ElectronMainExecutionParams | ||||
|     params: ElectronMainCommandOptions, | ||||
|     argv?: string[] | ||||
|   ): Promise<boolean> { | ||||
|     // Copy to prevent manipulation of original array | ||||
|     const argCopy = [...params.argv]; | ||||
|     const argCopy = [...(argv || this.argv)]; | ||||
|     let path: string | undefined; | ||||
|     for (const maybePath of argCopy) { | ||||
|       const resolvedPath = await this.resolvePath(maybePath, params.cwd); | ||||
| @@ -383,7 +438,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|     } | ||||
|     const [uri, electronWindow] = await Promise.all([ | ||||
|       this.createWindowUri(), | ||||
|       this.createWindow(options), | ||||
|       this.reuseOrCreateWindow(options), | ||||
|     ]); | ||||
|     electronWindow.loadURL(uri.withFragment(encodeURI(file)).toString(true)); | ||||
|     return electronWindow; | ||||
| @@ -483,7 +538,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { | ||||
|     argv: string[], | ||||
|     cwd: string | ||||
|   ): Promise<void> { | ||||
|     if (await this.launchFromArgs({ cwd, argv, secondInstance: true })) { | ||||
|     if (await this.launchFromArgs({ cwd, secondInstance: true }, argv)) { | ||||
|       // Application has received a file in its arguments | ||||
|       return; | ||||
|     } | ||||
| @@ -779,7 +834,7 @@ class InterruptWorkspaceRestoreError extends Error { | ||||
| // but it's the `package.json` inside the `resources/app/` folder if it's the final bundled app. | ||||
| // See https://github.com/arduino/arduino-ide/pull/2144#pullrequestreview-1556343430. | ||||
| async function updateFrontendApplicationConfigFromPackageJson( | ||||
|   config: FrontendApplicationConfig | ||||
|   config: Mutable<FrontendApplicationConfig> | ||||
| ): Promise<FrontendApplicationConfig> { | ||||
|   if (!isProductionMode) { | ||||
|     console.debug( | ||||
| @@ -846,7 +901,11 @@ const fallbackFrontendAppConfig: FrontendApplicationConfig = { | ||||
|   defaultIconTheme: 'none', | ||||
|   validatePreferencesSchema: false, | ||||
|   defaultLocale: '', | ||||
|   electron: {}, | ||||
|   electron: { | ||||
|     showWindowEarly: true, | ||||
|     uriScheme: 'arduino-ide', | ||||
|   }, | ||||
|   reloadOnReconnect: true, | ||||
| }; | ||||
|  | ||||
| // When the package.json must go from `./lib/backend/electron-main.js` to `./package.json` when the app is webpacked. | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import { ElectronArduinoRenderer } from '../electron-arduino'; | ||||
| @injectable() | ||||
| export class TheiaElectronWindow extends DefaultTheiaElectronWindow { | ||||
|   protected override reload(args?: unknown): void { | ||||
|     this.handleStopRequest(() => { | ||||
|     this.handleStopRequest(async () => { | ||||
|       this.applicationState = 'init'; | ||||
|       if (hasStartupTasks(args)) { | ||||
|         const { webContents } = this._window; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { join } from 'node:path'; | ||||
| import { inject, injectable, named } from '@theia/core/shared/inversify'; | ||||
| import { spawn, ChildProcess } from 'node:child_process'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { ILogger } from '@theia/core/lib/common/logger'; | ||||
| import { Deferred, retry } from '@theia/core/lib/common/promise-util'; | ||||
| import { | ||||
|   | ||||
| @@ -105,14 +105,8 @@ import { ClangFormatter } from './clang-formatter'; | ||||
| import { FormatterPath } from '../common/protocol/formatter'; | ||||
| import { HostedPluginLocalizationService } from './theia/plugin-ext/hosted-plugin-localization-service'; | ||||
| import { HostedPluginLocalizationService as TheiaHostedPluginLocalizationService } from '@theia/plugin-ext/lib/hosted/node/hosted-plugin-localization-service'; | ||||
| import { SurveyNotificationServiceImpl } from './survey-service-impl'; | ||||
| import { | ||||
|   SurveyNotificationService, | ||||
|   SurveyNotificationServicePath, | ||||
| } from '../common/protocol/survey-service'; | ||||
| import { IsTempSketch } from './is-temp-sketch'; | ||||
| import { rebindNsfwFileSystemWatcher } from './theia/filesystem/nsfw-bindings'; | ||||
| import { MessagingContribution } from './theia/core/messaging-contribution'; | ||||
| import { WebsocketEndpoint } from './theia/core/websocket-endpoint'; | ||||
| import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service'; | ||||
| import { HostedPluginReader } from './theia/plugin-ext/plugin-reader'; | ||||
| import { HostedPluginReader as TheiaHostedPluginReader } from '@theia/plugin-ext/lib/hosted/node/plugin-reader'; | ||||
| @@ -126,6 +120,7 @@ import { | ||||
| } from './theia/plugin-ext/plugin-deployer'; | ||||
| import { SettingsReader } from './settings-reader'; | ||||
| import { VsCodePluginScanner } from './theia/plugin-ext-vscode/scanner-vscode'; | ||||
| import { rebindParcelFileSystemWatcher } from './theia/filesystem/parcel-bindings'; | ||||
|  | ||||
| export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|   bind(BackendApplication).toSelf().inSingletonScope(); | ||||
| @@ -305,7 +300,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|         ) | ||||
|     ) | ||||
|     .inSingletonScope(); | ||||
|   rebindNsfwFileSystemWatcher(rebind); | ||||
|   rebindParcelFileSystemWatcher(rebind); | ||||
|  | ||||
|   // Output service per connection. | ||||
|   bind(ConnectionContainerModule).toConstantValue( | ||||
| @@ -383,23 +378,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { | ||||
|     HostedPluginLocalizationService | ||||
|   ); | ||||
|  | ||||
|   // Survey notification bindings | ||||
|   // It's currently unused. https://github.com/arduino/arduino-ide/pull/1150 | ||||
|   bind(SurveyNotificationServiceImpl).toSelf().inSingletonScope(); | ||||
|   bind(SurveyNotificationService).toService(SurveyNotificationServiceImpl); | ||||
|   bind(ConnectionHandler) | ||||
|     .toDynamicValue( | ||||
|       ({ container }) => | ||||
|         new JsonRpcConnectionHandler(SurveyNotificationServicePath, () => | ||||
|           container.get<SurveyNotificationService>(SurveyNotificationService) | ||||
|         ) | ||||
|     ) | ||||
|     .inSingletonScope(); | ||||
|  | ||||
|   bind(IsTempSketch).toSelf().inSingletonScope(); | ||||
|   rebind(MessagingService.Identifier) | ||||
|     .to(MessagingContribution) | ||||
|     .inSingletonScope(); | ||||
|   rebind(MessagingService.Identifier).to(WebsocketEndpoint).inSingletonScope(); | ||||
|  | ||||
|   // Removed undesired contributions from VS Code extensions | ||||
|   // Such as the RTOS view from the `cortex-debug` extension | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; | ||||
| import { MaybePromise } from '@theia/core/lib/common/types'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { constants, promises as fs } from 'node:fs'; | ||||
| import { join } from 'node:path'; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { notEmpty } from '@theia/core/lib/common/objects'; | ||||
| import { nls } from '@theia/core/lib/common/nls'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { | ||||
|   Range, | ||||
|   Position, | ||||
|   | ||||
| @@ -360,6 +360,8 @@ export class BoardListRequest extends jspb.Message { | ||||
|     setTimeout(value: number): BoardListRequest; | ||||
|     getFqbn(): string; | ||||
|     setFqbn(value: string): BoardListRequest; | ||||
|     getSkipCloudApiForBoardDetection(): boolean; | ||||
|     setSkipCloudApiForBoardDetection(value: boolean): BoardListRequest; | ||||
|  | ||||
|     serializeBinary(): Uint8Array; | ||||
|     toObject(includeInstance?: boolean): BoardListRequest.AsObject; | ||||
| @@ -376,6 +378,7 @@ export namespace BoardListRequest { | ||||
|         instance?: cc_arduino_cli_commands_v1_common_pb.Instance.AsObject, | ||||
|         timeout: number, | ||||
|         fqbn: string, | ||||
|         skipCloudApiForBoardDetection: boolean, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -493,6 +496,8 @@ export class BoardListWatchRequest extends jspb.Message { | ||||
|     clearInstance(): void; | ||||
|     getInstance(): cc_arduino_cli_commands_v1_common_pb.Instance | undefined; | ||||
|     setInstance(value?: cc_arduino_cli_commands_v1_common_pb.Instance): BoardListWatchRequest; | ||||
|     getSkipCloudApiForBoardDetection(): boolean; | ||||
|     setSkipCloudApiForBoardDetection(value: boolean): BoardListWatchRequest; | ||||
|  | ||||
|     serializeBinary(): Uint8Array; | ||||
|     toObject(includeInstance?: boolean): BoardListWatchRequest.AsObject; | ||||
| @@ -507,6 +512,7 @@ export class BoardListWatchRequest extends jspb.Message { | ||||
| export namespace BoardListWatchRequest { | ||||
|     export type AsObject = { | ||||
|         instance?: cc_arduino_cli_commands_v1_common_pb.Instance.AsObject, | ||||
|         skipCloudApiForBoardDetection: boolean, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -621,3 +627,56 @@ export namespace BoardSearchResponse { | ||||
|         boardsList: Array<BoardListItem.AsObject>, | ||||
|     } | ||||
| } | ||||
|  | ||||
| export class BoardIdentifyRequest extends jspb.Message {  | ||||
|  | ||||
|     hasInstance(): boolean; | ||||
|     clearInstance(): void; | ||||
|     getInstance(): cc_arduino_cli_commands_v1_common_pb.Instance | undefined; | ||||
|     setInstance(value?: cc_arduino_cli_commands_v1_common_pb.Instance): BoardIdentifyRequest; | ||||
|  | ||||
|     getPropertiesMap(): jspb.Map<string, string>; | ||||
|     clearPropertiesMap(): void; | ||||
|     getUseCloudApiForUnknownBoardDetection(): boolean; | ||||
|     setUseCloudApiForUnknownBoardDetection(value: boolean): BoardIdentifyRequest; | ||||
|  | ||||
|     serializeBinary(): Uint8Array; | ||||
|     toObject(includeInstance?: boolean): BoardIdentifyRequest.AsObject; | ||||
|     static toObject(includeInstance: boolean, msg: BoardIdentifyRequest): BoardIdentifyRequest.AsObject; | ||||
|     static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; | ||||
|     static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; | ||||
|     static serializeBinaryToWriter(message: BoardIdentifyRequest, writer: jspb.BinaryWriter): void; | ||||
|     static deserializeBinary(bytes: Uint8Array): BoardIdentifyRequest; | ||||
|     static deserializeBinaryFromReader(message: BoardIdentifyRequest, reader: jspb.BinaryReader): BoardIdentifyRequest; | ||||
| } | ||||
|  | ||||
| export namespace BoardIdentifyRequest { | ||||
|     export type AsObject = { | ||||
|         instance?: cc_arduino_cli_commands_v1_common_pb.Instance.AsObject, | ||||
|  | ||||
|         propertiesMap: Array<[string, string]>, | ||||
|         useCloudApiForUnknownBoardDetection: boolean, | ||||
|     } | ||||
| } | ||||
|  | ||||
| export class BoardIdentifyResponse extends jspb.Message {  | ||||
|     clearBoardsList(): void; | ||||
|     getBoardsList(): Array<BoardListItem>; | ||||
|     setBoardsList(value: Array<BoardListItem>): BoardIdentifyResponse; | ||||
|     addBoards(value?: BoardListItem, index?: number): BoardListItem; | ||||
|  | ||||
|     serializeBinary(): Uint8Array; | ||||
|     toObject(includeInstance?: boolean): BoardIdentifyResponse.AsObject; | ||||
|     static toObject(includeInstance: boolean, msg: BoardIdentifyResponse): BoardIdentifyResponse.AsObject; | ||||
|     static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; | ||||
|     static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; | ||||
|     static serializeBinaryToWriter(message: BoardIdentifyResponse, writer: jspb.BinaryWriter): void; | ||||
|     static deserializeBinary(bytes: Uint8Array): BoardIdentifyResponse; | ||||
|     static deserializeBinaryFromReader(message: BoardIdentifyResponse, reader: jspb.BinaryReader): BoardIdentifyResponse; | ||||
| } | ||||
|  | ||||
| export namespace BoardIdentifyResponse { | ||||
|     export type AsObject = { | ||||
|         boardsList: Array<BoardListItem.AsObject>, | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,6 +28,8 @@ goog.object.extend(proto, cc_arduino_cli_commands_v1_port_pb); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardDetailsRequest', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardDetailsResponse', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardIdentificationProperties', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardListAllRequest', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardListAllResponse', null, global); | ||||
| goog.exportSymbol('proto.cc.arduino.cli.commands.v1.BoardListItem', null, global); | ||||
| @@ -465,6 +467,48 @@ if (goog.DEBUG && !COMPILED) { | ||||
|    */ | ||||
|   proto.cc.arduino.cli.commands.v1.BoardSearchResponse.displayName = 'proto.cc.arduino.cli.commands.v1.BoardSearchResponse'; | ||||
| } | ||||
| /** | ||||
|  * Generated by JsPbCodeGenerator. | ||||
|  * @param {Array=} opt_data Optional initial data array, typically from a | ||||
|  * server response, or constructed directly in Javascript. The array is used | ||||
|  * in place and becomes part of the constructed object. It is not cloned. | ||||
|  * If no data is provided, the constructed object will be empty, but still | ||||
|  * valid. | ||||
|  * @extends {jspb.Message} | ||||
|  * @constructor | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest = function(opt_data) { | ||||
|   jspb.Message.initialize(this, opt_data, 0, -1, null, null); | ||||
| }; | ||||
| goog.inherits(proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest, jspb.Message); | ||||
| if (goog.DEBUG && !COMPILED) { | ||||
|   /** | ||||
|    * @public | ||||
|    * @override | ||||
|    */ | ||||
|   proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.displayName = 'proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest'; | ||||
| } | ||||
| /** | ||||
|  * Generated by JsPbCodeGenerator. | ||||
|  * @param {Array=} opt_data Optional initial data array, typically from a | ||||
|  * server response, or constructed directly in Javascript. The array is used | ||||
|  * in place and becomes part of the constructed object. It is not cloned. | ||||
|  * If no data is provided, the constructed object will be empty, but still | ||||
|  * valid. | ||||
|  * @extends {jspb.Message} | ||||
|  * @constructor | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse = function(opt_data) { | ||||
|   jspb.Message.initialize(this, opt_data, 0, -1, proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.repeatedFields_, null); | ||||
| }; | ||||
| goog.inherits(proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse, jspb.Message); | ||||
| if (goog.DEBUG && !COMPILED) { | ||||
|   /** | ||||
|    * @public | ||||
|    * @override | ||||
|    */ | ||||
|   proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.displayName = 'proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse'; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -3204,7 +3248,8 @@ proto.cc.arduino.cli.commands.v1.BoardListRequest.toObject = function(includeIns | ||||
|   var f, obj = { | ||||
|     instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f), | ||||
|     timeout: jspb.Message.getFieldWithDefault(msg, 2, 0), | ||||
|     fqbn: jspb.Message.getFieldWithDefault(msg, 3, "") | ||||
|     fqbn: jspb.Message.getFieldWithDefault(msg, 3, ""), | ||||
|     skipCloudApiForBoardDetection: jspb.Message.getBooleanFieldWithDefault(msg, 4, false) | ||||
|   }; | ||||
|  | ||||
|   if (includeInstance) { | ||||
| @@ -3254,6 +3299,10 @@ proto.cc.arduino.cli.commands.v1.BoardListRequest.deserializeBinaryFromReader = | ||||
|       var value = /** @type {string} */ (reader.readString()); | ||||
|       msg.setFqbn(value); | ||||
|       break; | ||||
|     case 4: | ||||
|       var value = /** @type {boolean} */ (reader.readBool()); | ||||
|       msg.setSkipCloudApiForBoardDetection(value); | ||||
|       break; | ||||
|     default: | ||||
|       reader.skipField(); | ||||
|       break; | ||||
| @@ -3305,6 +3354,13 @@ proto.cc.arduino.cli.commands.v1.BoardListRequest.serializeBinaryToWriter = func | ||||
|       f | ||||
|     ); | ||||
|   } | ||||
|   f = message.getSkipCloudApiForBoardDetection(); | ||||
|   if (f) { | ||||
|     writer.writeBool( | ||||
|       4, | ||||
|       f | ||||
|     ); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -3381,6 +3437,24 @@ proto.cc.arduino.cli.commands.v1.BoardListRequest.prototype.setFqbn = function(v | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * optional bool skip_cloud_api_for_board_detection = 4; | ||||
|  * @return {boolean} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardListRequest.prototype.getSkipCloudApiForBoardDetection = function() { | ||||
|   return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false)); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {boolean} value | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardListRequest} returns this | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardListRequest.prototype.setSkipCloudApiForBoardDetection = function(value) { | ||||
|   return jspb.Message.setProto3BooleanField(this, 4, value); | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * List of repeated fields within this message type. | ||||
| @@ -4230,7 +4304,8 @@ proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.prototype.toObject = func | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.toObject = function(includeInstance, msg) { | ||||
|   var f, obj = { | ||||
|     instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f) | ||||
|     instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f), | ||||
|     skipCloudApiForBoardDetection: jspb.Message.getBooleanFieldWithDefault(msg, 2, false) | ||||
|   }; | ||||
|  | ||||
|   if (includeInstance) { | ||||
| @@ -4272,6 +4347,10 @@ proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.deserializeBinaryFromRead | ||||
|       reader.readMessage(value,cc_arduino_cli_commands_v1_common_pb.Instance.deserializeBinaryFromReader); | ||||
|       msg.setInstance(value); | ||||
|       break; | ||||
|     case 2: | ||||
|       var value = /** @type {boolean} */ (reader.readBool()); | ||||
|       msg.setSkipCloudApiForBoardDetection(value); | ||||
|       break; | ||||
|     default: | ||||
|       reader.skipField(); | ||||
|       break; | ||||
| @@ -4309,6 +4388,13 @@ proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.serializeBinaryToWriter = | ||||
|       cc_arduino_cli_commands_v1_common_pb.Instance.serializeBinaryToWriter | ||||
|     ); | ||||
|   } | ||||
|   f = message.getSkipCloudApiForBoardDetection(); | ||||
|   if (f) { | ||||
|     writer.writeBool( | ||||
|       2, | ||||
|       f | ||||
|     ); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -4349,6 +4435,24 @@ proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.prototype.hasInstance = f | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * optional bool skip_cloud_api_for_board_detection = 2; | ||||
|  * @return {boolean} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.prototype.getSkipCloudApiForBoardDetection = function() { | ||||
|   return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false)); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {boolean} value | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardListWatchRequest} returns this | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardListWatchRequest.prototype.setSkipCloudApiForBoardDetection = function(value) { | ||||
|   return jspb.Message.setProto3BooleanField(this, 2, value); | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -5172,4 +5276,378 @@ proto.cc.arduino.cli.commands.v1.BoardSearchResponse.prototype.clearBoardsList = | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| if (jspb.Message.GENERATE_TO_OBJECT) { | ||||
| /** | ||||
|  * Creates an object representation of this proto. | ||||
|  * Field names that are reserved in JavaScript and will be renamed to pb_name. | ||||
|  * Optional fields that are not set will be set to undefined. | ||||
|  * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. | ||||
|  * For the list of reserved names please see: | ||||
|  *     net/proto2/compiler/js/internal/generator.cc#kKeyword. | ||||
|  * @param {boolean=} opt_includeInstance Deprecated. whether to include the | ||||
|  *     JSPB instance for transitional soy proto support: | ||||
|  *     http://goto/soy-param-migration | ||||
|  * @return {!Object} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.toObject = function(opt_includeInstance) { | ||||
|   return proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.toObject(opt_includeInstance, this); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Static version of the {@see toObject} method. | ||||
|  * @param {boolean|undefined} includeInstance Deprecated. Whether to include | ||||
|  *     the JSPB instance for transitional soy proto support: | ||||
|  *     http://goto/soy-param-migration | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} msg The msg instance to transform. | ||||
|  * @return {!Object} | ||||
|  * @suppress {unusedLocalVariables} f is only used for nested messages | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.toObject = function(includeInstance, msg) { | ||||
|   var f, obj = { | ||||
|     instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f), | ||||
|     propertiesMap: (f = msg.getPropertiesMap()) ? f.toObject(includeInstance, undefined) : [], | ||||
|     useCloudApiForUnknownBoardDetection: jspb.Message.getBooleanFieldWithDefault(msg, 3, false) | ||||
|   }; | ||||
|  | ||||
|   if (includeInstance) { | ||||
|     obj.$jspbMessageInstance = msg; | ||||
|   } | ||||
|   return obj; | ||||
| }; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Deserializes binary data (in protobuf wire format). | ||||
|  * @param {jspb.ByteSource} bytes The bytes to deserialize. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.deserializeBinary = function(bytes) { | ||||
|   var reader = new jspb.BinaryReader(bytes); | ||||
|   var msg = new proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest; | ||||
|   return proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.deserializeBinaryFromReader(msg, reader); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Deserializes binary data (in protobuf wire format) from the | ||||
|  * given reader into the given message object. | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} msg The message object to deserialize into. | ||||
|  * @param {!jspb.BinaryReader} reader The BinaryReader to use. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.deserializeBinaryFromReader = function(msg, reader) { | ||||
|   while (reader.nextField()) { | ||||
|     if (reader.isEndGroup()) { | ||||
|       break; | ||||
|     } | ||||
|     var field = reader.getFieldNumber(); | ||||
|     switch (field) { | ||||
|     case 1: | ||||
|       var value = new cc_arduino_cli_commands_v1_common_pb.Instance; | ||||
|       reader.readMessage(value,cc_arduino_cli_commands_v1_common_pb.Instance.deserializeBinaryFromReader); | ||||
|       msg.setInstance(value); | ||||
|       break; | ||||
|     case 2: | ||||
|       var value = msg.getPropertiesMap(); | ||||
|       reader.readMessage(value, function(message, reader) { | ||||
|         jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readString, null, "", ""); | ||||
|          }); | ||||
|       break; | ||||
|     case 3: | ||||
|       var value = /** @type {boolean} */ (reader.readBool()); | ||||
|       msg.setUseCloudApiForUnknownBoardDetection(value); | ||||
|       break; | ||||
|     default: | ||||
|       reader.skipField(); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   return msg; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Serializes the message to binary data (in protobuf wire format). | ||||
|  * @return {!Uint8Array} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.serializeBinary = function() { | ||||
|   var writer = new jspb.BinaryWriter(); | ||||
|   proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.serializeBinaryToWriter(this, writer); | ||||
|   return writer.getResultBuffer(); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Serializes the given message to binary data (in protobuf wire | ||||
|  * format), writing to the given BinaryWriter. | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} message | ||||
|  * @param {!jspb.BinaryWriter} writer | ||||
|  * @suppress {unusedLocalVariables} f is only used for nested messages | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.serializeBinaryToWriter = function(message, writer) { | ||||
|   var f = undefined; | ||||
|   f = message.getInstance(); | ||||
|   if (f != null) { | ||||
|     writer.writeMessage( | ||||
|       1, | ||||
|       f, | ||||
|       cc_arduino_cli_commands_v1_common_pb.Instance.serializeBinaryToWriter | ||||
|     ); | ||||
|   } | ||||
|   f = message.getPropertiesMap(true); | ||||
|   if (f && f.getLength() > 0) { | ||||
|     f.serializeBinary(2, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString); | ||||
|   } | ||||
|   f = message.getUseCloudApiForUnknownBoardDetection(); | ||||
|   if (f) { | ||||
|     writer.writeBool( | ||||
|       3, | ||||
|       f | ||||
|     ); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * optional Instance instance = 1; | ||||
|  * @return {?proto.cc.arduino.cli.commands.v1.Instance} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.getInstance = function() { | ||||
|   return /** @type{?proto.cc.arduino.cli.commands.v1.Instance} */ ( | ||||
|     jspb.Message.getWrapperField(this, cc_arduino_cli_commands_v1_common_pb.Instance, 1)); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {?proto.cc.arduino.cli.commands.v1.Instance|undefined} value | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} returns this | ||||
| */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.setInstance = function(value) { | ||||
|   return jspb.Message.setWrapperField(this, 1, value); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Clears the message field making it undefined. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} returns this | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.clearInstance = function() { | ||||
|   return this.setInstance(undefined); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Returns whether this field is set. | ||||
|  * @return {boolean} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.hasInstance = function() { | ||||
|   return jspb.Message.getField(this, 1) != null; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * map<string, string> properties = 2; | ||||
|  * @param {boolean=} opt_noLazyCreate Do not create the map if | ||||
|  * empty, instead returning `undefined` | ||||
|  * @return {!jspb.Map<string,string>} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.getPropertiesMap = function(opt_noLazyCreate) { | ||||
|   return /** @type {!jspb.Map<string,string>} */ ( | ||||
|       jspb.Message.getMapField(this, 2, opt_noLazyCreate, | ||||
|       null)); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Clears values from the map. The map will be non-null. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} returns this | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.clearPropertiesMap = function() { | ||||
|   this.getPropertiesMap().clear(); | ||||
|   return this;}; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * optional bool use_cloud_api_for_unknown_board_detection = 3; | ||||
|  * @return {boolean} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.getUseCloudApiForUnknownBoardDetection = function() { | ||||
|   return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false)); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {boolean} value | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest} returns this | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyRequest.prototype.setUseCloudApiForUnknownBoardDetection = function(value) { | ||||
|   return jspb.Message.setProto3BooleanField(this, 3, value); | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * List of repeated fields within this message type. | ||||
|  * @private {!Array<number>} | ||||
|  * @const | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.repeatedFields_ = [1]; | ||||
|  | ||||
|  | ||||
|  | ||||
| if (jspb.Message.GENERATE_TO_OBJECT) { | ||||
| /** | ||||
|  * Creates an object representation of this proto. | ||||
|  * Field names that are reserved in JavaScript and will be renamed to pb_name. | ||||
|  * Optional fields that are not set will be set to undefined. | ||||
|  * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. | ||||
|  * For the list of reserved names please see: | ||||
|  *     net/proto2/compiler/js/internal/generator.cc#kKeyword. | ||||
|  * @param {boolean=} opt_includeInstance Deprecated. whether to include the | ||||
|  *     JSPB instance for transitional soy proto support: | ||||
|  *     http://goto/soy-param-migration | ||||
|  * @return {!Object} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.prototype.toObject = function(opt_includeInstance) { | ||||
|   return proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.toObject(opt_includeInstance, this); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Static version of the {@see toObject} method. | ||||
|  * @param {boolean|undefined} includeInstance Deprecated. Whether to include | ||||
|  *     the JSPB instance for transitional soy proto support: | ||||
|  *     http://goto/soy-param-migration | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} msg The msg instance to transform. | ||||
|  * @return {!Object} | ||||
|  * @suppress {unusedLocalVariables} f is only used for nested messages | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.toObject = function(includeInstance, msg) { | ||||
|   var f, obj = { | ||||
|     boardsList: jspb.Message.toObjectList(msg.getBoardsList(), | ||||
|     proto.cc.arduino.cli.commands.v1.BoardListItem.toObject, includeInstance) | ||||
|   }; | ||||
|  | ||||
|   if (includeInstance) { | ||||
|     obj.$jspbMessageInstance = msg; | ||||
|   } | ||||
|   return obj; | ||||
| }; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Deserializes binary data (in protobuf wire format). | ||||
|  * @param {jspb.ByteSource} bytes The bytes to deserialize. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.deserializeBinary = function(bytes) { | ||||
|   var reader = new jspb.BinaryReader(bytes); | ||||
|   var msg = new proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse; | ||||
|   return proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.deserializeBinaryFromReader(msg, reader); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Deserializes binary data (in protobuf wire format) from the | ||||
|  * given reader into the given message object. | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} msg The message object to deserialize into. | ||||
|  * @param {!jspb.BinaryReader} reader The BinaryReader to use. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.deserializeBinaryFromReader = function(msg, reader) { | ||||
|   while (reader.nextField()) { | ||||
|     if (reader.isEndGroup()) { | ||||
|       break; | ||||
|     } | ||||
|     var field = reader.getFieldNumber(); | ||||
|     switch (field) { | ||||
|     case 1: | ||||
|       var value = new proto.cc.arduino.cli.commands.v1.BoardListItem; | ||||
|       reader.readMessage(value,proto.cc.arduino.cli.commands.v1.BoardListItem.deserializeBinaryFromReader); | ||||
|       msg.addBoards(value); | ||||
|       break; | ||||
|     default: | ||||
|       reader.skipField(); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   return msg; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Serializes the message to binary data (in protobuf wire format). | ||||
|  * @return {!Uint8Array} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.prototype.serializeBinary = function() { | ||||
|   var writer = new jspb.BinaryWriter(); | ||||
|   proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.serializeBinaryToWriter(this, writer); | ||||
|   return writer.getResultBuffer(); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Serializes the given message to binary data (in protobuf wire | ||||
|  * format), writing to the given BinaryWriter. | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} message | ||||
|  * @param {!jspb.BinaryWriter} writer | ||||
|  * @suppress {unusedLocalVariables} f is only used for nested messages | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.serializeBinaryToWriter = function(message, writer) { | ||||
|   var f = undefined; | ||||
|   f = message.getBoardsList(); | ||||
|   if (f.length > 0) { | ||||
|     writer.writeRepeatedMessage( | ||||
|       1, | ||||
|       f, | ||||
|       proto.cc.arduino.cli.commands.v1.BoardListItem.serializeBinaryToWriter | ||||
|     ); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * repeated BoardListItem boards = 1; | ||||
|  * @return {!Array<!proto.cc.arduino.cli.commands.v1.BoardListItem>} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.prototype.getBoardsList = function() { | ||||
|   return /** @type{!Array<!proto.cc.arduino.cli.commands.v1.BoardListItem>} */ ( | ||||
|     jspb.Message.getRepeatedWrapperField(this, proto.cc.arduino.cli.commands.v1.BoardListItem, 1)); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {!Array<!proto.cc.arduino.cli.commands.v1.BoardListItem>} value | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} returns this | ||||
| */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.prototype.setBoardsList = function(value) { | ||||
|   return jspb.Message.setRepeatedWrapperField(this, 1, value); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {!proto.cc.arduino.cli.commands.v1.BoardListItem=} opt_value | ||||
|  * @param {number=} opt_index | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardListItem} | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.prototype.addBoards = function(opt_value, opt_index) { | ||||
|   return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.cc.arduino.cli.commands.v1.BoardListItem, opt_index); | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Clears the list making it empty but non-null. | ||||
|  * @return {!proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse} returns this | ||||
|  */ | ||||
| proto.cc.arduino.cli.commands.v1.BoardIdentifyResponse.prototype.clearBoardsList = function() { | ||||
|   return this.setBoardsList([]); | ||||
| }; | ||||
|  | ||||
|  | ||||
| goog.object.extend(exports, proto.cc.arduino.cli.commands.v1); | ||||
|   | ||||
| @@ -32,6 +32,7 @@ interface IArduinoCoreServiceService extends grpc.ServiceDefinition<grpc.Untyped | ||||
|     boardList: IArduinoCoreServiceService_IBoardList; | ||||
|     boardListAll: IArduinoCoreServiceService_IBoardListAll; | ||||
|     boardSearch: IArduinoCoreServiceService_IBoardSearch; | ||||
|     boardIdentify: IArduinoCoreServiceService_IBoardIdentify; | ||||
|     boardListWatch: IArduinoCoreServiceService_IBoardListWatch; | ||||
|     compile: IArduinoCoreServiceService_ICompile; | ||||
|     platformInstall: IArduinoCoreServiceService_IPlatformInstall; | ||||
| @@ -195,6 +196,15 @@ interface IArduinoCoreServiceService_IBoardSearch extends grpc.MethodDefinition< | ||||
|     responseSerialize: grpc.serialize<cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse>; | ||||
|     responseDeserialize: grpc.deserialize<cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse>; | ||||
| } | ||||
| interface IArduinoCoreServiceService_IBoardIdentify extends grpc.MethodDefinition<cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse> { | ||||
|     path: "/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardIdentify"; | ||||
|     requestStream: false; | ||||
|     responseStream: false; | ||||
|     requestSerialize: grpc.serialize<cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest>; | ||||
|     requestDeserialize: grpc.deserialize<cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest>; | ||||
|     responseSerialize: grpc.serialize<cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse>; | ||||
|     responseDeserialize: grpc.deserialize<cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse>; | ||||
| } | ||||
| interface IArduinoCoreServiceService_IBoardListWatch extends grpc.MethodDefinition<cc_arduino_cli_commands_v1_board_pb.BoardListWatchRequest, cc_arduino_cli_commands_v1_board_pb.BoardListWatchResponse> { | ||||
|     path: "/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardListWatch"; | ||||
|     requestStream: false; | ||||
| @@ -528,6 +538,7 @@ export interface IArduinoCoreServiceServer extends grpc.UntypedServiceImplementa | ||||
|     boardList: grpc.handleUnaryCall<cc_arduino_cli_commands_v1_board_pb.BoardListRequest, cc_arduino_cli_commands_v1_board_pb.BoardListResponse>; | ||||
|     boardListAll: grpc.handleUnaryCall<cc_arduino_cli_commands_v1_board_pb.BoardListAllRequest, cc_arduino_cli_commands_v1_board_pb.BoardListAllResponse>; | ||||
|     boardSearch: grpc.handleUnaryCall<cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse>; | ||||
|     boardIdentify: grpc.handleUnaryCall<cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse>; | ||||
|     boardListWatch: grpc.handleServerStreamingCall<cc_arduino_cli_commands_v1_board_pb.BoardListWatchRequest, cc_arduino_cli_commands_v1_board_pb.BoardListWatchResponse>; | ||||
|     compile: grpc.handleServerStreamingCall<cc_arduino_cli_commands_v1_compile_pb.CompileRequest, cc_arduino_cli_commands_v1_compile_pb.CompileResponse>; | ||||
|     platformInstall: grpc.handleServerStreamingCall<cc_arduino_cli_commands_v1_core_pb.PlatformInstallRequest, cc_arduino_cli_commands_v1_core_pb.PlatformInstallResponse>; | ||||
| @@ -605,6 +616,9 @@ export interface IArduinoCoreServiceClient { | ||||
|     boardSearch(request: cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse) => void): grpc.ClientUnaryCall; | ||||
|     boardSearch(request: cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse) => void): grpc.ClientUnaryCall; | ||||
|     boardSearch(request: cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse) => void): grpc.ClientUnaryCall; | ||||
|     boardIdentify(request: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse) => void): grpc.ClientUnaryCall; | ||||
|     boardIdentify(request: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse) => void): grpc.ClientUnaryCall; | ||||
|     boardIdentify(request: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse) => void): grpc.ClientUnaryCall; | ||||
|     boardListWatch(request: cc_arduino_cli_commands_v1_board_pb.BoardListWatchRequest, options?: Partial<grpc.CallOptions>): grpc.ClientReadableStream<cc_arduino_cli_commands_v1_board_pb.BoardListWatchResponse>; | ||||
|     boardListWatch(request: cc_arduino_cli_commands_v1_board_pb.BoardListWatchRequest, metadata?: grpc.Metadata, options?: Partial<grpc.CallOptions>): grpc.ClientReadableStream<cc_arduino_cli_commands_v1_board_pb.BoardListWatchResponse>; | ||||
|     compile(request: cc_arduino_cli_commands_v1_compile_pb.CompileRequest, options?: Partial<grpc.CallOptions>): grpc.ClientReadableStream<cc_arduino_cli_commands_v1_compile_pb.CompileResponse>; | ||||
| @@ -737,6 +751,9 @@ export class ArduinoCoreServiceClient extends grpc.Client implements IArduinoCor | ||||
|     public boardSearch(request: cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse) => void): grpc.ClientUnaryCall; | ||||
|     public boardSearch(request: cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse) => void): grpc.ClientUnaryCall; | ||||
|     public boardSearch(request: cc_arduino_cli_commands_v1_board_pb.BoardSearchRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardSearchResponse) => void): grpc.ClientUnaryCall; | ||||
|     public boardIdentify(request: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse) => void): grpc.ClientUnaryCall; | ||||
|     public boardIdentify(request: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse) => void): grpc.ClientUnaryCall; | ||||
|     public boardIdentify(request: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse) => void): grpc.ClientUnaryCall; | ||||
|     public boardListWatch(request: cc_arduino_cli_commands_v1_board_pb.BoardListWatchRequest, options?: Partial<grpc.CallOptions>): grpc.ClientReadableStream<cc_arduino_cli_commands_v1_board_pb.BoardListWatchResponse>; | ||||
|     public boardListWatch(request: cc_arduino_cli_commands_v1_board_pb.BoardListWatchRequest, metadata?: grpc.Metadata, options?: Partial<grpc.CallOptions>): grpc.ClientReadableStream<cc_arduino_cli_commands_v1_board_pb.BoardListWatchResponse>; | ||||
|     public compile(request: cc_arduino_cli_commands_v1_compile_pb.CompileRequest, options?: Partial<grpc.CallOptions>): grpc.ClientReadableStream<cc_arduino_cli_commands_v1_compile_pb.CompileResponse>; | ||||
|   | ||||
| @@ -74,6 +74,28 @@ function deserialize_cc_arduino_cli_commands_v1_BoardDetailsResponse(buffer_arg) | ||||
|   return cc_arduino_cli_commands_v1_board_pb.BoardDetailsResponse.deserializeBinary(new Uint8Array(buffer_arg)); | ||||
| } | ||||
|  | ||||
| function serialize_cc_arduino_cli_commands_v1_BoardIdentifyRequest(arg) { | ||||
|   if (!(arg instanceof cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest)) { | ||||
|     throw new Error('Expected argument of type cc.arduino.cli.commands.v1.BoardIdentifyRequest'); | ||||
|   } | ||||
|   return Buffer.from(arg.serializeBinary()); | ||||
| } | ||||
|  | ||||
| function deserialize_cc_arduino_cli_commands_v1_BoardIdentifyRequest(buffer_arg) { | ||||
|   return cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest.deserializeBinary(new Uint8Array(buffer_arg)); | ||||
| } | ||||
|  | ||||
| function serialize_cc_arduino_cli_commands_v1_BoardIdentifyResponse(arg) { | ||||
|   if (!(arg instanceof cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse)) { | ||||
|     throw new Error('Expected argument of type cc.arduino.cli.commands.v1.BoardIdentifyResponse'); | ||||
|   } | ||||
|   return Buffer.from(arg.serializeBinary()); | ||||
| } | ||||
|  | ||||
| function deserialize_cc_arduino_cli_commands_v1_BoardIdentifyResponse(buffer_arg) { | ||||
|   return cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse.deserializeBinary(new Uint8Array(buffer_arg)); | ||||
| } | ||||
|  | ||||
| function serialize_cc_arduino_cli_commands_v1_BoardListAllRequest(arg) { | ||||
|   if (!(arg instanceof cc_arduino_cli_commands_v1_board_pb.BoardListAllRequest)) { | ||||
|     throw new Error('Expected argument of type cc.arduino.cli.commands.v1.BoardListAllRequest'); | ||||
| @@ -1282,6 +1304,18 @@ boardSearch: { | ||||
|     responseSerialize: serialize_cc_arduino_cli_commands_v1_BoardSearchResponse, | ||||
|     responseDeserialize: deserialize_cc_arduino_cli_commands_v1_BoardSearchResponse, | ||||
|   }, | ||||
|   // Identify a board using the given properties. | ||||
| boardIdentify: { | ||||
|     path: '/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardIdentify', | ||||
|     requestStream: false, | ||||
|     responseStream: false, | ||||
|     requestType: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyRequest, | ||||
|     responseType: cc_arduino_cli_commands_v1_board_pb.BoardIdentifyResponse, | ||||
|     requestSerialize: serialize_cc_arduino_cli_commands_v1_BoardIdentifyRequest, | ||||
|     requestDeserialize: deserialize_cc_arduino_cli_commands_v1_BoardIdentifyRequest, | ||||
|     responseSerialize: serialize_cc_arduino_cli_commands_v1_BoardIdentifyResponse, | ||||
|     responseDeserialize: deserialize_cc_arduino_cli_commands_v1_BoardIdentifyResponse, | ||||
|   }, | ||||
|   // List boards connection and disconnected events. | ||||
| boardListWatch: { | ||||
|     path: '/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardListWatch', | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import yaml from 'js-yaml'; | ||||
| import { injectable, inject, named } from '@theia/core/shared/inversify'; | ||||
| import URI from '@theia/core/lib/common/uri'; | ||||
| import { ILogger } from '@theia/core/lib/common/logger'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { Event, Emitter } from '@theia/core/lib/common/event'; | ||||
| import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application'; | ||||
| import { | ||||
|   | ||||
| @@ -5,12 +5,13 @@ import { | ||||
|   Disposable, | ||||
|   DisposableCollection, | ||||
| } from '@theia/core/lib/common/disposable'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { nls } from '@theia/core/lib/common/nls'; | ||||
| import type { Mutable } from '@theia/core/lib/common/types'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import * as jspb from 'google-protobuf'; | ||||
| import path from 'node:path'; | ||||
| import { userAbort } from '../common/nls'; | ||||
| import { | ||||
|   UploadResponse as ApiUploadResponse, | ||||
|   OutputMessage, | ||||
| @@ -26,6 +27,7 @@ import { | ||||
|   isCompileSummary, | ||||
|   isUploadResponse, | ||||
| } from '../common/protocol/core-service'; | ||||
| import { UserAbortApplicationError } from '../common/protocol/progressible'; | ||||
| import { ResponseService } from '../common/protocol/response-service'; | ||||
| import { firstToUpperCase, notEmpty } from '../common/utils'; | ||||
| import { BoardDiscovery, createApiPort } from './board-discovery'; | ||||
| @@ -52,8 +54,6 @@ import { ExecuteWithProgress, ProgressResponse } from './grpc-progressible'; | ||||
| import { MonitorManager } from './monitor-manager'; | ||||
| import { ServiceError } from './service-error'; | ||||
| import { AutoFlushingBuffer } from './utils/buffers'; | ||||
| import { userAbort } from '../common/nls'; | ||||
| import { UserAbortApplicationError } from '../common/protocol/progressible'; | ||||
|  | ||||
| namespace Uploadable { | ||||
|   export type Request = UploadRequest | UploadUsingProgrammerRequest; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import { | ||||
| } from '@theia/core/shared/inversify'; | ||||
| import { join } from 'node:path'; | ||||
| import fs from 'node:fs'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { | ||||
|   SketchRef, | ||||
|   SketchContainer, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { ExecutableService } from '../common/protocol/executable-service'; | ||||
| import { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import { | ||||
|   postConstruct, | ||||
| } from '@theia/core/shared/inversify'; | ||||
| import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { promisify } from 'util'; | ||||
| import { MonitorSettingsProvider } from './monitor-settings-provider'; | ||||
| import { Deferred } from '@theia/core/lib/common/promise-util'; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { FileSystemExt } from '../common/protocol/filesystem-ext'; | ||||
|  | ||||
| @injectable() | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { inject, injectable } from '@theia/core/shared/inversify'; | ||||
| import { promises as fs } from 'node:fs'; | ||||
| import { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import { Deferred } from '@theia/core/lib/common/promise-util'; | ||||
| import { escapeRegExpCharacters } from '@theia/core/lib/common/strings'; | ||||
| import type { Mutable } from '@theia/core/lib/common/types'; | ||||
| import URI from '@theia/core/lib/common/uri'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { inject, injectable, named } from '@theia/core/shared/inversify'; | ||||
| import { glob } from 'glob'; | ||||
| import crypto from 'node:crypto'; | ||||
|   | ||||
| @@ -1,20 +0,0 @@ | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| import { SurveyNotificationService } from '../common/protocol/survey-service'; | ||||
|  | ||||
| /** | ||||
|  * Service for checking if it is the first instance of the IDE, in this case it sets a flag to true. | ||||
|  * This flag is used to prevent the survey notification from being visible in every open window. It must only be shown on one window. | ||||
|  */ | ||||
| @injectable() | ||||
| export class SurveyNotificationServiceImpl | ||||
|   implements SurveyNotificationService | ||||
| { | ||||
|   private surveyDidShow = false; | ||||
|   async isFirstInstance(): Promise<boolean> { | ||||
|     if (this.surveyDidShow) { | ||||
|       return false; | ||||
|     } | ||||
|     this.surveyDidShow = true; | ||||
|     return this.surveyDidShow; | ||||
|   } | ||||
| } | ||||
| @@ -1,7 +1,8 @@ | ||||
| import { MessagingContribution as TheiaMessagingContribution } from '@theia/core/lib/node/messaging/messaging-contribution'; | ||||
| import { WebsocketEndpoint as TheiaWebsocketEndpoint } from '@theia/core/lib/node/messaging/websocket-endpoint'; | ||||
| import { injectable } from '@theia/core/shared/inversify'; | ||||
| 
 | ||||
| @injectable() | ||||
| export class MessagingContribution extends TheiaMessagingContribution { | ||||
| export class WebsocketEndpoint extends TheiaWebsocketEndpoint { | ||||
|   // https://github.com/eclipse-theia/theia/discussions/11543
 | ||||
|   protected override checkAliveTimeout = process.argv.includes( | ||||
|     '--no-ping-timeout' | ||||
| @@ -5,7 +5,7 @@ import { | ||||
| import { isWindows } from '@theia/core/lib/common/os'; | ||||
| import URI from '@theia/core/lib/common/uri'; | ||||
| import { BackendApplicationConfigProvider } from '@theia/core/lib/node/backend-application-config-provider'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { | ||||
|   inject, | ||||
|   injectable, | ||||
|   | ||||
| @@ -1,42 +0,0 @@ | ||||
| import { join } from 'node:path'; | ||||
| import { interfaces } from '@theia/core/shared/inversify'; | ||||
| import { | ||||
|   NsfwFileSystemWatcherServiceProcessOptions, | ||||
|   NSFW_SINGLE_THREADED, | ||||
|   spawnNsfwFileSystemWatcherServiceProcess, | ||||
| } from '@theia/filesystem/lib/node/filesystem-backend-module'; | ||||
| import { FileSystemWatcherService } from '@theia/filesystem/lib/common/filesystem-watcher-protocol'; | ||||
| import { NsfwFileSystemWatcherServerOptions } from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service'; | ||||
| import { FileSystemWatcherServiceDispatcher } from '@theia/filesystem/lib/node/filesystem-watcher-dispatcher'; | ||||
| import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-watcher/nsfw-filesystem-service'; | ||||
|  | ||||
| export function rebindNsfwFileSystemWatcher(rebind: interfaces.Rebind): void { | ||||
|   rebind<NsfwFileSystemWatcherServiceProcessOptions>( | ||||
|     NsfwFileSystemWatcherServiceProcessOptions | ||||
|   ).toConstantValue({ | ||||
|     entryPoint: join(__dirname, 'nsfw-watcher'), | ||||
|   }); | ||||
|   rebind<FileSystemWatcherService>(FileSystemWatcherService) | ||||
|     .toDynamicValue((context) => | ||||
|       NSFW_SINGLE_THREADED | ||||
|         ? createNsfwFileSystemWatcherService(context) | ||||
|         : spawnNsfwFileSystemWatcherServiceProcess(context) | ||||
|     ) | ||||
|     .inSingletonScope(); | ||||
| } | ||||
|  | ||||
| function createNsfwFileSystemWatcherService({ | ||||
|   container, | ||||
| }: interfaces.Context): FileSystemWatcherService { | ||||
|   const options = container.get<NsfwFileSystemWatcherServerOptions>( | ||||
|     NsfwFileSystemWatcherServerOptions | ||||
|   ); | ||||
|   const dispatcher = container.get<FileSystemWatcherServiceDispatcher>( | ||||
|     FileSystemWatcherServiceDispatcher | ||||
|   ); | ||||
|   const server = new NoDelayDisposalTimeoutNsfwFileSystemWatcherService( | ||||
|     options | ||||
|   ); | ||||
|   server.setClient(dispatcher); | ||||
|   return server; | ||||
| } | ||||
| @@ -0,0 +1,42 @@ | ||||
| import { join } from 'node:path'; | ||||
| import { interfaces } from '@theia/core/shared/inversify'; | ||||
| import { | ||||
|   FileSystemWatcherServiceProcessOptions, | ||||
|   WATCHER_SINGLE_THREADED, | ||||
|   spawnParcelFileSystemWatcherServiceProcess, | ||||
| } from '@theia/filesystem/lib/node/filesystem-backend-module'; | ||||
| import { FileSystemWatcherService } from '@theia/filesystem/lib/common/filesystem-watcher-protocol'; | ||||
| import { ParcelFileSystemWatcherServerOptions } from '@theia/filesystem/lib/node/parcel-watcher/parcel-filesystem-service'; | ||||
| import { FileSystemWatcherServiceDispatcher } from '@theia/filesystem/lib/node/filesystem-watcher-dispatcher'; | ||||
| import { NoDelayDisposalTimeoutParcelFileSystemWatcherService } from './parcel-watcher/parcel-filesystem-service'; | ||||
|  | ||||
| export function rebindParcelFileSystemWatcher(rebind: interfaces.Rebind): void { | ||||
|   rebind<FileSystemWatcherServiceProcessOptions>( | ||||
|     FileSystemWatcherServiceProcessOptions | ||||
|   ).toConstantValue({ | ||||
|     entryPoint: join(__dirname, 'parcel-watcher'), | ||||
|   }); | ||||
|   rebind<FileSystemWatcherService>(FileSystemWatcherService) | ||||
|     .toDynamicValue((context) => | ||||
|       WATCHER_SINGLE_THREADED | ||||
|         ? createParcelFileSystemWatcherService(context) | ||||
|         : spawnParcelFileSystemWatcherServiceProcess(context) | ||||
|     ) | ||||
|     .inSingletonScope(); | ||||
| } | ||||
|  | ||||
| function createParcelFileSystemWatcherService({ | ||||
|   container, | ||||
| }: interfaces.Context): FileSystemWatcherService { | ||||
|   const options = container.get<ParcelFileSystemWatcherServerOptions>( | ||||
|     ParcelFileSystemWatcherServerOptions | ||||
|   ); | ||||
|   const dispatcher = container.get<FileSystemWatcherServiceDispatcher>( | ||||
|     FileSystemWatcherServiceDispatcher | ||||
|   ); | ||||
|   const server = new NoDelayDisposalTimeoutParcelFileSystemWatcherService( | ||||
|     options | ||||
|   ); | ||||
|   server.setClient(dispatcher); | ||||
|   return server; | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| import * as yargs from '@theia/core/shared/yargs'; | ||||
| import { JsonRpcProxyFactory } from '@theia/core/lib/common/messaging/proxy-factory'; | ||||
| import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-filesystem-service'; | ||||
| import { NoDelayDisposalTimeoutParcelFileSystemWatcherService } from './parcel-filesystem-service'; | ||||
| import type { IPCEntryPoint } from '@theia/core/lib/node/messaging/ipc-protocol'; | ||||
| import type { FileSystemWatcherServiceClient } from '@theia/filesystem/lib/common/filesystem-watcher-protocol'; | ||||
| 
 | ||||
| @@ -20,7 +20,7 @@ const options: { | ||||
|   }).argv as any; | ||||
| 
 | ||||
| export default <IPCEntryPoint>((connection) => { | ||||
|   const server = new NoDelayDisposalTimeoutNsfwFileSystemWatcherService( | ||||
|   const server = new NoDelayDisposalTimeoutParcelFileSystemWatcherService( | ||||
|     options | ||||
|   ); | ||||
|   const factory = new JsonRpcProxyFactory<FileSystemWatcherServiceClient>( | ||||
| @@ -1,26 +1,26 @@ | ||||
| import { Minimatch } from 'minimatch'; | ||||
| import type { WatchOptions } from '@theia/filesystem/lib/common/filesystem-watcher-protocol'; | ||||
| import { | ||||
|   NsfwFileSystemWatcherService, | ||||
|   NsfwWatcher, | ||||
| } from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service'; | ||||
|   ParcelFileSystemWatcherService, | ||||
|   ParcelWatcher, | ||||
| } from '@theia/filesystem/lib/node/parcel-watcher/parcel-filesystem-service'; | ||||
| 
 | ||||
| // Dispose the watcher immediately when the last reference is removed. By default, Theia waits 10 sec.
 | ||||
| // https://github.com/eclipse-theia/theia/issues/11639#issuecomment-1238980708
 | ||||
| const NoDelay = 0; | ||||
| 
 | ||||
| export class NoDelayDisposalTimeoutNsfwFileSystemWatcherService extends NsfwFileSystemWatcherService { | ||||
| export class NoDelayDisposalTimeoutParcelFileSystemWatcherService extends ParcelFileSystemWatcherService { | ||||
|   protected override createWatcher( | ||||
|     clientId: number, | ||||
|     fsPath: string, | ||||
|     options: WatchOptions | ||||
|   ): NsfwWatcher { | ||||
|   ): ParcelWatcher { | ||||
|     const watcherOptions = { | ||||
|       ignored: options.ignored.map( | ||||
|         (pattern) => new Minimatch(pattern, { dot: true }) | ||||
|       ), | ||||
|     }; | ||||
|     return new NsfwWatcher( | ||||
|     return new ParcelWatcher( | ||||
|       clientId, | ||||
|       fsPath, | ||||
|       watcherOptions, | ||||
| @@ -83,7 +83,9 @@ const cortexDebugMapper: PluginContributionMapper = ( | ||||
|   } | ||||
|   for (const _debugger of contribution.debuggers ?? []) { | ||||
|     if (_debugger.type === 'cortex-debug') { | ||||
|       for (const attributes of _debugger.configurationAttributes ?? []) { | ||||
|       for (const attributes of Object.values( | ||||
|         _debugger.configurationAttributes ?? {} | ||||
|       )) { | ||||
|         if (attributes.properties) { | ||||
|           // Patch the cortex-debug debug config schema to allow the in-house `configId`. | ||||
|           attributes.properties['configId'] = { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import { | ||||
|   Disposable, | ||||
|   DisposableCollection, | ||||
| } from '@theia/core/lib/common/disposable'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { expect } from 'chai'; | ||||
| import { promises as fs } from 'node:fs'; | ||||
| import path from 'node:path'; | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import type { MaybePromise } from '@theia/core/lib/common/types'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { Container } from '@theia/core/shared/inversify'; | ||||
| import { expect } from 'chai'; | ||||
| import { dump, load } from 'js-yaml'; | ||||
| import { promises as fs } from 'node:fs'; | ||||
| import { join } from 'node:path'; | ||||
| import { sync as deleteSync } from 'rimraf'; | ||||
| import { rimrafSync } from 'rimraf'; | ||||
| import { | ||||
|   BoardsService, | ||||
|   CoreService, | ||||
| @@ -65,7 +65,7 @@ describe('core-client-provider', () => { | ||||
|   it("should recover when the 'directories.data' folder is missing", async function () { | ||||
|     this.timeout(timeout); | ||||
|     const configDirPath = await prepareTestConfigDir(); | ||||
|     deleteSync(join(configDirPath, 'data')); | ||||
|     rimrafSync(join(configDirPath, 'data')); | ||||
|  | ||||
|     const container = await startCli(configDirPath, toDispose); | ||||
|     await assertFunctionalCli(container, ({ coreClientProvider }) => { | ||||
| @@ -84,7 +84,7 @@ describe('core-client-provider', () => { | ||||
|       'Arduino15', | ||||
|       'package_index.json' | ||||
|     ); | ||||
|     deleteSync(primaryPackageIndexPath); | ||||
|     rimrafSync(primaryPackageIndexPath); | ||||
|  | ||||
|     const container = await startCli(configDirPath, toDispose); | ||||
|     await assertFunctionalCli(container, ({ coreClientProvider }) => { | ||||
| @@ -118,7 +118,7 @@ describe('core-client-provider', () => { | ||||
|         'tools', | ||||
|         tool | ||||
|       ); | ||||
|       deleteSync(builtinToolsPath); | ||||
|       rimrafSync(builtinToolsPath); | ||||
|  | ||||
|       const container = await startCli(configDirPath, toDispose); | ||||
|       await assertFunctionalCli(container, ({ coreClientProvider }) => { | ||||
| @@ -140,7 +140,7 @@ describe('core-client-provider', () => { | ||||
|       'Arduino15', | ||||
|       'library_index.json' | ||||
|     ); | ||||
|     deleteSync(libraryPackageIndexPath); | ||||
|     rimrafSync(libraryPackageIndexPath); | ||||
|  | ||||
|     const container = await startCli(configDirPath, toDispose); | ||||
|     await assertFunctionalCli(container, ({ coreClientProvider }) => { | ||||
| @@ -176,7 +176,7 @@ describe('core-client-provider', () => { | ||||
|       'Arduino15', | ||||
|       'package_teensy_index.json' | ||||
|     ); | ||||
|     deleteSync(thirdPartyPackageIndexPath); | ||||
|     rimrafSync(thirdPartyPackageIndexPath); | ||||
|  | ||||
|     const container = await startCli(configDirPath, toDispose); | ||||
|     await assertFunctionalCli( | ||||
| @@ -193,7 +193,7 @@ describe('core-client-provider', () => { | ||||
|   it("should recover when invalid 3rd package URL is defined in the CLI config and the 'directories.data' folder is missing", async function () { | ||||
|     this.timeout(timeout); | ||||
|     const configDirPath = await prepareTestConfigDir(); | ||||
|     deleteSync(join(configDirPath, 'data')); | ||||
|     rimrafSync(join(configDirPath, 'data')); | ||||
|  | ||||
|     // set an invalid URL so the CLI will try to download it | ||||
|     const cliConfigPath = join(configDirPath, 'arduino-cli.yaml'); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { DisposableCollection } from '@theia/core/lib/common/disposable'; | ||||
| import { isWindows } from '@theia/core/lib/common/os'; | ||||
| import { FileUri } from '@theia/core/lib/node/file-uri'; | ||||
| import { FileUri } from '@theia/core/lib/common/file-uri'; | ||||
| import { Container } from '@theia/core/shared/inversify'; | ||||
| import { expect } from 'chai'; | ||||
| import { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user