From 8de9bd31554ecb0ec6eee1ddaabdbfd2cf4403dd Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Sat, 15 May 2021 23:02:25 +0200 Subject: [PATCH] electron window config - create dummy menus - close to tray --- server/{ => electron}/preload.js | 0 server/main.js | 149 +++++++++++++++++++++++++++++-- server/package.json | 19 ++-- server/yarn.lock | 120 ++++++++++++++++++++++++- 4 files changed, 270 insertions(+), 18 deletions(-) rename server/{ => electron}/preload.js (100%) diff --git a/server/preload.js b/server/electron/preload.js similarity index 100% rename from server/preload.js rename to server/electron/preload.js diff --git a/server/main.js b/server/main.js index 490836824..625813715 100644 --- a/server/main.js +++ b/server/main.js @@ -1,33 +1,166 @@ -const { app, BrowserWindow } = require('electron'); +const { + app, + BrowserWindow, + Menu, + globalShortcut, + Tray, + dialog, +} = require('electron'); const path = require('path'); +const { electron } = require('process'); const nodeapp = require('./app.js'); +require('@electron/remote/main').initialize(); + +// Load Icons +// TODO: Icons appear pixelated +const trayIcon = path.join(__dirname, './assets/images/logos/LOGO-512.png'); +const appIcon = path.join(__dirname, './assets/images/logos/LOGO-512.png'); + +// Ensure there isn't another instance of the app running already +var lock = app.requestSingleInstanceLock(); +if (!lock) { + dialog.showErrorBox( + 'Multiple instances', + 'Another instance is already running. Please close the other instance first.' + ); + app.quit(); + return; +} + +var win, tray; function createWindow() { - const win = new BrowserWindow({ + win = new BrowserWindow({ width: 800, height: 600, + backgroundColor: '#202020', + icon: appIcon, + // TODO: Make framerless + // frame: false, webPreferences: { - preload: path.join(__dirname, './preload.js'), + preload: path.join(__dirname, './electron/preload.js'), + // TODO: what are recommended alternatives to node integration? nodeIntegration: true, + enableRemoteModule: true, }, }); + // Load page served by node win.loadURL('http://localhost:4001/editor'); - win.webContents.openDevTools(); + // TODO: Make development environment and run live react instead + // win.loadURL('http://localhost:3000/editor'); + + // Show dev tools + win.webContents.openDevTools({ mode: 'detach' }); } app.whenReady().then(() => { createWindow(); + // TODO: Move to separate file + // TODO: Should move to react? + // Define App Menu + const appMenuTemplate = [ + { + label: 'Help', + submenu: [ + { + label: 'Getting Started', + click: () => { + console.log('Gonna do something here: Help > Getting Started'); + }, + }, + { + label: 'OSC Controls', + click: () => { + console.log('Gonna do something here: Help > OSC Controls'); + }, + }, + { + label: 'URL Definitions', + click: () => { + console.log('Gonna do something here: Help > URL Definitions'); + }, + }, + ], + }, + ]; + + const appMenu = Menu.buildFromTemplate(appMenuTemplate); + Menu.setApplicationMenu(appMenu); + + /* ====================================== + * CONTEXT MENU CREATION ON REACT SIDE + // Create context menu + // const contextMenu = new Menu(); + // contextMenu.append( + // new MenuItem({ + // label: 'Build context menu here', + // }) + // ); + + // open context menu when clicked + // win.webContents.on('context-menu', (e, params) => { + // contextMenu.popup(win, params.x, params.y); + // }); + * ====================================== + */ + + // register global shortcuts + // (available regardless of wheter app is in focus) + // bring focus to window + globalShortcut.register('Alt+1', () => { + win.show(); + }); + + // recreate window if no others open app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); + + // Hide on minimise + win.on('minimize', function (event) { + event.preventDefault(); + win.hide(); + }); + + //Hide on close + win.on('close', function (event) { + event.preventDefault(); + win.hide(); + + return false; + }); + + // create tray + // TODO: Design better icon + tray = new Tray(trayIcon); + + // TODO: Move to separate file + // Define context menu + const trayMenuTemplate = [ + { + label: 'Show App', + click: () => win.show(), + }, + { + label: 'Close', + click: () => { + win.destroy(); + app.quit(); + }, + }, + ]; + + const trayContextMenu = Menu.buildFromTemplate(trayMenuTemplate); + + tray.setContextMenu(trayContextMenu); + tray.setToolTip('ontime running on http://localhost:4001/'); }); -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } +// unregister shortcuts before quitting +app.once('will-quit', () => { + globalShortcut.unregisterAll(); }); diff --git a/server/package.json b/server/package.json index 070574918..7442f2e1c 100644 --- a/server/package.json +++ b/server/package.json @@ -1,10 +1,9 @@ { - "name": "my-electron-app", + "name": "ontime", "version": "0.1.0", - "author": "your name", - "description": "My Electron app", + "author": "Carlos Valente", + "description": "Time keeping for live events", "main": "main.js", - "dependencies": { "body-parser": "~1.19.0", "express": "~4.17.1", @@ -17,6 +16,8 @@ "socket.io": "^4.0.0" }, "devDependencies": { + "@electron/remote": "^1.1.0", + "concurrently": "^6.1.0", "electron": "^12.0.7", "electron-builder": "^22.11.3", "eslint": "^7.26.0", @@ -31,7 +32,8 @@ "nodestart": "node app.js", "start": "electron .", "pack": "electron-builder --dir", - "dist": "electron-builder" + "dist": "electron-builder", + "startall": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"" }, "build": { "appId": "your.id", @@ -45,8 +47,11 @@ { "from": "../client/build", "to": "resources/client/build", - "filter": ["**/*"] + "filter": [ + "**/*" + ] } - ] }, + ] + }, "postinstall": "electron-builder install-app-deps" } diff --git a/server/yarn.lock b/server/yarn.lock index 1b4a25846..43aaaf31f 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -14,12 +14,19 @@ dependencies: "@babel/highlight" "^7.10.4" +"@babel/code-frame@^7.0.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" + integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== + dependencies: + "@babel/highlight" "^7.12.13" + "@babel/helper-validator-identifier@^7.14.0": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== -"@babel/highlight@^7.10.4": +"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf" integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== @@ -67,6 +74,11 @@ global-agent "^2.0.2" global-tunnel-ng "^2.7.1" +"@electron/remote@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@electron/remote/-/remote-1.1.0.tgz#167d119c7c03c7778b556fdc4f1f38a44b23f1c2" + integrity sha512-yr8gZTkIgJYKbFqExI4QZqMSjn1kL/us9Dl46+TH1EZdhgRtsJ6HDfdsIxu0QEc6Hv+DMAXs69rgquH+8FDk4w== + "@electron/universal@1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.0.5.tgz#b812340e4ef21da2b3ee77b2b4d35c9b86defe37" @@ -182,6 +194,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.45.tgz#ec2dfb5566ff814d061aef7e141575aedba245cf" integrity sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + "@types/plist@^3.0.1": version "3.0.2" resolved "https://registry.yarnpkg.com/@types/plist/-/plist-3.0.2.tgz#61b3727bba0f5c462fe333542534a0c3e19ccb01" @@ -749,6 +766,21 @@ concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" +concurrently@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-6.1.0.tgz#00d22525d3fcdce7f34cc7f3c9753f90a57d6208" + integrity sha512-jy+xj49pvqeKjc2TAVXRIhrgPG51eBKDZti0kZ41kaWk9iLbyWBjH6KMFpW7peOLkEymD+ZM83Lx6UEy3N/M9g== + dependencies: + chalk "^4.1.0" + date-fns "^2.16.1" + lodash "^4.17.21" + read-pkg "^5.2.0" + rxjs "^6.6.3" + spawn-command "^0.0.2-1" + supports-color "^8.1.0" + tree-kill "^1.2.2" + yargs "^16.2.0" + config-chain@^1.1.11: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -855,6 +887,11 @@ damerau-levenshtein@^1.0.6: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== +date-fns@^2.16.1: + version "2.21.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.21.3.tgz#8f5f6889d7a96bbcc1f0ea50239b397a83357f9b" + integrity sha512-HeYdzCaFflc1i4tGbj7JKMjM4cKGYoyxwcIIkHzNgCkX8xXDNJDZXgDDVchIWpN4eQc3lH37WarduXFZJOtxfw== + debug@2.6.9, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1119,7 +1156,7 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -error-ex@^1.2.0: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -2064,6 +2101,11 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2161,6 +2203,11 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -2346,7 +2393,7 @@ node-osc@^6.0.1: dependencies: osc-min "^1.1.1" -normalize-package-data@^2.3.2: +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -2510,6 +2557,16 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -2733,6 +2790,16 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@^2.2.2: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -2835,6 +2902,13 @@ roarr@^2.15.3: semver-compare "^1.0.0" sprintf-js "^1.1.2" +rxjs@^6.6.3: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -3021,6 +3095,11 @@ source-map@^0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +spawn-command@^0.0.2-1: + version "0.0.2-1" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" + integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= + spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -3193,6 +3272,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + table@^6.0.4: version "6.7.0" resolved "https://registry.yarnpkg.com/table/-/table-6.7.0.tgz#26274751f0ee099c547f6cb91d3eff0d61d155b2" @@ -3242,6 +3328,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + truncate-utf8-bytes@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" @@ -3259,6 +3350,11 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + tunnel@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" @@ -3281,6 +3377,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -3515,6 +3616,19 @@ yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb"