diff --git a/package.json b/package.json index 30dd60a..b2024b2 100644 --- a/package.json +++ b/package.json @@ -22,13 +22,20 @@ "devDependencies": { "custom-electron-titlebar": "^3.0.9", "electron": "^5.0.4", - "electron-builder": "^21.1.1" + "electron-builder": "^21.2.0" }, "build": { "appId": "lector", "productName": "Lector", "copyright": "Copyright (c) 2019 Sagar Gurtu", "buildVersion": "1.1.0", + "mac": { + "icon": "./src/assets/icons/mac/icon.icns", + "fileAssociations": { + "ext": "pdf", + "icon": "./src/assets/icons/mac/icon.icns" + } + }, "win": { "target": "NSIS", "icon": "./src/assets/icons/win/icon.ico", diff --git a/src/js/index.js b/src/js/index.js index 47e95f3..4335543 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -5,7 +5,7 @@ * See License in the project root for license information. *----------------------------------------------------------------------------*/ -(function () { +(function() { const { ipcRenderer, remote } = require('electron'); const customTitlebar = require('custom-electron-titlebar'); @@ -63,10 +63,8 @@ */ _appendTabsToContainer(bucketPosition) { this._tabContainer.innerHTML = ""; - for (let i = bucketPosition * this.stepTabs; - i < this._tabs.length && - i < (bucketPosition + 1) * this.stepTabs; - i++) { + for (let i = bucketPosition * this.stepTabs; i < this._tabs.length && + i < (bucketPosition + 1) * this.stepTabs; i++) { this._tabContainer.append(this._tabs[i]); } } @@ -198,10 +196,14 @@ } else { // If no tabs remaining that._toggleTabContainer(false); that._updateTitle(); + + // Add the drop listener after a timeout, otherwise, it won't work + setTimeout(() => { + that._addDropListener(); + }, 1000); } that._toggleSeek(); event.stopPropagation(); - }); tabElement.addEventListener('mouseover', event => { @@ -465,6 +467,39 @@ this._processArguments(remote.process.argv); } + /** + * @desc Add an event listener to the viewer, so files can be dropped and opened + * Derived from: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop + */ + _addDropListener() { + // Get the document from the viewer iframe + document.getElementById('viewer').contentWindow.document.body.ondragover = ev => { + // Prevent default behavior (Prevent file from being opened) + ev.preventDefault(); + } + + document.getElementById('viewer').contentWindow.document.body.ondrop = ev => { + // Prevent default behavior (Prevent file from being opened) + ev.preventDefault(); + + if (ev.dataTransfer.items) { + // Use DataTransferItemList interface to access the file(s) + for (var i = 0; i < ev.dataTransfer.items.length; i++) { + // If dropped items aren't files, reject them + if (ev.dataTransfer.items[i].kind === 'file') { + var file = ev.dataTransfer.items[i].getAsFile(); + this._openFile(file.path); + } + } + } else { + // Use DataTransfer interface to access the file(s) + for (var i = 0; i < ev.dataTransfer.files.length; i++) { + this._openFile(ev.dataTransfer.files[i].path); + } + } + } + } + /** * @desc Runs the application */ @@ -475,6 +510,10 @@ this._setWindowEvents(); this._setExternalEvents(); this._processRemoteArguments(); + this._addDropListener(); + + // On MacOs, notify the main process that this has finished loading + if (process.platform === 'darwin') ipcRenderer.send("web-loaded"); } } @@ -482,4 +521,4 @@ const application = new Reader(); application.run(); -})(); +})(); \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index c4560a4..478d27a 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -12,6 +12,11 @@ const { buildMenuTemplate } = require('./menutemplate'); // be closed automatically when the JavaScript object is garbage collected. let win, aboutWin; +// An array for all file paths to open on program start +const files = []; +// If the web site has finished loading +let web_loaded = false; + function createWindow() { // Create the browser window. win = new BrowserWindow({ @@ -24,6 +29,8 @@ function createWindow() { plugins: true, nodeIntegration: true }, + // Set titleBarStyle on mac to 'hidden', according to: https://www.electronjs.org/docs/api/frameless-window#alternatives-on-macos + titleBarStyle: ((process.platform === 'darwin') ? 'hidden' : 'visible'), frame: false }); @@ -69,6 +76,20 @@ function createWindow() { // Set application menu Menu.setApplicationMenu(menu); + // On MacOs listen for the web site to finish loading, to send all file paths to open to it + // Since parsing program args does not work + // General idea: https://medium.com/@roysegall/electron-open-with-for-mac-osx-f215a1fe2ce1 + if (process.platform === 'darwin') { + ipcMain.on('web-loaded', () => { + web_loaded = true; + files.forEach(path => { + win.webContents.send('file-open', path); + }); + // Empty the files list to prevent it from beeing sent again + files.length = 0; + }); + } + // Add event listener for enabling/disabling menu items ipcMain.on('toggle-menu-items', (event, flag) => { menu.getMenuItemById('file-print').enabled = flag; @@ -96,6 +117,19 @@ if (!gotTheLock) { } }); + // On MacOs, push all files to an array to open when the web site is loaded + if (process.platform === 'darwin') { + app.on('open-file', (event, path) => { + // If the web site is already loaded, do not push to the array + // Triggers, when the application is already running and a file is opened by the user + if (web_loaded) { + win.webContents.send('file-open', path); + } else { + files.push(path); + } + }); + } + // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. diff --git a/src/js/menutemplate.js b/src/js/menutemplate.js index 3a37301..c053cc6 100644 --- a/src/js/menutemplate.js +++ b/src/js/menutemplate.js @@ -63,6 +63,7 @@ exports.buildMenuTemplate = function (win) { }, { label: 'Exit', + accelerator: ((process.platform === 'darwin')? 'CmdOrCtrl+Q' : ''), // listen on MacOs for Command+Q to exit click() { app.quit() }