diff --git a/.eslintrc.js b/.eslintrc.js index 4bb67da9..f01e4eff 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,7 @@ module.exports = { '.browser_modules/*', 'docs/*', 'scripts/*', + 'browser-app/*', 'electron-app/lib/*', 'electron-app/src-gen/*', 'electron-app/gen-webpack*.js', diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..3c032078 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/.vscode/launch.json b/.vscode/launch.json index 2a8081fb..37a9d9af 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -80,6 +80,37 @@ "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", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b53773f8..1425237a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -15,6 +15,17 @@ "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", @@ -26,6 +37,17 @@ "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", @@ -37,6 +59,14 @@ "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", diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 45e85298..70adb642 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -158,9 +158,11 @@ "frontend": "lib/browser/arduino-ide-frontend-module" }, { + "frontend": "lib/browser/theia/core/browser-menu-module", "frontendElectron": "lib/electron-browser/theia/core/electron-menu-module" }, { + "frontend": "lib/browser/theia/core/browser-window-module", "frontendElectron": "lib/electron-browser/theia/core/electron-window-module" }, { diff --git a/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts b/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts new file mode 100644 index 00000000..869be3e3 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts @@ -0,0 +1,26 @@ +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); + } + } +} \ No newline at end of file diff --git a/arduino-ide-extension/src/browser/theia/core/browser-menu-module.ts b/arduino-ide-extension/src/browser/theia/core/browser-menu-module.ts new file mode 100644 index 00000000..755d71b1 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/browser-menu-module.ts @@ -0,0 +1,18 @@ +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(); +}); \ No newline at end of file diff --git a/arduino-ide-extension/src/browser/theia/core/browser-window-module.ts b/arduino-ide-extension/src/browser/theia/core/browser-window-module.ts new file mode 100644 index 00000000..e69de29b diff --git a/arduino-ide-extension/src/browser/theia/core/default-window-service.ts b/arduino-ide-extension/src/browser/theia/core/default-window-service.ts new file mode 100644 index 00000000..c256e97a --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/default-window-service.ts @@ -0,0 +1,17 @@ +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 { + return true; + } +} \ No newline at end of file diff --git a/browser-app/package.json b/browser-app/package.json new file mode 100644 index 00000000..4f319bac --- /dev/null +++ b/browser-app/package.json @@ -0,0 +1,63 @@ +{ + "private": true, + "name": "browser-app", + "version": "2.0.0", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@theia/core": "1.41.0", + "@theia/debug": "1.41.0", + "@theia/editor": "1.41.0", + "@theia/file-search": "1.41.0", + "@theia/filesystem": "1.41.0", + "@theia/keymaps": "1.41.0", + "@theia/messages": "1.41.0", + "@theia/monaco": "1.41.0", + "@theia/navigator": "1.41.0", + "@theia/plugin-ext": "1.41.0", + "@theia/plugin-ext-vscode": "1.41.0", + "@theia/preferences": "1.41.0", + "@theia/process": "1.41.0", + "@theia/terminal": "1.41.0", + "@theia/workspace": "1.41.0", + "arduino-ide-extension": "2.3.5" + }, + "devDependencies": { + "@theia/cli": "1.41.0" + }, + "scripts": { + "prepare": "theia build --mode development", + "start": "theia start --plugins=local-dir:../plugins", + "watch": "theia build --watch --mode development" + }, + "theia": { + "frontend": { + "config": { + "applicationName": "Arduino IDE", + "defaultTheme": "arduino-theme", + "preferences": { + "files.autoSave": "afterDelay", + "editor.minimap.enabled": false, + "editor.tabSize": 2, + "editor.scrollBeyondLastLine": false, + "editor.quickSuggestions": { + "other": false, + "comments": false, + "strings": false + }, + "breadcrumbs.enabled": false + } + } + }, + "backend": { + "config": { + "configDirName": ".arduinoIDE" + } + }, + "generator": { + "config": { + "preloadTemplate": "
" + } + } + } + } + \ No newline at end of file diff --git a/browser-app/webpack.config.js b/browser-app/webpack.config.js new file mode 100644 index 00000000..38baa16f --- /dev/null +++ b/browser-app/webpack.config.js @@ -0,0 +1,20 @@ +/** + * This file can be edited to customize webpack configuration. + * To reset delete this file and rerun theia build again. + */ +// @ts-check +const config = require('./gen-webpack.config.js'); + +config.resolve.fallback['http'] = false; +config.resolve.fallback['fs'] = false; + +/** + * Expose bundled modules on window.theia.moduleName namespace, e.g. + * window['theia']['@theia/core/lib/common/uri']. + * Such syntax can be used by external code, for instance, for testing. +config.module.rules.push({ + test: /\.js$/, + loader: require.resolve('@theia/application-manager/lib/expose-loader') +}); */ + +module.exports = config; \ No newline at end of file diff --git a/package.json b/package.json index 6f66bf55..19abe81c 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ }, "scripts": { "prepare": "lerna run prepare", - "cleanup": "rimraf ./**/node_modules && rm -rf ./node_modules ./.browser_modules ./arduino-ide-extension/build ./arduino-ide-extension/downloads ./arduino-ide-extension/Examples ./arduino-ide-extension/lib ./electron-app/lib ./electron-app/src-gen ./electron-app/gen-webpack.config.js", + "cleanup": "rimraf ./**/node_modules && rm -rf ./node_modules ./.browser_modules ./arduino-ide-extension/build ./arduino-ide-extension/downloads ./arduino-ide-extension/Examples ./arduino-ide-extension/lib ./electron-app/lib ./electron-app/src-gen ./electron-app/gen-webpack.config.js ./browser-app/lib ./browser-app/src-gen ./browser-app/gen-webpack.config.js", "rebuild:browser": "theia rebuild:browser", "rebuild:electron": "theia rebuild:electron", "start": "yarn --cwd ./electron-app start", @@ -54,7 +54,7 @@ "test": "lerna run test", "test:slow": "lerna run test:slow", "update:version": "node ./scripts/update-version.js", - "i18n:generate": "theia nls-extract -e vscode -f \"+(arduino-ide-extension|electron-app|plugins)/**/*.ts?(x)\" -o ./i18n/en.json", + "i18n:generate": "theia nls-extract -e vscode -f \"+(arduino-ide-extension|browser-app|electron-app|plugins)/**/*.ts?(x)\" -o ./i18n/en.json", "i18n:check": "yarn i18n:generate && git add -N ./i18n && git diff --exit-code ./i18n", "i18n:push": "node ./scripts/i18n/transifex-push.js ./i18n/en.json", "i18n:pull": "node ./scripts/i18n/transifex-pull.js ./i18n/", @@ -74,6 +74,7 @@ }, "workspaces": [ "arduino-ide-extension", - "electron-app" + "electron-app", + "browser-app" ] } diff --git a/scripts/update-version.js b/scripts/update-version.js index e787dba4..be0de261 100644 --- a/scripts/update-version.js +++ b/scripts/update-version.js @@ -38,6 +38,7 @@ console.log( for (const toUpdate of [ path.join(repoRootPath, 'package.json'), path.join(repoRootPath, 'electron-app', 'package.json'), + path.join(repoRootPath, 'browser-app', 'package.json'), path.join(repoRootPath, 'arduino-ide-extension', 'package.json'), ]) { process.stdout.write(` Updating ${toUpdate}'...`);