Skip to content

Merging develop to main #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 71 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
2f7be45
Adjust layout and theme
murilopolese Jun 1, 2022
c240a5e
updated application icon
ubidefeo Jun 7, 2022
68825b4
fixed app icon shadow
ubidefeo Jun 7, 2022
d047416
Same file update event for saving and uploading files to the board
murilopolese Jun 17, 2022
44c2bae
Adjusting button style
murilopolese Jun 17, 2022
e97a3b6
Connected and disconnected status
murilopolese Jun 17, 2022
8f77cb2
Organizing files and adding comments
murilopolese Jun 17, 2022
cb4b0fb
Wait for code be executed before running other script
murilopolese Jul 8, 2022
9d28eab
Write files with python multi line comments
murilopolese Jul 8, 2022
bcff4f9
Using method from `pyboard.py` to get file contents from board
murilopolese Jul 8, 2022
26f7253
Merge branch 'main' into develop
murilopolese Jul 8, 2022
237b7c6
Updating project dependencies and start migrating to new micropython.js
murilopolese Jul 31, 2022
3ddfd9a
Drafting store events with promise based micropython.js
murilopolese Aug 5, 2022
41a2e0e
Drafting serial fs operations
murilopolese Aug 5, 2022
ce4c324
Update dependencies and package json scripts
murilopolese Aug 12, 2022
4a2cf20
Arduino UI with terminal
murilopolese Aug 12, 2022
2d3f9ea
Listing and loading files from serial
murilopolese Aug 12, 2022
c4379f9
Saving to the board
murilopolese Aug 12, 2022
4c89089
Open, list and select disk files
murilopolese Aug 22, 2022
12a8574
Save disk files
murilopolese Aug 22, 2022
667259d
Rename and create new files over serial connection
murilopolese Aug 22, 2022
b8ffc01
Rename and create files on disk
murilopolese Aug 22, 2022
a30b66e
Save file name on blur input
murilopolese Aug 22, 2022
2104ac0
Download and upload files
murilopolese Aug 22, 2022
8fe770c
Add icons and fix upload/download
murilopolese Aug 22, 2022
e8a9e9d
Editor size fix
murilopolese Aug 23, 2022
7dfb454
Update toolbar icons
murilopolese Aug 24, 2022
b79c273
Fix download from board to disk
murilopolese Aug 24, 2022
9a52c00
Sync project version with release version
murilopolese Aug 26, 2022
171a7fd
Clean old icons
murilopolese Aug 26, 2022
0040c32
Resize editor correctly on content update
murilopolese Aug 26, 2022
1f3fec3
Adjust colors and buttons
murilopolese Aug 26, 2022
93d8981
Change label on file manager
murilopolese Aug 26, 2022
605188a
Fixing bug with file renaming
murilopolese Sep 2, 2022
2025976
Updating micropython.js
murilopolese Sep 9, 2022
fd1f48d
Connection messages
murilopolese Sep 9, 2022
0a0935b
Sticky disconnection message
murilopolese Sep 9, 2022
b571808
Comments and logs
murilopolese Sep 16, 2022
93c9862
Using the message box to indicate pending upload/download
murilopolese Sep 16, 2022
74c1927
Slow down fs_put so it works on Nano boards
murilopolese Sep 16, 2022
0445cfa
set version to 0.3.0-alpha
ubidefeo Sep 21, 2022
bdf3e6c
Resizeable panel
murilopolese Sep 30, 2022
6a6e824
Merge pull request #6 from arduino/bugfix/resize-panel
murilopolese Sep 30, 2022
d74c840
Add readme
murilopolese Oct 7, 2022
e91204d
Update readme
murilopolese Oct 7, 2022
9f9f835
Merge branch 'main' into develop
murilopolese Oct 7, 2022
f685450
Update with the new name
stevisco Oct 12, 2022
bb00962
Update index.html
stevisco Oct 12, 2022
d5228fc
fixed cursor offset Windows | updated version to 0.3.1
ubidefeo Oct 13, 2022
738a901
fixed package json name | updated window title
ubidefeo Oct 13, 2022
c1f6674
fixed typo in file name
ubidefeo Oct 13, 2022
b4fed09
changed port list filter from manufacturer to serialNumber to clean-u…
ubidefeo Oct 20, 2022
56c5d90
added package.json entry to generate aptly named application
ubidefeo Oct 20, 2022
a3e5f3c
Remove blank UI
murilopolese Oct 21, 2022
47a0bfe
Remove responsivity
murilopolese Oct 21, 2022
9cd5fd5
Filter USB ports by `vendorId` and `productId`
murilopolese Oct 21, 2022
298369c
Resize editor with bottom drawer (panel)
murilopolese Oct 21, 2022
0109376
Custom menu
murilopolese Oct 21, 2022
ef57b0d
Clear terminal
murilopolese Oct 21, 2022
c5e47fe
Copy and paste from terminal
murilopolese Oct 28, 2022
1b923cd
Filter out dot files and folder
murilopolese Oct 28, 2022
fec93ea
Show a dialog to decide where to create new file
murilopolese Oct 28, 2022
b6293ae
updated icons
ubidefeo Oct 30, 2022
0287453
added about-window package
ubidefeo Nov 1, 2022
275d0d8
added conditional for dev detection > dev tools
ubidefeo Nov 1, 2022
2c1ed17
updated about box CSS - cleanup
ubidefeo Nov 2, 2022
31ad131
fixed URL
ubidefeo Nov 2, 2022
42fe6ae
updated URLs in Help menu
ubidefeo Nov 2, 2022
c44e194
cleaned up code according to @murilopolese 's review
ubidefeo Nov 4, 2022
e877d4e
removed info object
ubidefeo Nov 4, 2022
1e019d1
Merge pull request #9 from arduino/about-box
murilopolese Nov 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
80 changes: 78 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,80 @@
# Arduino MicroPython Lab
# Arduino Lab for MicroPython

