diff --git a/css/status-bar.css b/css/status-bar.css index d60203d..0d35ad8 100644 --- a/css/status-bar.css +++ b/css/status-bar.css @@ -11,6 +11,10 @@ transition: max-height 0.5s ease, padding 0.5s ease, opacity 0.3s ease; } +.status-bar .close-button { + cursor: pointer; +} + .status-bar.visible { display: flex; max-height: 480px; diff --git a/forge.config.js b/forge.config.js index b88f019..b4ead4a 100644 --- a/forge.config.js +++ b/forge.config.js @@ -82,7 +82,8 @@ module.exports = { ignore: filesToExclude, prune: true, derefSymlinks: true, - protocols: [ { + protocols: [ { + // Register custom URL scheme on macOS name: 'micropython-package-installer', schemes: ['micropython-package-installer'] }], @@ -134,6 +135,11 @@ module.exports = { { name: '@electron-forge/maker-deb', platforms: ['linux'], + config: { + options: { + mimeType: ['x-scheme-handler/micropython-package-installer'] + } + } }, ], publishers: [ diff --git a/index.html b/index.html index fdb8c22..85f7577 100644 --- a/index.html +++ b/index.html @@ -69,6 +69,12 @@

Packages

diff --git a/main.js b/main.js index 45f6946..2c5e9e9 100644 --- a/main.js +++ b/main.js @@ -2,12 +2,23 @@ if (require('electron-squirrel-startup')) return; const { app, BrowserWindow, ipcMain, shell } = require('electron'); const path = require('path'); +const APP_SCHEME_NAME = 'micropython-package-installer'; +const ARDUINO_VID = 0x2341; + // Handle events from windows squirrel installer if (process.platform === "win32" && handleSquirrelEvent()) { // squirrel event handled and app will exit in 1000ms, so don't do anything else return; } +// On macOS the scheme is already registered through the app bundle metadata +// but on Windows and Linux we need to register it manually +if (process.platform !== "darwin" && !app.isDefaultProtocolClient(APP_SCHEME_NAME)) { + if(!app.setAsDefaultProtocolClient(APP_SCHEME_NAME)) { + console.error('Failed to register custom URL scheme', APP_SCHEME_NAME); + } +} + const { updateElectronApp } = require('update-electron-app') updateElectronApp() @@ -15,7 +26,6 @@ let mainWindow; let upyPackage; let packageManager; let deviceManager; -const ARDUINO_VID = 0x2341; function createWindow() { mainWindow = new BrowserWindow({ @@ -45,9 +55,7 @@ app.on('ready', async() => { }); app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } + app.quit(); }); app.on('activate', () => { @@ -95,7 +103,7 @@ ipcMain.handle('install-package', async (event, aPackage, serialPort, compileFil return { success: true }; } catch (error) { let packageDesignator = aPackage.name || aPackage.url; - console.error(`Failed to install package ${packageDesignator}:`, error); + console.error(`Failed to install package ${packageDesignator}:`, error.message); // Check if error contains "Resource busy" and return a more user-friendly message if(error.message.includes('Resource busy') || error.message.includes('Access denied')) { diff --git a/package-lock.json b/package-lock.json index cb8e76c..3a4e9a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "micropython-package-installer", - "version": "1.0.0", + "version": "1.0.1-beta.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "micropython-package-installer", - "version": "1.0.0", + "version": "1.0.1-beta.1", "license": "ISC", "dependencies": { "electron-squirrel-startup": "^1.0.1", "update-electron-app": "^3.0.0", - "upy-package": "github:arduino/upy-package#v1.0.0" + "upy-package": "github:arduino/upy-package#v1.0.1" }, "devDependencies": { "@electron-forge/cli": "^7.5.0", @@ -7268,8 +7268,8 @@ } }, "node_modules/upy-package": { - "version": "1.0.0", - "resolved": "git+ssh://git@github.com/arduino/upy-package.git#8a0f68f958caedd6afbad535e6c5e2dd05f154d6", + "version": "1.0.1", + "resolved": "git+ssh://git@github.com/arduino/upy-package.git#54245d58eab61f493dc82779926e85e14fa4df4a", "license": "ISC", "dependencies": { "commander": "^11.1.0", @@ -7277,7 +7277,7 @@ "inquirer": "^9.2.12", "js-yaml": "^4.1.0", "semver": "^7.6.2", - "upy-packager": "github:arduino/upy-packager#v1.0.0" + "upy-packager": "github:arduino/upy-packager#v1.0.1" }, "bin": { "upy-package": "main.js" diff --git a/package.json b/package.json index c4ac217..9324876 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "micropython-package-installer", - "version": "1.0.0", + "version": "1.0.1-beta.1", "description": "A tool to install MicroPython packages onto supported Arduino boards.", "main": "main.js", "scripts": { @@ -40,6 +40,6 @@ "dependencies": { "electron-squirrel-startup": "^1.0.1", "update-electron-app": "^3.0.0", - "upy-package": "github:arduino/upy-package#v1.0.0" + "upy-package": "github:arduino/upy-package#v1.0.1" } } diff --git a/renderer.js b/renderer.js index 2ee3602..fc4f59f 100644 --- a/renderer.js +++ b/renderer.js @@ -8,6 +8,7 @@ let customURLplaceholders = ['github:janedoe/button-mpy', ]; const statusBar = document.getElementById('status-bar'); +const statusBarCloseButton = document.getElementById('status-bar-close'); const statusMessage = document.getElementById('status-message'); const deviceSelectionList = document.querySelector(".item-selection-list"); const reloadDeviceListLink = document.getElementById("reload-link"); @@ -52,6 +53,8 @@ document.addEventListener('DOMContentLoaded', async () => { setInstallButtonsEnabled(true); }); + statusBarCloseButton.addEventListener('click', hideStatus); + reloadDeviceListLink.addEventListener('click', async () => { await reloadDeviceList(); }); @@ -248,6 +251,8 @@ function toggleUserInteraction(enabled) { searchField.disabled = !enabled; githubUrlInput.disabled = !enabled; manualInstallButton.disabled = !enabled; + compileFilesCheckbox.disabled = !enabled; + overwriteExistingCheckbox.disabled = !enabled; reloadDeviceListLink.style.pointerEvents = enabled ? 'auto' : 'none'; boardItems.forEach(board => board.style.pointerEvents = enabled ? 'auto' : 'none'); @@ -335,6 +340,9 @@ function showStatus(message, displayLoader = false, duration = null) { statusMessage.textContent = message; statusBar.classList.remove('hidden'); statusBarLoadingSpinner.classList.toggle('hidden', !displayLoader); + + // Hide close button when loader is displayed + statusBarCloseButton.classList.toggle('hidden', displayLoader); // Add the visible class to trigger the slide down effect setTimeout(() => { @@ -348,14 +356,12 @@ function showStatus(message, displayLoader = false, duration = null) { } function hideStatus() { - const statusBar = document.getElementById('status-bar'); - // Remove the visible class to trigger the slide-up effect statusBar.classList.remove('visible'); // After the transition ends, hide the element setTimeout(() => { - statusBar.style.display = 'none'; + statusBar.classList.add('hidden'); }, 500); // Match this duration with the CSS transition duration }