From 6497fc915df69faed2ab29d2abc037ba80190a90 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 18 Dec 2024 16:00:22 +0100 Subject: [PATCH 1/7] Add IPC handlers for opening an app and a URL --- backend/ipc.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/backend/ipc.js b/backend/ipc.js index 62a404f..1e0ee53 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -1,6 +1,7 @@ const fs = require('fs') const registerMenu = require('./menu.js') const serial = require('./serial/serial.js').sharedInstance +const { shell } = require('electron'); const { openFolderDialog, @@ -138,6 +139,25 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { registerMenu(win, state) }) + ipcMain.handle('launch-app', async (event, urlScheme) => { + // Launch an external app with a custom protocol + return new Promise((resolve, reject) => { + try { + shell.openExternal(urlScheme).then(() => { + resolve(true); // App opened successfully + }).catch(() => { + resolve(false); // App not installed + }); + } catch (err) { + reject(err); + } + }); + }); + + ipcMain.handle('open-url', async (event, url) => { + shell.openExternal(url); + }); + win.on('close', (event) => { console.log('BrowserWindow', 'close') event.preventDefault() From 10f9bf5a5bf43b20f688494c6ca5865b8ec56d8b Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 5 Mar 2025 10:55:54 +0100 Subject: [PATCH 2/7] Expose function to launch app in main world --- preload.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/preload.js b/preload.js index fbc1579..daef453 100644 --- a/preload.js +++ b/preload.js @@ -2,7 +2,7 @@ console.log('preload') const { contextBridge, ipcRenderer } = require('electron') const path = require('path') const shortcuts = require('./backend/shortcuts.js').shortcuts.global -const { emit, platform } = require('process') +const { platform } = require('process') const SerialBridge = require('./backend/serial/serial-bridge.js') const Disk = { @@ -85,6 +85,21 @@ const Window = { getShortcuts: () => shortcuts } +/** + * Launches an app using the provided URL scheme (e.g. myapp://). If the app is not installed, it will + * fallback to open the provided fallback URL. + * @param {string} url The URL scheme to use to launch the app + * @param {string} fallbackUrl The URL to open if the app is not installed + */ +async function launchApp(url, fallbackUrl) { + const success = await ipcRenderer.invoke('launch-app', url); + + if (!success) { + await ipcRenderer.invoke('open-url', fallbackUrl); // Fallback to open a URL in the default browser + } +} + +contextBridge.exposeInMainWorld('launchApp', launchApp) contextBridge.exposeInMainWorld('BridgeSerial', SerialBridge) contextBridge.exposeInMainWorld('BridgeDisk', Disk) contextBridge.exposeInMainWorld('BridgeWindow', Window) \ No newline at end of file From 3ccc7234271b47eac746b1c6d4621139dfba70ff Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 18 Dec 2024 16:04:57 +0100 Subject: [PATCH 3/7] Add event handler for launching an app --- ui/arduino/store.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index 6fdf059..5b8e45d 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -116,6 +116,10 @@ async function store(state, emitter) { updateMenu() }) + emitter.on('launch-app', async (url, fallbackUrl) => { + window.launchApp(url, fallbackUrl) + }) + // CONNECTION DIALOG emitter.on('open-connection-dialog', async () => { log('open-connection-dialog') From f5b23e4d3c919d0039f8e64ade6dc56becce8f80 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 5 Mar 2025 10:58:20 +0100 Subject: [PATCH 4/7] Add button to launch package installer --- ui/arduino/media/install-package.svg | 33 ++++++++++++++++++++++++++ ui/arduino/views/components/toolbar.js | 12 ++++++++++ 2 files changed, 45 insertions(+) create mode 100644 ui/arduino/media/install-package.svg diff --git a/ui/arduino/media/install-package.svg b/ui/arduino/media/install-package.svg new file mode 100644 index 0000000..f26feff --- /dev/null +++ b/ui/arduino/media/install-package.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index a0b8a45..0f3c4d1 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -90,6 +90,18 @@ function Toolbar(state, emit) { })} + +
+ ${!window.BridgeWindow.isLinux() ? Button({ + icon: 'install-package.svg', + tooltip: `Install Package`, + active: true, + onClick: () => { + if(state.isConnected) emit('disconnect') // Package installer requires exclusive access to the serial port + emit('launch-app', 'micropython-package-installer://', 'https://github.com/arduino/lab-micropython-package-installer/releases/latest') + } + }) : '' } +
` } From 3f2636ed2ae308785647b998e8ea4d8792387f79 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 5 Mar 2025 11:11:29 +0100 Subject: [PATCH 5/7] Add label --- ui/arduino/views/components/toolbar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index 0f3c4d1..c559bc3 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -94,7 +94,7 @@ function Toolbar(state, emit) {
${!window.BridgeWindow.isLinux() ? Button({ icon: 'install-package.svg', - tooltip: `Install Package`, + label: `Install Package`, active: true, onClick: () => { if(state.isConnected) emit('disconnect') // Package installer requires exclusive access to the serial port From 851b10e250facc3d2c9d9578b5f1a09d2971a6f9 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 5 Mar 2025 11:18:16 +0100 Subject: [PATCH 6/7] Move button to primary toolbar actions --- ui/arduino/views/components/toolbar.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index c559bc3..c6bcb89 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -69,6 +69,17 @@ function Toolbar(state, emit) { disabled: !_canSave, onClick: () => emit('save') })} + +
+ + ${!window.BridgeWindow.isLinux() ? Button({ + icon: 'install-package.svg', + label: `Add Package`, + onClick: () => { + if(state.isConnected) emit('disconnect') // Package installer requires exclusive access to the serial port + emit('launch-app', 'micropython-package-installer://', 'https://github.com/arduino/lab-micropython-package-installer/releases/latest') + } + }) : '' }
@@ -88,19 +99,6 @@ function Toolbar(state, emit) { square: true, onClick: () => emit('change-view', 'file-manager') })} - -
- -
- ${!window.BridgeWindow.isLinux() ? Button({ - icon: 'install-package.svg', - label: `Install Package`, - active: true, - onClick: () => { - if(state.isConnected) emit('disconnect') // Package installer requires exclusive access to the serial port - emit('launch-app', 'micropython-package-installer://', 'https://github.com/arduino/lab-micropython-package-installer/releases/latest') - } - }) : '' }
` From b81a84d3a82594a7fce0a0333ec894bbe8d0cbd9 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Wed, 5 Mar 2025 11:56:52 +0100 Subject: [PATCH 7/7] Hiding separator on Linux. Signed-off-by: ubi de feo --- ui/arduino/views/components/toolbar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index c6bcb89..ad72a4f 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -70,7 +70,7 @@ function Toolbar(state, emit) { onClick: () => emit('save') })} -
+ ${!window.BridgeWindow.isLinux() ? html`
` : ''} ${!window.BridgeWindow.isLinux() ? Button({ icon: 'install-package.svg',