A lightweight editor for MicroPython supporting connection with a board, code upload, file transfer, interactive REPL shell.
Arduino Lab for MicroPython is an Integrated Development Environment (IDE) for MicroPython.

## Features
- MicroPython's Read Eval Print Loop (REPL)
- Enter paste mode
- Enter raw repl
- Software reset
- File system management (Disk and MicroPython File System)
- Create
- Rename
- Remove
- Upload
- Download
- Text editor with Python syntax highlight
- Code execution controls
- Run what's on text editor
- Stop (keyboard interrupt)
- Soft reset

## Technical

Arduino Lab for MicroPython is an [Electron](https://www.electronjs.org/) app that has its main purpose to communicate over serial with a microprocessor running [MicroPython](https://micropython.org/). All Electron code is at `/index.js`.

All operations over serial are abstracted and packaged on `/micropython.js` which is an attempt of porting `pyboard.py`. The port has its [own repository](https://github.com/murilopolese/micropython.js) but for the sake of simplicity and transparency, `micropython.js` is committed as source code.

The User Interface (UI) source code stays inside `/ui` folder and is completely independent of the Electron code.

The communication between interface and Electron app is accomplished by using the methods and events specified by `/preload.js`.

## Folder structure

At the root of the repository you will find:

- `/.github`: Github's workflow configuration.
- `/build_resources`: Icons and other assets used during the build process.
- `/scripts`: Scripts executed during the build process.
- `/ui`: Available user interfaces.
- `/index.js`: Main Electron code.
- `/micropython.js`: Serial connection abstraction.
- `/preload.js`: Creates Disk and Serial APIs on Electron's main process and exposes it to Electron's renderer process (context bridge).

## Arduino UI

Default UI is a [choo-choo](https://github.com/choojs/choo) app. It has pre-built dependencies so no build process is required for the interface.

The dependencies and source code are included manually in the `/ui/arduino/index.html` file.

The app is a standard [choo-choo](https://github.com/choojs/choo) app and it has:

- `/ui/arduino/app.js`: A router deciding which view to load.
- `/ui/arduino/components`: HTML templates and components.
- `/ui/arduino/store.js`: A "store" that handles events emitted by the views, change the app state and orchestrate re-rendering.
- `/ui/arduino/libs`: Prebuilt dependencies.

It can be useful to learn more about [Choo](https://github.com/choojs/choo) or the [Elm Architecture](https://guide.elm-lang.org/architecture/).

## Disk and Serial API

In order for the UI code to be independent of Electron code, there is an API defined at `/preload.js` that describes all the allowed operations.

There are 2 main operation "channels": Serial communication and local Filesystem operations. Both channels offer methods that always return promises and are used mostly through [`async`/`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function).

While the serial communication is mediated by `/micropython.js`, the local filesystem operations are done through Electron's `ipcRenderer` calls. The handlers for these calls are defined at `/index.js`

## Running Arduino Lab for MicroPython from source code

1. Clone this repository: `git clone https://github.com/arduino/MicroPython_Lab.git`
2. Navigate to repository folder: `cd MicroPython_Lab`
3. Install dependencies: `npm install`
4. Run dev mode: `npm run dev`

Some changes on the Electron code will require reopening the app but all UI changes will only require refreshing the window (ctrl-r/cmd-r).


## Trademarks

"Python" and the Python Logo are trademarks of the Python Software Foundation.

Binary file modified build_resources/icon.icns
Binary file not shown.
Binary file modified build_resources/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
172 changes: 164 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
const { app, BrowserWindow, Menu, ipcMain, dialog } = require('electron')
const path = require('path')
const fs = require('fs')
const join = require('path').join
const openAboutWindow = require('about-window').default

let win = null // main window

// HELPERS
async function openFolderDialog() {
// https://stackoverflow.com/questions/46027287/electron-open-folder-dialog
let dir = await dialog.showOpenDialog(win, { properties: [ 'openDirectory' ] })
return dir.filePaths[0] || null
}

function listFolder(folder) {
files = fs.readdirSync(path.resolve(folder))
// Filter out directories
files = files.filter(f => {
let filePath = path.resolve(folder, f)
return !fs.lstatSync(filePath).isDirectory()
})
return files
}

// LOCAL FILE SYSTEM ACCESS
ipcMain.handle('open-folder', async (event) => {
console.log('ipcMain', 'open-folder')
const folder = await openFolderDialog()
let files = []
if (folder) {
files = fs.readdirSync(path.resolve(folder))
// Filter out directories
files = files.filter(f => {
let filePath = path.resolve(folder, f)
return !fs.lstatSync(filePath).isDirectory()
})
files = listFolder(folder)
}
return { folder, files }
})

ipcMain.handle('list-files', async (event, folder) => {
console.log('ipcMain', 'list-files', folder)
if (!folder) return []
return listFolder(folder)
})

ipcMain.handle('load-file', (event, folder, filename) => {
console.log('ipcMain', 'load-file', folder, filename )
let filePath = path.resolve(folder, filename)
Expand All @@ -40,6 +55,7 @@ ipcMain.handle('save-file', (event, folder, filename, content) => {
})

ipcMain.handle('update-folder', (event, folder) => {
console.log('ipcMain', 'update-folder', folder)
let files = fs.readdirSync(path.resolve(folder))
// Filter out directories
files = files.filter(f => {
Expand All @@ -64,6 +80,7 @@ ipcMain.handle('rename-file', (event, folder, filename, newFilename) => {
return newFilename
})

// START APP
function createWindow () {
// Create the browser window.
win = new BrowserWindow({
Expand All @@ -77,7 +94,146 @@ function createWindow () {
}
})
// and load the index.html of the app.
win.loadFile('ui/blank/index.html')
win.loadFile('ui/arduino/index.html')
}

// TODO: Loading splash screen

const isMac = process.platform === 'darwin'
const isDev = !app.isPackaged
const template = [
...(isMac ? [{
label: app.name,
submenu: [
{ role: 'about'},
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}] : []),
{
label: 'File',
submenu: [
isMac ? { role: 'close' } : { role: 'quit' }
]
},
{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
...(isMac ? [
{ role: 'pasteAndMatchStyle' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
] : [
{ type: 'separator' },
{ role: 'selectAll' }
])
]
},
{
label: 'View',
submenu: [
{ role: 'reload' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' },
...(isDev ? [
{ type: 'separator' },
{ role: 'toggleDevTools' },
]:[
])
]
},
{
label: 'Window',
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
...(isMac ? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
] : [
{ role: 'close' }
])
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: async () => {
const { shell } = require('electron')
await shell.openExternal('https://github.com/arduino/MicroPython_Lab')
}
},
{
label: 'Report an issue',
click: async () => {
const { shell } = require('electron')
await shell.openExternal('https://github.com/arduino/MicroPython_Lab/issues')
}
},
{
label:'Info about this app',
click: () => {
openAboutWindow({
icon_path: join(__dirname, 'ui/arduino/assets/about_image.png'),
css_path: join(__dirname, 'ui/arduino/about.css'),
copyright: '© Arduino SA 2022',
package_json_dir: __dirname,
bug_report_url: "https://github.com/arduino/MicroPython_Lab/issues",
bug_link_text: "report an issue",
homepage: "https://labs.arduino.cc",
use_version_info: false,
win_options: {
parent: win,
modal: true,
},
show_close_button: 'Close',
})
}
},
]
}
]

const menu = Menu.buildFromTemplate(template)

app.setAboutPanelOptions({
applicationName: app.name,
applicationVersion: app.getVersion(),
copyright: app.copyright,
credits: '(See "Info about this app" in the Help menu)',
authors: ['Arduino'],
website: 'https://arduino.cc',
iconPath: path.join(__dirname, '../assets/image.png'),
})

Menu.setApplicationMenu(menu)


app.whenReady().then(createWindow)
Loading