esp32tool 1.6.6 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/apple-touch-icon.png +0 -0
  2. package/css/style.css +325 -25
  3. package/dist/const.d.ts +6 -1
  4. package/dist/const.js +9 -3
  5. package/dist/esp_loader.js +35 -22
  6. package/dist/flash_jedec.js +5 -0
  7. package/dist/stubs/esp32.json +5 -5
  8. package/dist/stubs/esp32c2.json +4 -4
  9. package/dist/stubs/esp32c3.json +4 -4
  10. package/dist/stubs/esp32c5.json +4 -4
  11. package/dist/stubs/esp32c6.json +4 -4
  12. package/dist/stubs/esp32c61.json +4 -4
  13. package/dist/stubs/esp32h2.json +4 -4
  14. package/dist/stubs/esp32p4.json +4 -4
  15. package/dist/stubs/esp32p4r3.json +4 -4
  16. package/dist/stubs/esp32s2.json +4 -4
  17. package/dist/stubs/esp32s3.json +27 -5
  18. package/dist/stubs/esp32s31.json +8 -0
  19. package/dist/stubs/esp8266.json +5 -5
  20. package/dist/stubs/index.js +4 -2
  21. package/dist/util/console-color.js +3 -3
  22. package/dist/util/timestamp-transformer.js +24 -1
  23. package/dist/web/esp32-n1hWo9nn.js +1 -0
  24. package/dist/web/esp32c2-CPnHdueO.js +1 -0
  25. package/dist/web/esp32c3-ea1mvbdS.js +1 -0
  26. package/dist/web/esp32c5-Dzn4lVbd.js +1 -0
  27. package/dist/web/esp32c6-DL8Ekn6h.js +1 -0
  28. package/dist/web/esp32c61-DDIvCrFA.js +1 -0
  29. package/dist/web/esp32h2-Dnu87P5q.js +1 -0
  30. package/dist/web/esp32p4-HGPqzQsU.js +1 -0
  31. package/dist/web/esp32p4r3-DounZFQB.js +1 -0
  32. package/dist/web/esp32s2-gzKRBlZl.js +1 -0
  33. package/dist/web/esp32s3-BzPgJvNE.js +1 -0
  34. package/dist/web/esp32s31-Ck4fXdho.js +1 -0
  35. package/dist/web/esp8266-KToZdvHe.js +1 -0
  36. package/dist/web/index.js +1 -1
  37. package/electron/cli-main.cjs +19 -19
  38. package/electron/main.cjs +167 -148
  39. package/electron/preload.js +16 -18
  40. package/icons/icon-128.png +0 -0
  41. package/icons/icon-144.png +0 -0
  42. package/icons/icon-152.png +0 -0
  43. package/icons/icon-192.png +0 -0
  44. package/icons/icon-384.png +0 -0
  45. package/icons/icon-512.png +0 -0
  46. package/icons/icon-72.png +0 -0
  47. package/icons/icon-96.png +0 -0
  48. package/js/console.js +21 -12
  49. package/js/hex-editor.js +216 -163
  50. package/js/improv.js +59 -21
  51. package/js/modules/esp32-n1hWo9nn.js +1 -0
  52. package/js/modules/esp32c2-CPnHdueO.js +1 -0
  53. package/js/modules/esp32c3-ea1mvbdS.js +1 -0
  54. package/js/modules/esp32c5-Dzn4lVbd.js +1 -0
  55. package/js/modules/esp32c6-DL8Ekn6h.js +1 -0
  56. package/js/modules/esp32c61-DDIvCrFA.js +1 -0
  57. package/js/modules/esp32h2-Dnu87P5q.js +1 -0
  58. package/js/modules/esp32p4-HGPqzQsU.js +1 -0
  59. package/js/modules/esp32p4r3-DounZFQB.js +1 -0
  60. package/js/modules/esp32s2-gzKRBlZl.js +1 -0
  61. package/js/modules/esp32s3-BzPgJvNE.js +1 -0
  62. package/js/modules/esp32s31-Ck4fXdho.js +1 -0
  63. package/js/modules/esp8266-KToZdvHe.js +1 -0
  64. package/js/modules/esptool.js +1 -1
  65. package/js/nvs-editor.js +1366 -182
  66. package/js/script.js +1048 -845
  67. package/js/util/console-color.js +3 -3
  68. package/js/util/timestamp-transformer.js +24 -1
  69. package/js/webusb-serial.js +1075 -950
  70. package/package.cli.json +2 -2
  71. package/package.json +22 -13
  72. package/screenshots/desktop.png +0 -0
  73. package/screenshots/mobile.png +0 -0
  74. package/src/const.ts +12 -3
  75. package/src/esp_loader.ts +41 -24
  76. package/src/flash_jedec.ts +5 -0
  77. package/src/stubs/README.md +3 -1
  78. package/src/stubs/esp32.json +5 -5
  79. package/src/stubs/esp32c2.json +4 -4
  80. package/src/stubs/esp32c3.json +4 -4
  81. package/src/stubs/esp32c5.json +4 -4
  82. package/src/stubs/esp32c6.json +4 -4
  83. package/src/stubs/esp32c61.json +4 -4
  84. package/src/stubs/esp32h2.json +4 -4
  85. package/src/stubs/esp32h4.json +8 -0
  86. package/src/stubs/esp32p4.json +4 -4
  87. package/src/stubs/esp32p4r3.json +4 -4
  88. package/src/stubs/esp32s2.json +4 -4
  89. package/src/stubs/esp32s3.json +27 -5
  90. package/src/stubs/esp32s31.json +8 -0
  91. package/src/stubs/esp8266.json +5 -5
  92. package/src/stubs/index.ts +3 -2
  93. package/src/util/console-color.ts +3 -3
  94. package/src/util/timestamp-transformer.ts +27 -1
  95. package/sw.js +1 -1
  96. package/dist/web/esp32-BRKoi17y.js +0 -1
  97. package/dist/web/esp32c2-Btgr_lwh.js +0 -1
  98. package/dist/web/esp32c3-CHKfoI8W.js +0 -1
  99. package/dist/web/esp32c5-BDW4KtLo.js +0 -1
  100. package/dist/web/esp32c6-il8tTxAG.js +0 -1
  101. package/dist/web/esp32c61-thKzxBGf.js +0 -1
  102. package/dist/web/esp32h2-CxoUHv_P.js +0 -1
  103. package/dist/web/esp32p4-D3jLP-jY.js +0 -1
  104. package/dist/web/esp32p4r3-CqI71ojR.js +0 -1
  105. package/dist/web/esp32s2-iX3WoDbg.js +0 -1
  106. package/dist/web/esp32s3-DGwDVIgz.js +0 -1
  107. package/dist/web/esp8266-CUwxJpGa.js +0 -1
  108. package/js/modules/esp32-BRKoi17y.js +0 -1
  109. package/js/modules/esp32c2-Btgr_lwh.js +0 -1
  110. package/js/modules/esp32c3-CHKfoI8W.js +0 -1
  111. package/js/modules/esp32c5-BDW4KtLo.js +0 -1
  112. package/js/modules/esp32c6-il8tTxAG.js +0 -1
  113. package/js/modules/esp32c61-thKzxBGf.js +0 -1
  114. package/js/modules/esp32h2-CxoUHv_P.js +0 -1
  115. package/js/modules/esp32p4-D3jLP-jY.js +0 -1
  116. package/js/modules/esp32p4r3-CqI71ojR.js +0 -1
  117. package/js/modules/esp32s2-iX3WoDbg.js +0 -1
  118. package/js/modules/esp32s3-DGwDVIgz.js +0 -1
  119. package/js/modules/esp8266-CUwxJpGa.js +0 -1
@@ -3,13 +3,13 @@
3
3
  * This provides a truly standalone CLI without requiring Node.js installation
4
4
  */
5
5
 
6
- const { app } = require('electron');
7
- const path = require('path');
6
+ const { app } = require("electron");
7
+ const path = require("path");
8
8
 
9
9
  // Prevent Electron from showing any windows
10
10
  app.dock?.hide(); // macOS
11
- app.commandLine.appendSwitch('disable-gpu');
12
- app.commandLine.appendSwitch('no-sandbox');
11
+ app.commandLine.appendSwitch("disable-gpu");
12
+ app.commandLine.appendSwitch("no-sandbox");
13
13
 
14
14
  // Get CLI arguments (skip electron executable and script path)
15
15
  const cliArgs = process.argv.slice(app.isPackaged ? 1 : 2);
@@ -19,27 +19,27 @@ app.whenReady().then(async () => {
19
19
  try {
20
20
  // Dynamically import the CLI module
21
21
  const cliPath = app.isPackaged
22
- ? path.join(process.resourcesPath, 'app.asar', 'dist', 'cli.js')
23
- : path.join(__dirname, '..', 'dist', 'cli.js');
24
-
22
+ ? path.join(process.resourcesPath, "app.asar", "dist", "cli.js")
23
+ : path.join(__dirname, "..", "dist", "cli.js");
24
+
25
25
  // Set process.argv to match CLI expectations
26
26
  // In packaged app: argv[0] is the executable path
27
27
  // We want: ['node', 'esp32tool', ...actualArgs]
28
28
  const actualArgs = cliArgs;
29
- process.argv = ['node', 'esp32tool', ...actualArgs];
30
-
29
+ process.argv = ["node", "esp32tool", ...actualArgs];
30
+
31
31
  // Import CLI module
32
- const cliModule = await import('file://' + cliPath);
33
-
32
+ const cliModule = await import("file://" + cliPath);
33
+
34
34
  // Run the CLI
35
35
  await cliModule.runCLI();
36
-
36
+
37
37
  // Give a small delay for cleanup
38
38
  setTimeout(() => {
39
39
  app.exit(0);
40
40
  }, 100);
41
41
  } catch (error) {
42
- console.error('CLI Error:', error.message);
42
+ console.error("CLI Error:", error.message);
43
43
  if (process.env.DEBUG) {
44
44
  console.error(error.stack);
45
45
  }
@@ -50,25 +50,25 @@ app.whenReady().then(async () => {
50
50
  });
51
51
 
52
52
  // Handle app activation (macOS)
53
- app.on('activate', () => {
53
+ app.on("activate", () => {
54
54
  // Do nothing - we're a CLI app
55
55
  });
56
56
 
57
57
  // Quit when all windows are closed
58
- app.on('window-all-closed', () => {
58
+ app.on("window-all-closed", () => {
59
59
  // Do nothing - we don't have windows
60
60
  });
61
61
 
62
62
  // Handle errors
63
- process.on('uncaughtException', (error) => {
64
- console.error('Uncaught Exception:', error.message);
63
+ process.on("uncaughtException", (error) => {
64
+ console.error("Uncaught Exception:", error.message);
65
65
  if (process.env.DEBUG) {
66
66
  console.error(error.stack);
67
67
  }
68
68
  app.exit(1);
69
69
  });
70
70
 
71
- process.on('unhandledRejection', (reason) => {
72
- console.error('Unhandled Rejection:', reason);
71
+ process.on("unhandledRejection", (reason) => {
72
+ console.error("Unhandled Rejection:", reason);
73
73
  app.exit(1);
74
74
  });
package/electron/main.cjs CHANGED
@@ -1,12 +1,19 @@
1
- const { app, BrowserWindow, Menu, session, ipcMain, dialog } = require('electron');
2
- const path = require('path');
3
- const fs = require('fs');
1
+ const {
2
+ app,
3
+ BrowserWindow,
4
+ Menu,
5
+ session,
6
+ ipcMain,
7
+ dialog,
8
+ } = require("electron");
9
+ const path = require("path");
10
+ const fs = require("fs");
4
11
 
5
12
  // Handle creating/removing shortcuts on Windows when installing/uninstalling.
6
13
  // Only required for Windows Squirrel installer
7
- if (process.platform === 'win32') {
14
+ if (process.platform === "win32") {
8
15
  try {
9
- if (require('electron-squirrel-startup')) {
16
+ if (require("electron-squirrel-startup")) {
10
17
  app.quit();
11
18
  }
12
19
  } catch (e) {
@@ -28,22 +35,22 @@ function createWindow() {
28
35
  webPreferences: {
29
36
  nodeIntegration: false,
30
37
  contextIsolation: true,
31
- preload: path.join(__dirname, 'preload.js'),
38
+ preload: path.join(__dirname, "preload.js"),
32
39
  },
33
- icon: path.join(__dirname, 'icons', 'icon.png'),
34
- title: 'ESP32Tool',
40
+ icon: path.join(__dirname, "icons", "icon.png"),
41
+ title: "ESP32Tool",
35
42
  autoHideMenuBar: false,
36
43
  });
37
44
 
38
45
  // Load the index.html of the app
39
- mainWindow.loadFile(path.join(__dirname, '..', 'index.html'));
46
+ mainWindow.loadFile(path.join(__dirname, "..", "index.html"));
40
47
 
41
48
  // Open DevTools in development
42
- if (process.env.NODE_ENV === 'development') {
49
+ if (process.env.NODE_ENV === "development") {
43
50
  mainWindow.webContents.openDevTools();
44
51
  }
45
52
 
46
- mainWindow.on('closed', () => {
53
+ mainWindow.on("closed", () => {
47
54
  mainWindow = null;
48
55
  });
49
56
 
@@ -53,51 +60,56 @@ function createWindow() {
53
60
 
54
61
  function setupSerialPortHandlers(ses) {
55
62
  const isLikelyEspPort = (port) => {
56
- const name = `${port?.displayName || ''} ${port?.portName || ''}`.toLowerCase();
63
+ const name =
64
+ `${port?.displayName || ""} ${port?.portName || ""}`.toLowerCase();
57
65
  return (
58
- name.includes('cp2102') ||
59
- name.includes('cp2103') ||
60
- name.includes('cp2104') ||
61
- name.includes('cp2105') ||
62
- name.includes('cp2108') ||
63
- name.includes('ch9102') ||
64
- name.includes('ch9104') ||
65
- name.includes('ch340') ||
66
- name.includes('ch341') ||
67
- name.includes('ch343') ||
68
- name.includes('ftdi') ||
69
- name.includes('ft232') ||
70
- name.includes('usb') ||
71
- name.includes('uart') ||
72
- name.includes('silicon labs') ||
73
- name.includes('esp32') ||
74
- name.includes('esp8266') ||
75
- name.includes('esp')
66
+ name.includes("cp2102") ||
67
+ name.includes("cp2103") ||
68
+ name.includes("cp2104") ||
69
+ name.includes("cp2105") ||
70
+ name.includes("cp2108") ||
71
+ name.includes("ch9102") ||
72
+ name.includes("ch9104") ||
73
+ name.includes("ch340") ||
74
+ name.includes("ch341") ||
75
+ name.includes("ch343") ||
76
+ name.includes("ftdi") ||
77
+ name.includes("ft232") ||
78
+ name.includes("usb") ||
79
+ name.includes("uart") ||
80
+ name.includes("silicon labs") ||
81
+ name.includes("esp32") ||
82
+ name.includes("esp8266") ||
83
+ name.includes("esp")
76
84
  );
77
85
  };
78
86
 
79
- const getPortLabel = (port) => port?.displayName || port?.portName || port?.portId || 'Unknown port';
87
+ const getPortLabel = (port) =>
88
+ port?.displayName || port?.portName || port?.portId || "Unknown port";
80
89
 
81
90
  const getPortButtonLabel = (port, isRecommended = false) => {
82
- const shortId = port?.portName || port?.displayName || port?.portId || 'Unknown';
91
+ const shortId =
92
+ port?.portName || port?.displayName || port?.portId || "Unknown";
83
93
  return isRecommended ? `${shortId} (Recommended)` : shortId;
84
94
  };
85
95
 
86
96
  const toHexId = (value) =>
87
- typeof value === 'number' ? `0x${value.toString(16).toUpperCase().padStart(4, '0')}` : null;
97
+ typeof value === "number"
98
+ ? `0x${value.toString(16).toUpperCase().padStart(4, "0")}`
99
+ : null;
88
100
 
89
101
  // Guard against Electron re-firing select-serial-port while a dialog is open
90
102
  let activeSelectionId = 0;
91
103
 
92
104
  // Handle serial port selection - shows when navigator.serial.requestPort() is called
93
- ses.on('select-serial-port', (event, portList, webContents, callback) => {
105
+ ses.on("select-serial-port", (event, portList, webContents, callback) => {
94
106
  event.preventDefault();
95
107
 
96
108
  // Filter to only show ESP-compatible ports
97
109
  const espPorts = (portList || []).filter(isLikelyEspPort);
98
110
 
99
111
  if (espPorts.length === 0) {
100
- callback('');
112
+ callback("");
101
113
  return;
102
114
  }
103
115
 
@@ -113,35 +125,38 @@ function setupSerialPortHandlers(ses) {
113
125
  const buttonLabels = espPorts.map((port) => getPortButtonLabel(port));
114
126
  const cancelIndex = buttonLabels.length;
115
127
 
116
- const ownerWindow = BrowserWindow.fromWebContents(webContents) || mainWindow;
117
- dialog.showMessageBox(ownerWindow, {
118
- type: 'question',
119
- title: 'ESP32Tool',
120
- message: 'Select the serial port for your ESP device.',
121
- buttons: [...buttonLabels, 'Cancel'],
122
- defaultId: 0,
123
- cancelId: cancelIndex,
124
- noLink: true,
125
- }).then((result) => {
126
- // Ignore if a newer select-serial-port event superseded this one
127
- if (mySelectionId !== activeSelectionId) return;
128
- const selectedPort = espPorts[result.response];
129
- callback(selectedPort ? selectedPort.portId : '');
130
- });
128
+ const ownerWindow =
129
+ BrowserWindow.fromWebContents(webContents) || mainWindow;
130
+ dialog
131
+ .showMessageBox(ownerWindow, {
132
+ type: "question",
133
+ title: "ESP32Tool",
134
+ message: "Select the serial port for your ESP device.",
135
+ buttons: [...buttonLabels, "Cancel"],
136
+ defaultId: 0,
137
+ cancelId: cancelIndex,
138
+ noLink: true,
139
+ })
140
+ .then((result) => {
141
+ // Ignore if a newer select-serial-port event superseded this one
142
+ if (mySelectionId !== activeSelectionId) return;
143
+ const selectedPort = espPorts[result.response];
144
+ callback(selectedPort ? selectedPort.portId : "");
145
+ });
131
146
  });
132
147
 
133
- ses.on('serial-port-added', (event, port) => {
134
- console.log('Serial port added:', port);
148
+ ses.on("serial-port-added", (event, port) => {
149
+ console.log("Serial port added:", port);
135
150
  });
136
151
 
137
- ses.on('serial-port-removed', (event, port) => {
138
- console.log('Serial port removed:', port);
152
+ ses.on("serial-port-removed", (event, port) => {
153
+ console.log("Serial port removed:", port);
139
154
  });
140
155
 
141
156
  ses.setPermissionCheckHandler(() => true);
142
157
 
143
158
  ses.setDevicePermissionHandler((details) => {
144
- if (details.deviceType === 'serial' && details.device) {
159
+ if (details.deviceType === "serial" && details.device) {
145
160
  grantedDevices.set(details.device.deviceId, details.device);
146
161
  }
147
162
  return true;
@@ -152,73 +167,71 @@ function setupSerialPortHandlers(ses) {
152
167
  function createMenu() {
153
168
  const template = [
154
169
  {
155
- label: 'File',
156
- submenu: [
157
- { role: 'quit' }
158
- ]
170
+ label: "File",
171
+ submenu: [{ role: "quit" }],
159
172
  },
160
173
  {
161
- label: 'Edit',
174
+ label: "Edit",
162
175
  submenu: [
163
- { role: 'undo' },
164
- { role: 'redo' },
165
- { type: 'separator' },
166
- { role: 'cut' },
167
- { role: 'copy' },
168
- { role: 'paste' },
169
- { role: 'selectAll' }
170
- ]
176
+ { role: "undo" },
177
+ { role: "redo" },
178
+ { type: "separator" },
179
+ { role: "cut" },
180
+ { role: "copy" },
181
+ { role: "paste" },
182
+ { role: "selectAll" },
183
+ ],
171
184
  },
172
185
  {
173
- label: 'View',
186
+ label: "View",
174
187
  submenu: [
175
- { role: 'reload' },
176
- { role: 'forceReload' },
177
- { role: 'toggleDevTools' },
178
- { type: 'separator' },
179
- { role: 'resetZoom' },
180
- { role: 'zoomIn' },
181
- { role: 'zoomOut' },
182
- { type: 'separator' },
183
- { role: 'togglefullscreen' }
184
- ]
188
+ { role: "reload" },
189
+ { role: "forceReload" },
190
+ { role: "toggleDevTools" },
191
+ { type: "separator" },
192
+ { role: "resetZoom" },
193
+ { role: "zoomIn" },
194
+ { role: "zoomOut" },
195
+ { type: "separator" },
196
+ { role: "togglefullscreen" },
197
+ ],
185
198
  },
186
199
  {
187
- label: 'Help',
200
+ label: "Help",
188
201
  submenu: [
189
202
  {
190
- label: 'About ESP32Tool',
203
+ label: "About ESP32Tool",
191
204
  click: async () => {
192
- const { shell } = require('electron');
193
- await shell.openExternal('https://github.com/Jason2866/esp32tool');
194
- }
205
+ const { shell } = require("electron");
206
+ await shell.openExternal("https://github.com/Jason2866/esp32tool");
207
+ },
195
208
  },
196
209
  {
197
- label: 'ESP32 Documentation',
210
+ label: "ESP32 Documentation",
198
211
  click: async () => {
199
- const { shell } = require('electron');
200
- await shell.openExternal('https://docs.espressif.com/');
201
- }
202
- }
203
- ]
204
- }
212
+ const { shell } = require("electron");
213
+ await shell.openExternal("https://docs.espressif.com/");
214
+ },
215
+ },
216
+ ],
217
+ },
205
218
  ];
206
219
 
207
220
  // macOS specific menu adjustments
208
- if (process.platform === 'darwin') {
221
+ if (process.platform === "darwin") {
209
222
  template.unshift({
210
223
  label: app.getName(),
211
224
  submenu: [
212
- { role: 'about' },
213
- { type: 'separator' },
214
- { role: 'services' },
215
- { type: 'separator' },
216
- { role: 'hide' },
217
- { role: 'hideOthers' },
218
- { role: 'unhide' },
219
- { type: 'separator' },
220
- { role: 'quit' }
221
- ]
225
+ { role: "about" },
226
+ { type: "separator" },
227
+ { role: "services" },
228
+ { type: "separator" },
229
+ { role: "hide" },
230
+ { role: "hideOthers" },
231
+ { role: "unhide" },
232
+ { type: "separator" },
233
+ { role: "quit" },
234
+ ],
222
235
  });
223
236
  }
224
237
 
@@ -231,7 +244,7 @@ app.whenReady().then(() => {
231
244
  createMenu();
232
245
  createWindow();
233
246
 
234
- app.on('activate', () => {
247
+ app.on("activate", () => {
235
248
  // On macOS re-create a window when dock icon is clicked and no windows are open
236
249
  if (BrowserWindow.getAllWindows().length === 0) {
237
250
  createWindow();
@@ -240,8 +253,8 @@ app.whenReady().then(() => {
240
253
  });
241
254
 
242
255
  // Quit when all windows are closed, except on macOS
243
- app.on('window-all-closed', () => {
244
- if (process.platform !== 'darwin') {
256
+ app.on("window-all-closed", () => {
257
+ if (process.platform !== "darwin") {
245
258
  app.quit();
246
259
  }
247
260
  });
@@ -251,37 +264,40 @@ app.on('window-all-closed', () => {
251
264
  // ============================================
252
265
 
253
266
  // Save file dialog and write data
254
- ipcMain.handle('save-file', async (event, { data, defaultFilename, filters }) => {
255
- const result = await dialog.showSaveDialog(mainWindow, {
256
- defaultPath: defaultFilename,
257
- filters: filters || [
258
- { name: 'Binary Files', extensions: ['bin'] },
259
- { name: 'All Files', extensions: ['*'] }
260
- ]
261
- });
267
+ ipcMain.handle(
268
+ "save-file",
269
+ async (event, { data, defaultFilename, filters }) => {
270
+ const result = await dialog.showSaveDialog(mainWindow, {
271
+ defaultPath: defaultFilename,
272
+ filters: filters || [
273
+ { name: "Binary Files", extensions: ["bin"] },
274
+ { name: "All Files", extensions: ["*"] },
275
+ ],
276
+ });
262
277
 
263
- if (result.canceled || !result.filePath) {
264
- return { success: false, canceled: true };
265
- }
278
+ if (result.canceled || !result.filePath) {
279
+ return { success: false, canceled: true };
280
+ }
266
281
 
267
- try {
268
- // Convert data to Buffer if it's a Uint8Array
269
- const buffer = Buffer.from(data);
270
- fs.writeFileSync(result.filePath, buffer);
271
- return { success: true, filePath: result.filePath };
272
- } catch (error) {
273
- return { success: false, error: error.message };
274
- }
275
- });
282
+ try {
283
+ // Convert data to Buffer if it's a Uint8Array
284
+ const buffer = Buffer.from(data);
285
+ fs.writeFileSync(result.filePath, buffer);
286
+ return { success: true, filePath: result.filePath };
287
+ } catch (error) {
288
+ return { success: false, error: error.message };
289
+ }
290
+ },
291
+ );
276
292
 
277
293
  // Open file dialog and read data
278
- ipcMain.handle('open-file', async (event, { filters }) => {
294
+ ipcMain.handle("open-file", async (event, { filters }) => {
279
295
  const result = await dialog.showOpenDialog(mainWindow, {
280
- properties: ['openFile'],
296
+ properties: ["openFile"],
281
297
  filters: filters || [
282
- { name: 'Binary Files', extensions: ['bin'] },
283
- { name: 'All Files', extensions: ['*'] }
284
- ]
298
+ { name: "Binary Files", extensions: ["bin"] },
299
+ { name: "All Files", extensions: ["*"] },
300
+ ],
285
301
  });
286
302
 
287
303
  if (result.canceled || result.filePaths.length === 0) {
@@ -292,11 +308,11 @@ ipcMain.handle('open-file', async (event, { filters }) => {
292
308
  const filePath = result.filePaths[0];
293
309
  const data = fs.readFileSync(filePath);
294
310
  const filename = path.basename(filePath);
295
- return {
296
- success: true,
297
- filePath,
311
+ return {
312
+ success: true,
313
+ filePath,
298
314
  filename,
299
- data: Array.from(data) // Convert Buffer to array for IPC transfer
315
+ data: Array.from(data), // Convert Buffer to array for IPC transfer
300
316
  };
301
317
  } catch (error) {
302
318
  return { success: false, error: error.message };
@@ -304,30 +320,33 @@ ipcMain.handle('open-file', async (event, { filters }) => {
304
320
  });
305
321
 
306
322
  // Show input dialog (replacement for prompt())
307
- ipcMain.handle('show-prompt', async (event, { message, defaultValue }) => {
323
+ ipcMain.handle("show-prompt", async (event, { message, defaultValue }) => {
308
324
  // Use a simple approach - return the default value
309
325
  // In Electron, we use the save dialog instead of prompt
310
326
  return defaultValue;
311
327
  });
312
328
 
313
329
  // Show message box
314
- ipcMain.handle('show-message', async (event, { type, title, message, buttons }) => {
315
- const result = await dialog.showMessageBox(mainWindow, {
316
- type: type || 'info',
317
- title: title || 'ESP32Tool',
318
- message: message,
319
- buttons: buttons || ['OK']
320
- });
321
- return result.response;
322
- });
330
+ ipcMain.handle(
331
+ "show-message",
332
+ async (event, { type, title, message, buttons }) => {
333
+ const result = await dialog.showMessageBox(mainWindow, {
334
+ type: type || "info",
335
+ title: title || "ESP32Tool",
336
+ message: message,
337
+ buttons: buttons || ["OK"],
338
+ });
339
+ return result.response;
340
+ },
341
+ );
323
342
 
324
343
  // Show confirm dialog
325
- ipcMain.handle('show-confirm', async (event, { message }) => {
344
+ ipcMain.handle("show-confirm", async (event, { message }) => {
326
345
  const result = await dialog.showMessageBox(mainWindow, {
327
- type: 'question',
328
- title: 'Confirm',
346
+ type: "question",
347
+ title: "Confirm",
329
348
  message: message,
330
- buttons: ['OK', 'Cancel']
349
+ buttons: ["OK", "Cancel"],
331
350
  });
332
351
  return result.response === 0; // true if OK clicked
333
352
  });
@@ -1,10 +1,10 @@
1
1
  // Preload script for Electron
2
2
  // This runs in a sandboxed environment with access to some Node.js APIs
3
3
 
4
- const { contextBridge, ipcRenderer } = require('electron');
4
+ const { contextBridge, ipcRenderer } = require("electron");
5
5
 
6
6
  // Expose platform info and file APIs to renderer
7
- contextBridge.exposeInMainWorld('electronAPI', {
7
+ contextBridge.exposeInMainWorld("electronAPI", {
8
8
  platform: process.platform,
9
9
  isElectron: true,
10
10
  versions: {
@@ -12,26 +12,24 @@ contextBridge.exposeInMainWorld('electronAPI', {
12
12
  chrome: process.versions.chrome,
13
13
  electron: process.versions.electron,
14
14
  },
15
-
15
+
16
16
  // File operations
17
- saveFile: (data, defaultFilename, filters) =>
18
- ipcRenderer.invoke('save-file', { data, defaultFilename, filters }),
19
-
20
- openFile: (filters) =>
21
- ipcRenderer.invoke('open-file', { filters }),
22
-
17
+ saveFile: (data, defaultFilename, filters) =>
18
+ ipcRenderer.invoke("save-file", { data, defaultFilename, filters }),
19
+
20
+ openFile: (filters) => ipcRenderer.invoke("open-file", { filters }),
21
+
23
22
  // Dialog operations
24
23
  showPrompt: (message, defaultValue) =>
25
- ipcRenderer.invoke('show-prompt', { message, defaultValue }),
26
-
24
+ ipcRenderer.invoke("show-prompt", { message, defaultValue }),
25
+
27
26
  showMessage: (type, title, message, buttons) =>
28
- ipcRenderer.invoke('show-message', { type, title, message, buttons }),
29
-
30
- showConfirm: (message) =>
31
- ipcRenderer.invoke('show-confirm', { message })
27
+ ipcRenderer.invoke("show-message", { type, title, message, buttons }),
28
+
29
+ showConfirm: (message) => ipcRenderer.invoke("show-confirm", { message }),
32
30
  });
33
31
 
34
32
  // Log when preload script runs
35
- console.log('Electron preload script loaded');
36
- console.log('Platform:', process.platform);
37
- console.log('Electron version:', process.versions.electron);
33
+ console.log("Electron preload script loaded");
34
+ console.log("Platform:", process.platform);
35
+ console.log("Electron version:", process.versions.electron);
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/icons/icon-72.png CHANGED
Binary file
package/icons/icon-96.png CHANGED
Binary file