From e159d5fa9609bfa66809b7b097d52d8116b624de Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:22:58 +0100 Subject: [PATCH 01/22] Implemented keyboard shortcuts. Signed-off-by: ubi de feo --- backend/ipc.js | 6 ++++ index.js | 48 ++++++++++++++++++++++++-- preload.js | 25 ++++++++++++-- ui/arduino/main.js | 6 +++- ui/arduino/store.js | 44 +++++++++++++++++++++++ ui/arduino/views/components/toolbar.js | 13 +++---- 6 files changed, 131 insertions(+), 11 deletions(-) diff --git a/backend/ipc.js b/backend/ipc.js index 8bace22..467cbff 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -129,9 +129,15 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { return response != opt.cancelId }) + ipcMain.handle('reload', (event, message = 'ciao, cane') => { + console.log('reload?') + win.webContents.send('reload', message) + }) + win.on('close', (event) => { console.log('BrowserWindow', 'close') event.preventDefault() win.webContents.send('check-before-close') }) + } diff --git a/index.js b/index.js index 57eba4c..dcf8def 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, ipcMain, dialog } = require('electron') +const { app, BrowserWindow, ipcMain, dialog, globalShortcut } = require('electron') const path = require('path') const fs = require('fs') @@ -57,4 +57,48 @@ function createWindow () { }) } -app.on('ready', createWindow) +function shortcutAction(key) { + win.webContents.send('shortcut-cmd', key); +} + +// Shortcuts +function registerShortcuts() { + globalShortcut.register('CommandOrControl+R', () => { + console.log('Running Program') + shortcutAction('r') + }) + globalShortcut.register('CommandOrControl+H', () => { + console.log('Stopping Program (Halt)') + shortcutAction('h') + }) + globalShortcut.register('CommandOrControl+S', () => { + console.log('Saving File') + shortcutAction('s') + }) + + globalShortcut.register('CommandOrControl+Shift+R', () => { + console.log('Resetting Board') + shortcutAction('R') + }) + globalShortcut.register('CommandOrControl+Shift+C', () => { + console.log('Connect to Board') + shortcutAction('C') + }) + globalShortcut.register('CommandOrControl+Shift+D', () => { + console.log('Disconnect from Board') + shortcutAction('D') + }) +} + +app.on('ready', () => { + createWindow() + registerShortcuts() + + win.on('focus', () => { + registerShortcuts() + }) + win.on('blur', () => { + globalShortcut.unregisterAll() + }) + +}) \ No newline at end of file diff --git a/preload.js b/preload.js index ddcb8aa..0ed2abb 100644 --- a/preload.js +++ b/preload.js @@ -3,6 +3,8 @@ const { contextBridge, ipcRenderer } = require('electron') const path = require('path') const MicroPython = require('micropython.js') +const { emit, platform } = require('process') +// const { platform } = requireprocess.platform const board = new MicroPython() board.chunk_size = 192 board.chunk_sleep = 200 @@ -155,12 +157,31 @@ const Window = { setWindowSize: (minWidth, minHeight) => { ipcRenderer.invoke('set-window-size', minWidth, minHeight) }, + anyShortcut: (callback, key) => { + ipcRenderer.on('shortcut-cmd', (event, k) => { + // Get the active element + const activeElement = document.activeElement; + // Check if the active element is the terminal + const isTerminalFocused = activeElement.classList.contains('xterm-helper-textarea'); + // Only trigger callback if terminal is not focused AND we're in editor view + if (!isTerminalFocused) { + console.log('shortcut-cmd-r executed') + callback(k); + } + }) + }, + + beforeClose: (callback) => ipcRenderer.on('check-before-close', callback), confirmClose: () => ipcRenderer.invoke('confirm-close'), isPackaged: () => ipcRenderer.invoke('is-packaged'), - openDialog: (opt) => ipcRenderer.invoke('open-dialog', opt) -} + openDialog: (opt) => ipcRenderer.invoke('open-dialog', opt), + getOS: () => platform, + isWindows: () => platform === 'win32', + isMac: () => platform === 'darwin', + isLinux: () => platform === 'linux' +} contextBridge.exposeInMainWorld('BridgeSerial', Serial) contextBridge.exposeInMainWorld('BridgeDisk', Disk) diff --git a/ui/arduino/main.js b/ui/arduino/main.js index bf693df..267e6d1 100644 --- a/ui/arduino/main.js +++ b/ui/arduino/main.js @@ -46,11 +46,15 @@ window.addEventListener('load', () => { app.use(store); app.route('*', App) app.mount('#app') - app.emitter.on('DOMContentLoaded', () => { if (app.state.diskNavigationRoot) { app.emitter.emit('refresh-files') } }) + app.emitter.on('', () => { + if (app.state.diskNavigationRoot) { + app.emitter.emit('refresh-files') + } + }) }) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index c748905..be77d8f 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -24,6 +24,7 @@ async function confirm(msg, cancelMsg, confirmMsg) { async function store(state, emitter) { win.setWindowSize(720, 640) + state.platform = window.BridgeWindow.getOS() state.view = 'editor' state.diskNavigationPath = '/' state.diskNavigationRoot = getDiskNavigationRootFromStorage() @@ -57,6 +58,8 @@ async function store(state, emitter) { state.isTerminalBound = false + state.shortcutsContext = 'editor' + const newFile = createEmptyFile({ parentFolder: null, // Null parent folder means not saved? source: 'disk' @@ -1360,6 +1363,47 @@ async function store(state, emitter) { await win.confirmClose() }) + // win.shortcutCmdR(() => { + // // Only run if we can execute + + // }) + + win.anyShortcut((key) => { + if (key === 'C') { + emitter.emit('open-connection-dialog') + } + if (key === 'D') { + emitter.emit('disconnect') + } + if (key === 'R') { + if (state.view != 'editor') return + emitter.emit('reset') + } + if (key === 'r') { + if (state.view != 'editor') return + runCode() + } + if (key === 'h') { + if (state.view != 'editor') return + stopCode() + } + if (key === 's') { + if (state.view != 'editor') return + emitter.emit('save') + } + + }) + + function runCode() { + if (canExecute({ view: state.view, isConnected: state.isConnected })) { + emitter.emit('run') + } + } + function stopCode() { + if (canExecute({ view: state.view, isConnected: state.isConnected })) { + emitter.emit('stop') + } + } function createFile(args) { const { source, diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index 3512ef9..fa8e87e 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -9,12 +9,13 @@ function Toolbar(state, emit) { view: state.view, isConnected: state.isConnected }) - + const metaKeyString = state.platform === 'darwin' ? 'Cmd' : 'Ctrl' + return html`
${Button({ icon: state.isConnected ? 'connect.svg' : 'disconnect.svg', - tooltip: state.isConnected ? 'Disconnect' : 'Connect', + tooltip: state.isConnected ? `Disconnect (${metaKeyString}+Shift+D)` : `Connect (${metaKeyString}+Shift+C)`, onClick: () => emit('open-connection-dialog'), active: state.isConnected })} @@ -23,19 +24,19 @@ function Toolbar(state, emit) { ${Button({ icon: 'run.svg', - tooltip: 'Run', + tooltip: `Run (${metaKeyString}+r)`, disabled: !_canExecute, onClick: () => emit('run') })} ${Button({ icon: 'stop.svg', - tooltip: 'Stop', + tooltip: `Stop (${metaKeyString}+h)`, disabled: !_canExecute, onClick: () => emit('stop') })} ${Button({ icon: 'reboot.svg', - tooltip: 'Reset', + tooltip: `Reset (${metaKeyString}+Shift+r)`, disabled: !_canExecute, onClick: () => emit('reset') })} @@ -44,7 +45,7 @@ function Toolbar(state, emit) { ${Button({ icon: 'save.svg', - tooltip: 'Save', + tooltip: `Save (${metaKeyString}+s)`, disabled: !_canSave, onClick: () => emit('save') })} From bfcc2c68d24d33eaeb60f4e0b27c4d5f447cde02 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:31:45 +0100 Subject: [PATCH 02/22] Renamed method to onKeyboardShortcut. Signed-off-by: ubi de feo --- backend/ipc.js | 5 ----- preload.js | 2 +- ui/arduino/store.js | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/backend/ipc.js b/backend/ipc.js index 467cbff..dfe5917 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -129,11 +129,6 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { return response != opt.cancelId }) - ipcMain.handle('reload', (event, message = 'ciao, cane') => { - console.log('reload?') - win.webContents.send('reload', message) - }) - win.on('close', (event) => { console.log('BrowserWindow', 'close') event.preventDefault() diff --git a/preload.js b/preload.js index 0ed2abb..bf31e73 100644 --- a/preload.js +++ b/preload.js @@ -157,7 +157,7 @@ const Window = { setWindowSize: (minWidth, minHeight) => { ipcRenderer.invoke('set-window-size', minWidth, minHeight) }, - anyShortcut: (callback, key) => { + onKeyboardShortcut: (callback, key) => { ipcRenderer.on('shortcut-cmd', (event, k) => { // Get the active element const activeElement = document.activeElement; diff --git a/ui/arduino/store.js b/ui/arduino/store.js index be77d8f..b471329 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1368,7 +1368,7 @@ async function store(state, emitter) { // }) - win.anyShortcut((key) => { + win.onKeyboardShortcut((key) => { if (key === 'C') { emitter.emit('open-connection-dialog') } From c6d8d91d5fe7d243428801d0cc3101d6eac3b743 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:33:20 +0100 Subject: [PATCH 03/22] Removed whitespace. Signed-off-by: ubi de feo --- backend/ipc.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/ipc.js b/backend/ipc.js index dfe5917..cabb54e 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -133,6 +133,5 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { console.log('BrowserWindow', 'close') event.preventDefault() win.webContents.send('check-before-close') - }) - + }) } From 45a582a188b21e84e2e0f64a8688316822f51773 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:33:46 +0100 Subject: [PATCH 04/22] Removed whitespace. Signed-off-by: ubi de feo --- backend/ipc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/ipc.js b/backend/ipc.js index cabb54e..8bace22 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -133,5 +133,5 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { console.log('BrowserWindow', 'close') event.preventDefault() win.webContents.send('check-before-close') - }) + }) } From 4c648a3add143d194f1f6934243db7cbd49a9dee Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:39:56 +0100 Subject: [PATCH 05/22] Removed leftover test code from main.js. Signed-off-by: ubi de feo --- ui/arduino/main.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ui/arduino/main.js b/ui/arduino/main.js index 267e6d1..ce52be1 100644 --- a/ui/arduino/main.js +++ b/ui/arduino/main.js @@ -51,10 +51,4 @@ window.addEventListener('load', () => { app.emitter.emit('refresh-files') } }) - app.emitter.on('', () => { - if (app.state.diskNavigationRoot) { - app.emitter.emit('refresh-files') - } - }) - }) From ed7f83955bb127f0cfab2afa0be80b0023708af1 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:43:58 +0100 Subject: [PATCH 06/22] Removed unnecessary shortcutsContext member. --- ui/arduino/store.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index b471329..0a1d337 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -58,8 +58,6 @@ async function store(state, emitter) { state.isTerminalBound = false - state.shortcutsContext = 'editor' - const newFile = createEmptyFile({ parentFolder: null, // Null parent folder means not saved? source: 'disk' From 9a490c23090387e8e814d9b0f0c58e2fe6681a43 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Sun, 8 Dec 2024 23:57:23 +0100 Subject: [PATCH 07/22] Removed accelerator shortcuts from Menu items for Reload and Dev Tools. Signed-off-by: ubi de feo --- backend/menu.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/menu.js b/backend/menu.js index 6b62cdf..6fa13f5 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -10,7 +10,6 @@ module.exports = function registerMenu(win) { submenu: [ { role: 'about'}, { type: 'separator' }, - { role: 'services' }, { type: 'separator' }, { role: 'hide' }, { role: 'hideOthers' }, @@ -54,8 +53,8 @@ module.exports = function registerMenu(win) { { label: 'View', submenu: [ - { role: 'reload' }, - { role: 'toggleDevTools' }, + { role: 'reload', accelerator: '' }, + { role: 'toggleDevTools', accelerator: ''}, { type: 'separator' }, { role: 'resetZoom' }, { role: 'zoomIn' }, From 177b7d1117b9f3e4f561b98ef6a302af385b39dc Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Mon, 9 Dec 2024 08:30:35 +0100 Subject: [PATCH 08/22] Implemented Board menu item. Signed-off-by: ubi de feo --- backend/ipc.js | 5 +++++ backend/menu.js | 38 ++++++++++++++++++++++++++++++++++++-- index.js | 7 ++++++- preload.js | 7 ++++++- ui/arduino/store.js | 13 +++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/backend/ipc.js b/backend/ipc.js index 8bace22..f42e822 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -129,6 +129,11 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { return response != opt.cancelId }) + ipcMain.handle('update-menu-state', (event, state) => { + const registerMenu = require('./menu.js') + registerMenu(win, state) + }) + win.on('close', (event) => { console.log('BrowserWindow', 'close') event.preventDefault() diff --git a/backend/menu.js b/backend/menu.js index 6fa13f5..ef56591 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -2,7 +2,7 @@ const { app, Menu } = require('electron') const path = require('path') const openAboutWindow = require('about-window').default -module.exports = function registerMenu(win) { +module.exports = function registerMenu(win, state = {}) { const isMac = process.platform === 'darwin' const template = [ ...(isMac ? [{ @@ -11,7 +11,7 @@ module.exports = function registerMenu(win) { { role: 'about'}, { type: 'separator' }, { type: 'separator' }, - { role: 'hide' }, + { role: 'hide', accelerator: 'CmdOrCtrl+Shift+H' }, { role: 'hideOthers' }, { role: 'unhide' }, { type: 'separator' }, @@ -50,6 +50,40 @@ module.exports = function registerMenu(win) { ]) ] }, + { + label: 'Board', + submenu: [ + { + label: 'Connect', + accelerator: 'CmdOrCtrl+Shift+C', + click: () => win.webContents.send('shortcut-cmd', 'C') + }, + { + label: 'Disconnect', + accelerator: 'CmdOrCtrl+Shift+D', + click: () => win.webContents.send('shortcut-cmd', 'D') + }, + { role: 'separator' }, + { + label: 'Run', + accelerator: 'CmdOrCtrl+R', + enabled: state.isConnected && state.view === 'editor', + click: () => win.webContents.send('shortcut-cmd', 'r') + }, + { + label: 'Stop', + accelerator: 'CmdOrCtrl+H', + enabled: state.isConnected && state.view === 'editor', + click: () => win.webContents.send('shortcut-cmd', 'h') + }, + { + label: 'Reset', + accelerator: 'CmdOrCtrl+Shift+R', + enabled: state.isConnected && state.view === 'editor', + click: () => win.webContents.send('shortcut-cmd', 'R') + } + ] + }, { label: 'View', submenu: [ diff --git a/index.js b/index.js index dcf8def..68bc3c8 100644 --- a/index.js +++ b/index.js @@ -49,8 +49,13 @@ function createWindow () { win.show() }) + const initialMenuState = { + isConnected: false, + view: 'editor' + } + registerIPCHandlers(win, ipcMain, app, dialog) - registerMenu(win) + registerMenu(win, initialMenuState) app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() diff --git a/preload.js b/preload.js index bf31e73..a88a4dd 100644 --- a/preload.js +++ b/preload.js @@ -180,7 +180,12 @@ const Window = { getOS: () => platform, isWindows: () => platform === 'win32', isMac: () => platform === 'darwin', - isLinux: () => platform === 'linux' + isLinux: () => platform === 'linux', + + updateMenuState: (state) => { + return ipcRenderer.invoke('update-menu-state', state) + } + } contextBridge.exposeInMainWorld('BridgeSerial', Serial) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index 0a1d337..10193fc 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -81,6 +81,14 @@ async function store(state, emitter) { emitter.emit('render') } + // Menu management + const updateMenu = () => { + window.BridgeWindow.updateMenuState({ + isConnected: state.isConnected, + view: state.view + }) + } + // START AND BASIC ROUTING emitter.on('select-disk-navigation-root', async () => { const folder = await selectDiskFolder() @@ -98,6 +106,7 @@ async function store(state, emitter) { emitter.emit('refresh-files') } emitter.emit('render') + updateMenu() }) // CONNECTION DIALOG @@ -143,11 +152,13 @@ async function store(state, emitter) { } // Stop whatever is going on // Recover from getting stuck in raw repl + await serial.getPrompt() clearTimeout(timeout_id) // Connected and ready state.isConnecting = false state.isConnected = true + updateMenu() if (state.view === 'editor' && state.panelHeight <= PANEL_CLOSED) { state.panelHeight = state.savedPanelHeight } @@ -181,6 +192,7 @@ async function store(state, emitter) { state.boardNavigationPath = '/' emitter.emit('refresh-files') emitter.emit('render') + updateMenu() }) emitter.on('connection-timeout', async () => { state.isConnected = false @@ -1646,4 +1658,5 @@ async function getHelperFullPath() { '' ) } + } From c6ec1804ae42b7786cd8a4ac2be3c5de7f736dfc Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Mon, 9 Dec 2024 08:55:42 +0100 Subject: [PATCH 09/22] Menu cleanup. Signed-off-by: ubi de feo --- backend/menu.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/menu.js b/backend/menu.js index ef56591..574a798 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -34,7 +34,6 @@ module.exports = function registerMenu(win, state = {}) { { role: 'copy' }, { role: 'paste' }, ...(isMac ? [ - { role: 'pasteAndMatchStyle' }, { role: 'selectAll' }, { type: 'separator' }, { @@ -108,7 +107,7 @@ module.exports = function registerMenu(win, state = {}) { { type: 'separator' }, { role: 'window' } ] : [ - { role: 'close' } + ]) ] }, From 1fb588e01529cb6c0c4d4ccc146bfdb99a082e89 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Mon, 9 Dec 2024 13:48:32 +0100 Subject: [PATCH 10/22] Added ESC key listener. Enabled it on connection dialog. Signed-off-by: ubi de feo --- index.js | 3 +++ ui/arduino/store.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/index.js b/index.js index 68bc3c8..97cffc5 100644 --- a/index.js +++ b/index.js @@ -92,6 +92,9 @@ function registerShortcuts() { globalShortcut.register('CommandOrControl+Shift+D', () => { console.log('Disconnect from Board') shortcutAction('D') + }), + globalShortcut.register('Escape', () => { + shortcutAction('ESC') }) } diff --git a/ui/arduino/store.js b/ui/arduino/store.js index 10193fc..396050c 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1401,6 +1401,11 @@ async function store(state, emitter) { if (state.view != 'editor') return emitter.emit('save') } + if (key === 'ESC') { + if (state.isConnectionDialogOpen) { + emitter.emit('close-connection-dialog') + } + } }) From 861b658c590bb243ba076157adf9aa1caee9054e Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Mon, 9 Dec 2024 18:34:46 +0100 Subject: [PATCH 11/22] Added Clear Terminal shortcut Meta+k. Signed-off-by: ubi de feo --- index.js | 9 +++++++++ preload.js | 19 +++++++++++-------- ui/arduino/store.js | 9 +++++++++ ui/arduino/views/components/repl-panel.js | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 97cffc5..67375fe 100644 --- a/index.js +++ b/index.js @@ -93,6 +93,15 @@ function registerShortcuts() { console.log('Disconnect from Board') shortcutAction('D') }), + globalShortcut.register('CommandOrControl+K', () => { + console.log('Clear Terminal') + shortcutAction('K') + }), + // Future: Toggle REPL Panel + // globalShortcut.register('CommandOrControl+T', () => { + // console.log('Toggle Terminal') + // shortcutAction('T') + // }), globalShortcut.register('Escape', () => { shortcutAction('ESC') }) diff --git a/preload.js b/preload.js index a88a4dd..dfb48d1 100644 --- a/preload.js +++ b/preload.js @@ -159,15 +159,18 @@ const Window = { }, onKeyboardShortcut: (callback, key) => { ipcRenderer.on('shortcut-cmd', (event, k) => { - // Get the active element - const activeElement = document.activeElement; - // Check if the active element is the terminal - const isTerminalFocused = activeElement.classList.contains('xterm-helper-textarea'); + + // Only trigger callback if terminal is not focused AND we're in editor view - if (!isTerminalFocused) { - console.log('shortcut-cmd-r executed') - callback(k); - } + // This has been deemed unnecessary since there are no real conflicts with the terminal + // The REPL shortcuts Ctrl+a|b|c|d are not used as application shortcuts and will + // only be triggered when the user has focused the REPL + // The code is left here for reference + // const activeElement = document.activeElement; + // const isTerminalFocused = activeElement.classList.contains('xterm-helper-textarea'); + // if (!isTerminalFocused) { + callback(k); + // } }) }, diff --git a/ui/arduino/store.js b/ui/arduino/store.js index 396050c..540c19f 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1389,6 +1389,15 @@ async function store(state, emitter) { if (state.view != 'editor') return emitter.emit('reset') } + if (key === 'K') { + if (state.view != 'editor') return + emitter.emit('clear-terminal') + } + // Future: Toggle REPL panel + // if (key === 'T') { + // if (state.view != 'editor') return + // emitter.emit('clear-terminal') + // } if (key === 'r') { if (state.view != 'editor') return runCode() diff --git a/ui/arduino/views/components/repl-panel.js b/ui/arduino/views/components/repl-panel.js index ac1760c..b56c531 100644 --- a/ui/arduino/views/components/repl-panel.js +++ b/ui/arduino/views/components/repl-panel.js @@ -50,7 +50,7 @@ function ReplOperations(state, emit) { Button({ icon: 'delete.svg', size: 'small', - tooltip: 'Clean', + tooltip: `Clean (${state.platform === 'darwin' ? 'Cmd' : 'Ctrl'}+k)`, onClick: () => emit('clear-terminal') }) ] From afadd3fa9ea7c4bfb87be481ec6d03650bf34d4a Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Tue, 10 Dec 2024 12:54:37 +0100 Subject: [PATCH 12/22] Testing disconnect before manual reload. Signed-off-by: ubi de feo --- backend/ipc.js | 5 +++++ backend/menu.js | 15 ++++++++++++++- index.js | 18 ++++++++++++++++++ preload.js | 9 +++++++++ ui/arduino/store.js | 12 ++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/backend/ipc.js b/backend/ipc.js index f42e822..eefd348 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -139,4 +139,9 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { event.preventDefault() win.webContents.send('check-before-close') }) + + // handle disconnection before reload + ipcMain.handle('prepare-reload', async (event) => { + return win.webContents.send('before-reload') + }) } diff --git a/backend/menu.js b/backend/menu.js index 574a798..6aa2051 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -86,7 +86,20 @@ module.exports = function registerMenu(win, state = {}) { { label: 'View', submenu: [ - { role: 'reload', accelerator: '' }, + { + label: 'Reload', + accelerator: '', + click: async () => { + try { + win.webContents.send('cleanup-before-reload') + setTimeout(() => { + win.reload() + }, 500) + } catch(e) { + console.error('Reload from menu failed:', e) + } + } + }, { role: 'toggleDevTools', accelerator: ''}, { type: 'separator' }, { role: 'resetZoom' }, diff --git a/index.js b/index.js index 67375fe..8c0409e 100644 --- a/index.js +++ b/index.js @@ -49,6 +49,24 @@ function createWindow () { win.show() }) + win.webContents.on('before-reload', async (event) => { + // Prevent the default reload behavior + event.preventDefault() + + try { + // Tell renderer to do cleanup + win.webContents.send('cleanup-before-reload') + + // Wait for cleanup then reload + setTimeout(() => { + // This will trigger a page reload, but won't trigger 'before-reload' again + win.reload() + }, 500) + } catch(e) { + console.error('Reload preparation failed:', e) + } + }) + const initialMenuState = { isConnected: false, view: 'editor' diff --git a/preload.js b/preload.js index dfb48d1..210d81f 100644 --- a/preload.js +++ b/preload.js @@ -174,6 +174,15 @@ const Window = { }) }, + onBeforeReload: (callback) => { + ipcRenderer.on('cleanup-before-reload', async () => { + try { + await callback() + } catch(e) { + console.error('Cleanup before reload failed:', e) + } + }) + }, beforeClose: (callback) => ipcRenderer.on('check-before-close', callback), confirmClose: () => ipcRenderer.invoke('confirm-close'), diff --git a/ui/arduino/store.js b/ui/arduino/store.js index 540c19f..a43cfcc 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1364,6 +1364,18 @@ async function store(state, emitter) { emitter.emit('render') }) + win.onBeforeReload(async () => { + // Perform any cleanup needed + if (state.isConnected) { + await serial.disconnect() + state.isConnected = false + state.panelHeight = PANEL_CLOSED + state.boardFiles = [] + state.boardNavigationPath = '/' + } + // Any other cleanup needed + }) + win.beforeClose(async () => { const hasChanges = !!state.openFiles.find(f => f.hasChanges) if (hasChanges) { From 88fe9a2af3a357f483641fe2700bcdc709d74f31 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Wed, 11 Dec 2024 16:40:54 +0100 Subject: [PATCH 13/22] Implemented ALT option to run code selection. Signed-off-by: ubi de feo --- index.js | 4 ++++ ui/arduino/store.js | 13 +++++++++++-- ui/arduino/views/components/elements/button.js | 2 +- ui/arduino/views/components/toolbar.js | 8 +++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 8c0409e..efb675e 100644 --- a/index.js +++ b/index.js @@ -90,6 +90,10 @@ function registerShortcuts() { console.log('Running Program') shortcutAction('r') }) + globalShortcut.register('CommandOrControl+Alt+R', () => { + console.log('Running Code Selection') + shortcutAction('_r') + }) globalShortcut.register('CommandOrControl+H', () => { console.log('Stopping Program (Halt)') shortcutAction('h') diff --git a/ui/arduino/store.js b/ui/arduino/store.js index fcaa0de..dca01bd 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -203,7 +203,7 @@ async function store(state, emitter) { }) // CODE EXECUTION - emitter.on('run', async () => { + emitter.on('run', async (selection = false) => { log('run') const openFile = state.openFiles.find(f => f.id == state.editingFile) let code = openFile.editor.editor.state.doc.toString() @@ -211,7 +211,7 @@ async function store(state, emitter) { // If there is a selection, run only the selected code const startIndex = openFile.editor.editor.state.selection.ranges[0].from const endIndex = openFile.editor.editor.state.selection.ranges[0].to - if (endIndex - startIndex > 0) { + if (endIndex - startIndex > 0 && selection) { selectedCode = openFile.editor.editor.state.doc.toString().substring(startIndex, endIndex) // Checking to see if the user accidentally double-clicked some whitespace // While a random selection would yield an error when executed, @@ -1430,6 +1430,10 @@ async function store(state, emitter) { if (state.view != 'editor') return runCode() } + if (key === '_r') { + if (state.view != 'editor') return + runCodeSelection() + } if (key === 'h') { if (state.view != 'editor') return stopCode() @@ -1451,6 +1455,11 @@ async function store(state, emitter) { emitter.emit('run') } } + function runCodeSelection() { + if (canExecute({ view: state.view, isConnected: state.isConnected })) { + emitter.emit('run', true) + } + } function stopCode() { if (canExecute({ view: state.view, isConnected: state.isConnected })) { emitter.emit('stop') diff --git a/ui/arduino/views/components/elements/button.js b/ui/arduino/views/components/elements/button.js index 7030d49..3d888dd 100644 --- a/ui/arduino/views/components/elements/button.js +++ b/ui/arduino/views/components/elements/button.js @@ -2,7 +2,7 @@ function Button(args) { const { size = '', icon = 'connect.svg', - onClick = () => false, + onClick = (e) => false, disabled = false, active = false, tooltip, diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index d5f6a7a..b63e243 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -26,7 +26,13 @@ function Toolbar(state, emit) { icon: 'run.svg', tooltip: `Run (${metaKeyString}+r)`, disabled: !_canExecute, - onClick: () => emit('run') + onClick: (e) => { + if (e.altKey) { + emit('run', true) + }else{ + emit('run') + } + } })} ${Button({ icon: 'stop.svg', From 9908d4a7789f0026f41adfa7f86f6e84fcaff9e0 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Thu, 12 Dec 2024 13:40:32 +0100 Subject: [PATCH 14/22] Refactored menu and global shortcuts into constants file. Signed-off-by: ubi de feo --- backend/menu.js | 38 ++++++---- backend/shortcuts.js | 23 ++++++ index.js | 88 +++++++++++++---------- preload.js | 6 +- ui/arduino/store.js | 20 +++--- ui/arduino/views/components/repl-panel.js | 2 +- 6 files changed, 114 insertions(+), 63 deletions(-) create mode 100644 backend/shortcuts.js diff --git a/backend/menu.js b/backend/menu.js index 6aa2051..e7ee2d9 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -1,6 +1,7 @@ const { app, Menu } = require('electron') const path = require('path') const openAboutWindow = require('about-window').default +const shortcuts = require('./shortcuts.js') module.exports = function registerMenu(win, state = {}) { const isMac = process.platform === 'darwin' @@ -54,32 +55,45 @@ module.exports = function registerMenu(win, state = {}) { submenu: [ { label: 'Connect', - accelerator: 'CmdOrCtrl+Shift+C', - click: () => win.webContents.send('shortcut-cmd', 'C') + accelerator: shortcuts.menu.CONNECT, + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.CONNECT) }, { label: 'Disconnect', - accelerator: 'CmdOrCtrl+Shift+D', - click: () => win.webContents.send('shortcut-cmd', 'D') + accelerator: shortcuts.menu.DISCONNECT, + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.DISCONNECT) }, - { role: 'separator' }, + { type: 'separator' }, { label: 'Run', - accelerator: 'CmdOrCtrl+R', + accelerator: shortcuts.menu.RUN, + enabled: state.isConnected && state.view === 'editor', + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.RUN) + }, + { + label: 'Run selection', + accelerator: shortcuts.menu.RUN_SELECTION, enabled: state.isConnected && state.view === 'editor', - click: () => win.webContents.send('shortcut-cmd', 'r') + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.RUN_SELECTION) }, { label: 'Stop', - accelerator: 'CmdOrCtrl+H', + accelerator: shortcuts.menu.STOP, enabled: state.isConnected && state.view === 'editor', - click: () => win.webContents.send('shortcut-cmd', 'h') + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.STOP) }, { label: 'Reset', - accelerator: 'CmdOrCtrl+Shift+R', + accelerator: shortcuts.menu.RESET, + enabled: state.isConnected && state.view === 'editor', + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.RESET) + }, + { type: 'separator' }, + { + label: 'Clear terminal', + accelerator: shortcuts.menu.CLEAR_TERMINAL, enabled: state.isConnected && state.view === 'editor', - click: () => win.webContents.send('shortcut-cmd', 'R') + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.CLEAR_TERMINAL) } ] }, @@ -100,7 +114,7 @@ module.exports = function registerMenu(win, state = {}) { } } }, - { role: 'toggleDevTools', accelerator: ''}, + { role: 'toggleDevTools'}, { type: 'separator' }, { role: 'resetZoom' }, { role: 'zoomIn' }, diff --git a/backend/shortcuts.js b/backend/shortcuts.js new file mode 100644 index 0000000..93026a2 --- /dev/null +++ b/backend/shortcuts.js @@ -0,0 +1,23 @@ +module.exports = { + global: { + CONNECT: 'CommandOrControl+Shift+C', + DISCONNECT: 'CommandOrControl+Shift+D', + SAVE: 'CommandOrControl+S', + RUN: 'CommandOrControl+R', + RUN_SELECTION: 'CommandOrControl+Alt+R', + STOP: 'CommandOrControl+H', + RESET: 'CommandOrControl+Shift+R', + CLEAR_TERMINAL: 'CommandOrControl+L', + ESC: 'Escape' + }, + menu: { + CONNECT: 'CmdOrCtrl+Shift+C', + DISCONNECT: 'CmdOrCtrl+Shift+D', + SAVE: 'CmdOrCtrl+S', + RUN: 'CmdOrCtrl+R', + RUN_SELECTION: 'CmdOrCtrl+Alt+R', + STOP: 'CmdOrCtrl+H', + RESET: 'CmdOrCtrl+Shift+R', + CLEAR_TERMINAL: 'CmdOrCtrl+L', + } +} diff --git a/index.js b/index.js index efb675e..b11d662 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ const { app, BrowserWindow, ipcMain, dialog, globalShortcut } = require('electron') const path = require('path') const fs = require('fs') +const shortcuts = require('./backend/shortcuts.js').global const registerIPCHandlers = require('./backend/ipc.js') const registerMenu = require('./backend/menu.js') @@ -86,47 +87,58 @@ function shortcutAction(key) { // Shortcuts function registerShortcuts() { - globalShortcut.register('CommandOrControl+R', () => { - console.log('Running Program') - shortcutAction('r') - }) - globalShortcut.register('CommandOrControl+Alt+R', () => { - console.log('Running Code Selection') - shortcutAction('_r') - }) - globalShortcut.register('CommandOrControl+H', () => { - console.log('Stopping Program (Halt)') - shortcutAction('h') - }) - globalShortcut.register('CommandOrControl+S', () => { - console.log('Saving File') - shortcutAction('s') + Object.entries(shortcuts).forEach(([command, shortcut]) => { + globalShortcut.register(shortcut, () => { + shortcutAction(shortcut) + }); }) + // shortcuts.forEach(element => { + // globalShortcut.register(element, () => { + + // shortcutAction(element) + // }); + // }); + // globalShortcut.register(shortcuts.RUN, () => { + // console.log('Running Program') + // shortcutAction(shortcuts.RUN) + // }) + // globalShortcut.register('CommandOrControl+Alt+R', () => { + // console.log('Running Code Selection') + // shortcutAction('meta_alt_r') + // }) + // globalShortcut.register('CommandOrControl+H', () => { + // console.log('Stopping Program (Halt)') + // shortcutAction('meta_h') + // }) + // globalShortcut.register('CommandOrControl+S', () => { + // console.log('Saving File') + // shortcutAction('meta_s') + // }) - globalShortcut.register('CommandOrControl+Shift+R', () => { - console.log('Resetting Board') - shortcutAction('R') - }) - globalShortcut.register('CommandOrControl+Shift+C', () => { - console.log('Connect to Board') - shortcutAction('C') - }) - globalShortcut.register('CommandOrControl+Shift+D', () => { - console.log('Disconnect from Board') - shortcutAction('D') - }), - globalShortcut.register('CommandOrControl+K', () => { - console.log('Clear Terminal') - shortcutAction('K') - }), - // Future: Toggle REPL Panel - // globalShortcut.register('CommandOrControl+T', () => { - // console.log('Toggle Terminal') - // shortcutAction('T') + // globalShortcut.register('CommandOrControl+Shift+R', () => { + // console.log('Resetting Board') + // shortcutAction('meta_shift_r') + // }) + // globalShortcut.register(shortcuts.CONNECT, () => { + // console.log('Connect to Board') + // shortcutAction(shortcuts.CONNECT) + // }) + // globalShortcut.register(shortcuts.DISCONNECT, () => { + // console.log('Disconnect from Board') + // shortcutAction(shortcuts.DISCONNECT) // }), - globalShortcut.register('Escape', () => { - shortcutAction('ESC') - }) + // globalShortcut.register('CommandOrControl+K', () => { + // console.log('Clear Terminal') + // shortcutAction('K') + // }), + // // Future: Toggle REPL Panel + // // globalShortcut.register('CommandOrControl+T', () => { + // // console.log('Toggle Terminal') + // // shortcutAction('T') + // // }), + // globalShortcut.register('Escape', () => { + // shortcutAction('ESC') + // }) } app.on('ready', () => { diff --git a/preload.js b/preload.js index 210d81f..bf78552 100644 --- a/preload.js +++ b/preload.js @@ -1,7 +1,7 @@ console.log('preload') const { contextBridge, ipcRenderer } = require('electron') const path = require('path') - +const shortcuts = require('./backend/shortcuts.js').global const MicroPython = require('micropython.js') const { emit, platform } = require('process') // const { platform } = requireprocess.platform @@ -196,8 +196,8 @@ const Window = { updateMenuState: (state) => { return ipcRenderer.invoke('update-menu-state', state) - } - + }, + getShortcuts: () => shortcuts } contextBridge.exposeInMainWorld('BridgeSerial', Serial) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index dca01bd..d10304d 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -3,6 +3,8 @@ const serial = window.BridgeSerial const disk = window.BridgeDisk const win = window.BridgeWindow +const shortcuts = window.BridgeWindow.getShortcuts() + const newFileContent = `# This program was created in Arduino Lab for MicroPython print('Hello, MicroPython!') @@ -1407,17 +1409,17 @@ async function store(state, emitter) { // }) win.onKeyboardShortcut((key) => { - if (key === 'C') { + if (key === shortcuts.CONNECT) { emitter.emit('open-connection-dialog') } - if (key === 'D') { + if (key === shortcuts.DISCONNECT) { emitter.emit('disconnect') } - if (key === 'R') { + if (key === shortcuts.RESET) { if (state.view != 'editor') return emitter.emit('reset') } - if (key === 'K') { + if (key === shortcuts.CLEAR_TERMINAL) { if (state.view != 'editor') return emitter.emit('clear-terminal') } @@ -1426,23 +1428,23 @@ async function store(state, emitter) { // if (state.view != 'editor') return // emitter.emit('clear-terminal') // } - if (key === 'r') { + if (key === shortcuts.RUN) { if (state.view != 'editor') return runCode() } - if (key === '_r') { + if (key === shortcuts.RUN_SELECTION) { if (state.view != 'editor') return runCodeSelection() } - if (key === 'h') { + if (key === shortcuts.STOP) { if (state.view != 'editor') return stopCode() } - if (key === 's') { + if (key === shortcuts.SAVE) { if (state.view != 'editor') return emitter.emit('save') } - if (key === 'ESC') { + if (key === shortcuts.ESC) { if (state.isConnectionDialogOpen) { emitter.emit('close-connection-dialog') } diff --git a/ui/arduino/views/components/repl-panel.js b/ui/arduino/views/components/repl-panel.js index b56c531..3974d50 100644 --- a/ui/arduino/views/components/repl-panel.js +++ b/ui/arduino/views/components/repl-panel.js @@ -50,7 +50,7 @@ function ReplOperations(state, emit) { Button({ icon: 'delete.svg', size: 'small', - tooltip: `Clean (${state.platform === 'darwin' ? 'Cmd' : 'Ctrl'}+k)`, + tooltip: `Clean (${state.platform === 'darwin' ? 'Cmd' : 'Ctrl'}+L)`, onClick: () => emit('clear-terminal') }) ] From 0fa99b18b97f80544d501d25c7ba63d0d50608ca Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Thu, 12 Dec 2024 14:03:51 +0100 Subject: [PATCH 15/22] Changed 'selection' to 'onlySelected'. Signed-off-by: ubi de feo --- ui/arduino/store.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index d10304d..aff39ce 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -205,7 +205,7 @@ async function store(state, emitter) { }) // CODE EXECUTION - emitter.on('run', async (selection = false) => { + emitter.on('run', async (onlySelected = false) => { log('run') const openFile = state.openFiles.find(f => f.id == state.editingFile) let code = openFile.editor.editor.state.doc.toString() @@ -213,7 +213,7 @@ async function store(state, emitter) { // If there is a selection, run only the selected code const startIndex = openFile.editor.editor.state.selection.ranges[0].from const endIndex = openFile.editor.editor.state.selection.ranges[0].to - if (endIndex - startIndex > 0 && selection) { + if (endIndex - startIndex > 0 && onlySelected) { selectedCode = openFile.editor.editor.state.doc.toString().substring(startIndex, endIndex) // Checking to see if the user accidentally double-clicked some whitespace // While a random selection would yield an error when executed, From 530dbc693156d36f8af01ec98dc2fa3328893c2c Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Thu, 12 Dec 2024 14:50:13 +0100 Subject: [PATCH 16/22] Moved registerMenu to file scope. Signed-off-by: ubi de feo --- backend/ipc.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/ipc.js b/backend/ipc.js index eefd348..12f2127 100644 --- a/backend/ipc.js +++ b/backend/ipc.js @@ -1,4 +1,6 @@ const fs = require('fs') +const registerMenu = require('./menu.js') + const { openFolderDialog, listFolder, @@ -130,7 +132,6 @@ module.exports = function registerIPCHandlers(win, ipcMain, app, dialog) { }) ipcMain.handle('update-menu-state', (event, state) => { - const registerMenu = require('./menu.js') registerMenu(win, state) }) From a019c999ea42cac6d6c5bada02ab454dbdffbd7d Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Fri, 13 Dec 2024 07:42:37 +0100 Subject: [PATCH 17/22] Only save if openFile (tab) has changes. Signed-off-by: ubi de feo --- ui/arduino/store.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index aff39ce..93ed152 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1599,6 +1599,7 @@ function pickRandom(array) { function canSave({ view, isConnected, openFiles, editingFile }) { const isEditor = view === 'editor' const file = openFiles.find(f => f.id === editingFile) + if (!file.hasChanges) return false // Can only save on editor if (!isEditor) return false // Can always save disk files From b0511201bb2b82add369ed5da02c1cef2d6a2e6d Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Fri, 13 Dec 2024 09:15:44 +0100 Subject: [PATCH 18/22] Added view switch, replaced editor icon, updated shortcuts. Signed-off-by: ubi de feo --- backend/menu.js | 32 ++++++++++++++++++-------- backend/shortcuts.js | 4 ++++ ui/arduino/media/code.svg | 3 +++ ui/arduino/store.js | 8 +++++++ ui/arduino/views/components/toolbar.js | 14 +++++------ 5 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 ui/arduino/media/code.svg diff --git a/backend/menu.js b/backend/menu.js index e7ee2d9..e706a41 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -2,6 +2,7 @@ const { app, Menu } = require('electron') const path = require('path') const openAboutWindow = require('about-window').default const shortcuts = require('./shortcuts.js') +const { type } = require('os') module.exports = function registerMenu(win, state = {}) { const isMac = process.platform === 'darwin' @@ -99,6 +100,27 @@ module.exports = function registerMenu(win, state = {}) { }, { label: 'View', + submenu: [ + { + label: 'Editor', + accelerator: shortcuts.menu.EDITOR_VIEW, + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.EDITOR_VIEW,) + }, + { + label: 'Files', + accelerator: shortcuts.menu.FILES_VIEW, + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.FILES_VIEW) + }, + { type: 'separator' }, + { role: 'resetZoom' }, + { role: 'zoomIn' }, + { role: 'zoomOut' }, + { type: 'separator' }, + { role: 'togglefullscreen' }, + ] + }, + { + label: 'Window', submenu: [ { label: 'Reload', @@ -116,16 +138,6 @@ module.exports = function registerMenu(win, state = {}) { }, { role: 'toggleDevTools'}, { type: 'separator' }, - { role: 'resetZoom' }, - { role: 'zoomIn' }, - { role: 'zoomOut' }, - { type: 'separator' }, - { role: 'togglefullscreen' }, - ] - }, - { - label: 'Window', - submenu: [ { role: 'minimize' }, { role: 'zoom' }, ...(isMac ? [ diff --git a/backend/shortcuts.js b/backend/shortcuts.js index 93026a2..b496200 100644 --- a/backend/shortcuts.js +++ b/backend/shortcuts.js @@ -8,6 +8,8 @@ module.exports = { STOP: 'CommandOrControl+H', RESET: 'CommandOrControl+Shift+R', CLEAR_TERMINAL: 'CommandOrControl+L', + EDITOR_VIEW: 'CommandOrControl+Alt+1', + FILES_VIEW: 'CommandOrControl+Alt+2', ESC: 'Escape' }, menu: { @@ -19,5 +21,7 @@ module.exports = { STOP: 'CmdOrCtrl+H', RESET: 'CmdOrCtrl+Shift+R', CLEAR_TERMINAL: 'CmdOrCtrl+L', + EDITOR_VIEW: 'CmdOrCtrl+Alt+1', + FILES_VIEW: 'CmdOrCtrl+Alt+2' } } diff --git a/ui/arduino/media/code.svg b/ui/arduino/media/code.svg new file mode 100644 index 0000000..3b4303f --- /dev/null +++ b/ui/arduino/media/code.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/arduino/store.js b/ui/arduino/store.js index 93ed152..fddea1a 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1444,6 +1444,14 @@ async function store(state, emitter) { if (state.view != 'editor') return emitter.emit('save') } + if (key === shortcuts.EDITOR_VIEW) { + if (state.view != 'file-manager') return + emitter.emit('change-view', 'editor') + } + if (key === shortcuts.FILES_VIEW) { + if (state.view != 'editor') return + emitter.emit('change-view', 'file-manager') + } if (key === shortcuts.ESC) { if (state.isConnectionDialogOpen) { emitter.emit('close-connection-dialog') diff --git a/ui/arduino/views/components/toolbar.js b/ui/arduino/views/components/toolbar.js index b63e243..0e3d497 100644 --- a/ui/arduino/views/components/toolbar.js +++ b/ui/arduino/views/components/toolbar.js @@ -24,7 +24,7 @@ function Toolbar(state, emit) { ${Button({ icon: 'run.svg', - tooltip: `Run (${metaKeyString}+r)`, + tooltip: `Run (${metaKeyString}+R)`, disabled: !_canExecute, onClick: (e) => { if (e.altKey) { @@ -36,13 +36,13 @@ function Toolbar(state, emit) { })} ${Button({ icon: 'stop.svg', - tooltip: `Stop (${metaKeyString}+h)`, + tooltip: `Stop (${metaKeyString}+H)`, disabled: !_canExecute, onClick: () => emit('stop') })} ${Button({ icon: 'reboot.svg', - tooltip: `Reset (${metaKeyString}+Shift+r)`, + tooltip: `Reset (${metaKeyString}+Shift+R)`, disabled: !_canExecute, onClick: () => emit('reset') })} @@ -51,7 +51,7 @@ function Toolbar(state, emit) { ${Button({ icon: 'save.svg', - tooltip: `Save (${metaKeyString}+s)`, + tooltip: `Save (${metaKeyString}+S)`, disabled: !_canSave, onClick: () => emit('save') })} @@ -59,14 +59,14 @@ function Toolbar(state, emit) {
${Button({ - icon: 'editor.svg', - tooltip: 'Editor and REPL', + icon: 'code.svg', + tooltip: `Editor (${metaKeyString}+Alt+1)`, active: state.view === 'editor', onClick: () => emit('change-view', 'editor') })} ${Button({ icon: 'files.svg', - tooltip: 'File Manager', + tooltip: `Files (${metaKeyString}+Alt+2)`, active: state.view === 'file-manager', onClick: () => emit('change-view', 'file-manager') })} From bd3cc3b0e9d248493222e4614ec43afc2e484b45 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Fri, 13 Dec 2024 09:19:55 +0100 Subject: [PATCH 19/22] Moved 'Clear Terminal' to 'View' Signed-off-by: ubi de feo --- backend/menu.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/menu.js b/backend/menu.js index e706a41..337571a 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -89,13 +89,7 @@ module.exports = function registerMenu(win, state = {}) { enabled: state.isConnected && state.view === 'editor', click: () => win.webContents.send('shortcut-cmd', shortcuts.global.RESET) }, - { type: 'separator' }, - { - label: 'Clear terminal', - accelerator: shortcuts.menu.CLEAR_TERMINAL, - enabled: state.isConnected && state.view === 'editor', - click: () => win.webContents.send('shortcut-cmd', shortcuts.global.CLEAR_TERMINAL) - } + { type: 'separator' } ] }, { @@ -111,6 +105,12 @@ module.exports = function registerMenu(win, state = {}) { accelerator: shortcuts.menu.FILES_VIEW, click: () => win.webContents.send('shortcut-cmd', shortcuts.global.FILES_VIEW) }, + { + label: 'Clear terminal', + accelerator: shortcuts.menu.CLEAR_TERMINAL, + enabled: state.isConnected && state.view === 'editor', + click: () => win.webContents.send('shortcut-cmd', shortcuts.global.CLEAR_TERMINAL) + }, { type: 'separator' }, { role: 'resetZoom' }, { role: 'zoomIn' }, From 923166149883f4de34f23e10bb4c4d84a9509c36 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Fri, 13 Dec 2024 11:40:54 +0100 Subject: [PATCH 20/22] Removed comments with dev notes. Signed-off-by: ubi de feo --- backend/menu.js | 1 - index.js | 47 ----------------------------------------------- preload.js | 13 +------------ 3 files changed, 1 insertion(+), 60 deletions(-) diff --git a/backend/menu.js b/backend/menu.js index 337571a..2d406f7 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -173,7 +173,6 @@ module.exports = function registerMenu(win, state = {}) { openAboutWindow({ icon_path: path.resolve(__dirname, '../ui/arduino/media/about_image.png'), css_path: path.resolve(__dirname, '../ui/arduino/views/about.css'), - // about_page_dir: path.resolve(__dirname, '../ui/arduino/views/'), copyright: '© Arduino SA 2022', package_json_dir: path.resolve(__dirname, '..'), bug_report_url: "https://github.com/arduino/lab-micropython-editor/issues", diff --git a/index.js b/index.js index b11d662..aa5d989 100644 --- a/index.js +++ b/index.js @@ -92,53 +92,6 @@ function registerShortcuts() { shortcutAction(shortcut) }); }) - // shortcuts.forEach(element => { - // globalShortcut.register(element, () => { - - // shortcutAction(element) - // }); - // }); - // globalShortcut.register(shortcuts.RUN, () => { - // console.log('Running Program') - // shortcutAction(shortcuts.RUN) - // }) - // globalShortcut.register('CommandOrControl+Alt+R', () => { - // console.log('Running Code Selection') - // shortcutAction('meta_alt_r') - // }) - // globalShortcut.register('CommandOrControl+H', () => { - // console.log('Stopping Program (Halt)') - // shortcutAction('meta_h') - // }) - // globalShortcut.register('CommandOrControl+S', () => { - // console.log('Saving File') - // shortcutAction('meta_s') - // }) - - // globalShortcut.register('CommandOrControl+Shift+R', () => { - // console.log('Resetting Board') - // shortcutAction('meta_shift_r') - // }) - // globalShortcut.register(shortcuts.CONNECT, () => { - // console.log('Connect to Board') - // shortcutAction(shortcuts.CONNECT) - // }) - // globalShortcut.register(shortcuts.DISCONNECT, () => { - // console.log('Disconnect from Board') - // shortcutAction(shortcuts.DISCONNECT) - // }), - // globalShortcut.register('CommandOrControl+K', () => { - // console.log('Clear Terminal') - // shortcutAction('K') - // }), - // // Future: Toggle REPL Panel - // // globalShortcut.register('CommandOrControl+T', () => { - // // console.log('Toggle Terminal') - // // shortcutAction('T') - // // }), - // globalShortcut.register('Escape', () => { - // shortcutAction('ESC') - // }) } app.on('ready', () => { diff --git a/preload.js b/preload.js index bf78552..dd4f28f 100644 --- a/preload.js +++ b/preload.js @@ -4,7 +4,7 @@ const path = require('path') const shortcuts = require('./backend/shortcuts.js').global const MicroPython = require('micropython.js') const { emit, platform } = require('process') -// const { platform } = requireprocess.platform + const board = new MicroPython() board.chunk_size = 192 board.chunk_sleep = 200 @@ -159,18 +159,7 @@ const Window = { }, onKeyboardShortcut: (callback, key) => { ipcRenderer.on('shortcut-cmd', (event, k) => { - - - // Only trigger callback if terminal is not focused AND we're in editor view - // This has been deemed unnecessary since there are no real conflicts with the terminal - // The REPL shortcuts Ctrl+a|b|c|d are not used as application shortcuts and will - // only be triggered when the user has focused the REPL - // The code is left here for reference - // const activeElement = document.activeElement; - // const isTerminalFocused = activeElement.classList.contains('xterm-helper-textarea'); - // if (!isTerminalFocused) { callback(k); - // } }) }, From 9759ed752e82f4b308377c5d15d1e95664a57592 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Fri, 13 Dec 2024 12:38:24 +0100 Subject: [PATCH 21/22] Replaced Win/Linux Ctrl+Alt+R ignored shortcut with Ctrl+Alt+S Signed-off-by: ubi de feo --- backend/menu.js | 4 ++-- backend/shortcuts.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/menu.js b/backend/menu.js index 2d406f7..eb7810e 100644 --- a/backend/menu.js +++ b/backend/menu.js @@ -73,9 +73,9 @@ module.exports = function registerMenu(win, state = {}) { }, { label: 'Run selection', - accelerator: shortcuts.menu.RUN_SELECTION, + accelerator: isMac ? shortcuts.menu.RUN_SELECTION : shortcuts.menu.RUN_SELECTION_WL, enabled: state.isConnected && state.view === 'editor', - click: () => win.webContents.send('shortcut-cmd', shortcuts.global.RUN_SELECTION) + click: () => win.webContents.send('shortcut-cmd', (isMac ? shortcuts.global.RUN_SELECTION : shortcuts.global.RUN_SELECTION_WL)) }, { label: 'Stop', diff --git a/backend/shortcuts.js b/backend/shortcuts.js index b496200..e6b7159 100644 --- a/backend/shortcuts.js +++ b/backend/shortcuts.js @@ -5,6 +5,7 @@ module.exports = { SAVE: 'CommandOrControl+S', RUN: 'CommandOrControl+R', RUN_SELECTION: 'CommandOrControl+Alt+R', + RUN_SELECTION_WL: 'CommandOrControl+Alt+S', STOP: 'CommandOrControl+H', RESET: 'CommandOrControl+Shift+R', CLEAR_TERMINAL: 'CommandOrControl+L', @@ -18,6 +19,7 @@ module.exports = { SAVE: 'CmdOrCtrl+S', RUN: 'CmdOrCtrl+R', RUN_SELECTION: 'CmdOrCtrl+Alt+R', + RUN_SELECTION_WL: 'CmdOrCtrl+Alt+S', STOP: 'CmdOrCtrl+H', RESET: 'CmdOrCtrl+Shift+R', CLEAR_TERMINAL: 'CmdOrCtrl+L', From 6432226e5b70f5abf6370402e9de81c028e0eca1 Mon Sep 17 00:00:00 2001 From: ubi de feo Date: Fri, 13 Dec 2024 12:44:06 +0100 Subject: [PATCH 22/22] Amended shortcut handling in store.js Signed-off-by: ubi de feo --- ui/arduino/store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/arduino/store.js b/ui/arduino/store.js index fddea1a..f2bd1b0 100644 --- a/ui/arduino/store.js +++ b/ui/arduino/store.js @@ -1432,7 +1432,7 @@ async function store(state, emitter) { if (state.view != 'editor') return runCode() } - if (key === shortcuts.RUN_SELECTION) { + if (key === shortcuts.RUN_SELECTION || key === shortcuts.RUN_SELECTION_WL) { if (state.view != 'editor') return runCodeSelection() } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy