diff --git a/docz/static/electron/index.js b/docz/static/electron/index.js index bf25d87..47e8a60 100644 --- a/docz/static/electron/index.js +++ b/docz/static/electron/index.js @@ -1,5 +1,6 @@ const XLSX = require("xlsx"); const electron = require("@electron/remote"); +const { ipcRenderer } = require('electron'); // --- Supported Extensions --- const EXTENSIONS = @@ -202,3 +203,16 @@ async function readFile(files) { // --- Initial Setup --- attachDropListeners(); + +// handle file opening events from the main process +ipcRenderer.on('file-opened', async (_evt, filePath) => { + console.log('Received file-opened event:', filePath); + showSpinner(); + // yield to event loop to render spinner + await new Promise(r => setTimeout(r, 50)); + renderWorkbookToTables(XLSX.readFile(filePath)); // already in your helper list + showLoadedFileUI(filePath.split(/[/\\]/).pop()); + hideSpinner(); + hideDropUI(); + showExportBtn(); +}); \ No newline at end of file diff --git a/docz/static/electron/main.js b/docz/static/electron/main.js index dd8588e..ccf9d65 100644 --- a/docz/static/electron/main.js +++ b/docz/static/electron/main.js @@ -6,6 +6,57 @@ require('@electron/remote/main').initialize(); // required for Electron 14+ var win = null; +const EXT_REGEX = /\.(xls|xlsx|xlsm|xlsb|xml|csv|txt|dif|sylk|slk|prn|ods|fods|htm|html|numbers)$/i; +const pendingPaths = []; // any paths that arrive before the window exists + + +// send file opening events to renderer +function sendToRenderer(filePath) { + if (win && win.webContents) { + win.webContents.send('file-opened', filePath); + } else { + pendingPaths.push(filePath); + } +} + +function firstSpreadsheetFromArgv() { + const args = process.defaultApp // dev: electron . + ? process.argv.slice(2) // skip electron executable & dir + : process.argv.slice(1); // skip packaged exe + return args.find(a => EXT_REGEX.test(a)); // undefined if none +} + +/* ---- 1️⃣ single-instance guard (needed for Windows / Linux) ---- */ +// on windows and linux, opening a file opens a new instance of the app, this prevents that. +const gotLock = app.requestSingleInstanceLock(); +if (!gotLock) app.quit(); +else { + app.on('second-instance', (_e, argv) => { // emitted in *primary* instance + const fp = argv.find(a => EXT_REGEX.test(a)); + if (fp) sendToRenderer(fp); + if (win) { win.show(); win.focus(); } + }); +} + +/* ---- 2️⃣ platform-specific “open file” hooks ---- */ +app.on('open-file', (event, fp) => { // macOS Dock / Finder + event.preventDefault(); + sendToRenderer(fp); +}); + +app.on('open-url', (event, url) => { // you can add a custom protocol if you want to handle URLs + event.preventDefault(); + sendToRenderer(url.replace('file://', '')); // crude, adjust if you keep deep-links +}); + +/* ---- 3️⃣ normal start-up, harvest argv ---- */ +app.whenReady().then(() => { + const fp = firstSpreadsheetFromArgv(); // Windows & Linux first launch + if (fp) pendingPaths.push(fp); + createWindow(); +}); + +/* ---- 4️⃣ create the window ---- */ function createWindow() { if (win) return; win = new electron.BrowserWindow({ @@ -18,12 +69,15 @@ function createWindow() { } }); win.loadURL("file://" + __dirname + "/index.html"); - require('@electron/remote/main').enable(win.webContents); // required for Electron 14+ - win.webContents.openDevTools(); + require('@electron/remote/main').enable(win.webContents); // required for Electron 14 + if (process.env.NODE_ENV === 'development') win.webContents.openDevTools(); // only open devtools in development win.on('closed', function () { win = null; }); + win.webContents.once('did-finish-load', () => { + pendingPaths.splice(0).forEach(sendToRenderer); + }); } if (app.setAboutPanelOptions) app.setAboutPanelOptions({ applicationName: 'sheetjs-electron', applicationVersion: "XLSX " + XLSX.version, copyright: "(C) 2017-present SheetJS LLC" }); -app.on('open-file', function () { console.log(arguments); }); + app.on('ready', createWindow); app.on('activate', createWindow); app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit(); }); diff --git a/docz/static/electron/package.json b/docz/static/electron/package.json index 6a46726..e378a3a 100644 --- a/docz/static/electron/package.json +++ b/docz/static/electron/package.json @@ -12,7 +12,8 @@ "scripts": { "start": "electron-forge start", "package": "electron-forge package", - "make": "electron-forge make" + "make": "electron-forge make", + "dist": "electron-builder" }, "devDependencies": { "@electron-forge/cli": "7.8.0", @@ -20,8 +21,28 @@ "@electron-forge/maker-rpm": "7.8.0", "@electron-forge/maker-squirrel": "7.8.0", "@electron-forge/maker-zip": "7.8.0", - "electron": "35.1.2" + "electron": "35.1.2", + "electron-builder": "^26.0.12" }, + + "build": { + "appId": "com.sheetjs.electron", + "fileAssociations": [ + { + "ext": [ + "xls","xlsx","xlsm","xlsb","xml","csv","txt","dif", + "sylk","slk","prn","ods","fods","htm","html","numbers" + ], + "name": "Spreadsheet / Delimited File", + "description": "Spreadsheets and delimited text files opened by SheetJS-Electron", + "role": "Editor" + } + ], + "mac": { "target": "dmg" }, + "win": { "target": "nsis" }, + "linux": { "target": "deb" } + }, + "config": { "forge": { "packagerConfig": {}, diff --git a/docz/static/electron/styles.css b/docz/static/electron/styles.css index bcbee33..c699ac0 100644 --- a/docz/static/electron/styles.css +++ b/docz/static/electron/styles.css @@ -288,6 +288,7 @@ summary:focus-within { .sheetjs-tab-content { cursor: pointer; padding: 1rem; + overflow-x: auto; } /* =====================