diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..bafee3f --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,20 @@ +module.exports = { + env: { + browser: true, + commonjs: true, + es2021: true, + node: true, + }, + extends: ['airbnb-base', 'prettier'], + parserOptions: { + ecmaVersion: 13, + }, + rules: { + 'import/no-extraneous-dependencies': 0, + 'no-unused-vars': ['error', { args: 'none' }], + 'no-console': 'off', + 'no-alert': 'off', + 'no-plusplus': 'off', + 'import/extensions': 'off', + }, +}; diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..9209ef5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +node_modules +out diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..5940bcb --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + trailingComma: 'es5', + tabWidth: 2, + semi: true, + singleQuote: true, + bracketSameLine: true, +}; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ad92582 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": true +} diff --git a/README.md b/README.md index 570dece..a131b48 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,18 @@ # Cue View + A dashboard for everything in your show. ![Screen Shot 2021-10-26 at 11 57 21 PM](https://user-images.githubusercontent.com/919746/138997636-dfca293a-7c98-459d-85a3-405c9b11ce8a.png) +## Features - - -### Features - Tons of supported equipment - Auto discover devices on the network - Live updating - Configurable layout - ## Supported Devices + - QLab 4 - ETC Eos Consoles - Watchout @@ -21,12 +20,16 @@ A dashboard for everything in your show. - X32 Audio Consoles - XAir Audio Consoles +#### Future Devices -### Future Devices - Spikemark - ATEM Video Mixers - Art-Net, sACN Universes - Epson Pro series Projectors - DiGiCo Consoles - d&b DS100, amps +- Hog +## Known Issues + +- QLab Cue Carts are not supported yet. diff --git a/index.html b/index.html index d8a2d43..81e7818 100644 --- a/index.html +++ b/index.html @@ -1,73 +1,101 @@ - + Cue View - - + - -
- -
- -
- - - - -
- -
-

Click the Search button to find devices on the network.

-
- -
- - - -
- - - -
- - - - - - - - - - - - - - - - - - -
Name:
Type:
Addr:
Port:Pin:
-

No Device Selected

- -
- - +
+
+ + +
-
- - - +
+

+ Click the Search button to find devices on the network. +

+
+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
Name: + +
Type: + +
Addr: + +
Port: + + Pin:
+ +

No Device Selected

+
+
+ +
- diff --git a/main.js b/main.js index d25d572..68758f2 100644 --- a/main.js +++ b/main.js @@ -1,21 +1,123 @@ -const { app, BrowserWindow, Menu } = require('electron'); +const { app, BrowserWindow, Menu, ipcMain } = require('electron'); const path = require('path'); // Handle creating/removing shortcuts on Windows when installing/uninstalling. -if (require('electron-squirrel-startup')) { // eslint-disable-line global-require - app.quit(); -} - +// eslint-disable-next-line global-require if (require('electron-squirrel-startup')) { app.quit(); } +// eslint-disable-next-line global-require +if (require('electron-squirrel-startup')) { + app.quit(); +} -var menu; +const isMac = process.platform === 'darwin'; +let menu; let mainWindow; +const menuTemplate = [ + { role: 'appMenu' }, + { + label: 'File', + submenu: [ + { + label: 'Clear Saved Data', + id: 'resetViews', + click: function (menuItem, window, event) { + mainWindow.webContents.send('resetViews'); + }, + }, + { + label: 'Reload App', + role: 'reload', + }, + { + type: 'separator', + }, + isMac ? { role: 'close' } : { role: 'quit' }, + ], + }, + { role: 'editMenu' }, + { + label: 'View', + submenu: [ + { role: 'togglefullscreen' }, + { type: 'separator' }, + { + label: 'Arrangement 1', + accelerator: 'CommandOrControl+1', + id: 'window1', + enabled: true, + click: function (menuItem, window, event) { + mainWindow.webContents.send('doSlots1'); + }, + }, + { + label: 'Arrangement 2', + accelerator: 'CommandOrControl+2', + id: 'window2', + enabled: true, + click: function (menuItem, window, event) { + mainWindow.webContents.send('doSlots2'); + }, + }, + { + label: 'Arrangement 3', + accelerator: 'CommandOrControl+3', + id: 'window3', + enabled: true, + click: function (menuItem, window, event) { + mainWindow.webContents.send('doSlots3'); + }, + }, + { type: 'separator' }, + { role: 'toggleDevTools' }, + ], + }, + { + label: 'Device', + submenu: [ + { + label: 'Search for Devices', + accelerator: 'CommandOrControl+F', + id: 'deviceSearch', + enabled: true, + click: function (menuItem, window, event) { + mainWindow.webContents.send('doSearch'); + }, + }, + { + type: 'separator', + }, + { + label: 'Pinned', + type: 'checkbox', + checked: true, + accelerator: 'CommandOrControl+P', + id: 'devicePin', + enabled: false, + click: function (menuItem, window, event) { + mainWindow.webContents.send( + 'setActiveDevicePinned', + menuItem.checked + ); + }, + }, + { + label: 'Delete', + accelerator: 'CommandOrControl+Backspace', + id: 'deviceDelete', + enabled: false, + click: function (menuItem, window, event) { + mainWindow.webContents.send('doDelete'); + }, + }, + ], + }, +]; + const createWindow = () => { - mainWindow = new BrowserWindow({ width: 1500, height: 900, @@ -23,46 +125,38 @@ const createWindow = () => { transparent: true, frame: false, show: false, - //backgroundColor: "#333333", - vibrancy: "window", - visualEffectState: "followWindow", + // backgroundColor: "#333333", + vibrancy: 'window', + visualEffectState: 'followWindow', webPreferences: { - //enableRemoteModule: true, + // enableRemoteModule: true, contextIsolation: false, nodeIntegration: true, - preload: path.join(__dirname, 'preload.js') - } + preload: path.join(__dirname, 'preload.js'), + }, }); mainWindow.loadFile('index.html'); mainWindow.on('ready-to-show', () => { - mainWindow.show(); + mainWindow.show(); }); - if(process.defaultApp){ + if (process.defaultApp) { mainWindow.webContents.openDevTools(); } - menu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(menu); - }; - - app.whenReady().then(() => { - createWindow() - - app.on('activate', function () { - if (BrowserWindow.getAllWindows().length === 0) createWindow() - }) -}) - - - + createWindow(); + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { @@ -70,9 +164,6 @@ app.on('window-all-closed', () => { } }); - - -const { ipcMain } = require('electron') ipcMain.on('enableDeviceDropdown', (event, arg) => { menu.getMenuItemById('devicePin').enabled = true; menu.getMenuItemById('deviceDelete').enabled = true; @@ -89,107 +180,6 @@ ipcMain.on('disableSearchAll', (event, arg) => { menu.getMenuItemById('deviceSearch').enabled = false; }); -ipcMain.on('setDevicePin', function(event, arg){ +ipcMain.on('setDevicePin', (event, arg) => { menu.getMenuItemById('devicePin').checked = arg; -}) - -const isMac = process.platform === 'darwin' - -const menuTemplate = [ - { role: 'appMenu' }, - { - label: "File", - submenu: [ - { - label: "Clear Saved Data", - id: "resetViews", - click: function(menuItem, window, event){ - mainWindow.webContents.send("resetViews"); - - } - }, - { - label: "Reload App", - role: "reload" - }, - { - type: "separator" - }, - isMac ? { role: 'close' } : { role: 'quit' }, - ] - }, - { role: 'editMenu' }, - { - label: "View", - submenu: [ - { role: 'togglefullscreen' }, - { type: 'separator' }, - { - label: "Arrangement 1", - accelerator: "CommandOrControl+1", - id: "window1", - enabled: true, - click: function(menuItem, window, event){ - mainWindow.webContents.send("doSlots1"); - } - }, - { - label: "Arrangement 2", - accelerator: "CommandOrControl+2", - id: "window2", - enabled: true, - click: function(menuItem, window, event){ - mainWindow.webContents.send("doSlots2"); - } - }, - { - label: "Arrangement 3", - accelerator: "CommandOrControl+3", - id: "window3", - enabled: true, - click: function(menuItem, window, event){ - mainWindow.webContents.send("doSlots3"); - } - }, - { type: 'separator' }, - { role: 'toggleDevTools' } - ] - }, - { - label: "Device", - submenu: [ - { - label: "Search for Devices", - accelerator: "CommandOrControl+F", - id: "deviceSearch", - enabled: true, - click: function(menuItem, window, event){ - mainWindow.webContents.send("doSearch"); - } - }, - { - type: "separator" - }, - { - label: "Pinned", - type: "checkbox", - checked: true, - accelerator: "CommandOrControl+P", - id: "devicePin", - enabled: false, - click: function(menuItem, window, event){ - mainWindow.webContents.send("setActiveDevicePinned", menuItem.checked); - } - }, - { - label: "Delete", - accelerator: "CommandOrControl+Backspace", - id: "deviceDelete", - enabled: false, - click: function(menuItem, window, event){ - mainWindow.webContents.send("doDelete"); - } - } - ] - } -] +}); diff --git a/package-lock.json b/package-lock.json index 02f4ee9..750f088 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "cue-view-2", - "version": "1.0.0", + "name": "Cue View", + "version": "0.9.3-pre", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "cue-view-2", - "version": "1.0.0", - "license": "ISC", + "name": "Cue View", + "version": "0.9.3-pre", + "license": "CC BY-SA 4.0", "dependencies": { "bonjour": "^3.5.0", "ejs": "^3.1.5", @@ -25,7 +25,10 @@ "@electron-forge/maker-rpm": "^6.0.0-beta.61", "@electron-forge/maker-squirrel": "^6.0.0-beta.61", "@electron-forge/maker-zip": "^6.0.0-beta.61", - "electron": "^15.2.0" + "electron": "^15.2.0", + "eslint": "^8.6.0", + "eslint-config-prettier": "^8.3.0", + "prettier": "^2.5.1" } }, "node_modules/@electron-forge/async-ora": { @@ -892,12 +895,64 @@ "global-tunnel-ng": "^2.7.1" } }, + "node_modules/@eslint/eslintrc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", + "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.2.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@gar/promisify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", "dev": true }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", + "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", @@ -1302,6 +1357,27 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -1357,6 +1433,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1436,6 +1521,12 @@ "readable-stream": "^2.0.6" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1834,6 +1925,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -2304,6 +2404,12 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -2404,6 +2510,18 @@ "buffer-indexof": "^1.0.0" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -3509,6 +3627,18 @@ "once": "^1.4.0" } }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -3554,7 +3684,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "optional": true, "engines": { "node": ">=10" }, @@ -3562,6 +3691,217 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", + "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.0.5", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.3.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.2.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", + "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", + "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", + "dev": true, + "dependencies": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.1.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -3755,6 +4095,12 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -3797,6 +4143,18 @@ "node": ">=0.8.0" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -3864,6 +4222,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, "node_modules/flora-colossus": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.1.tgz", @@ -3970,6 +4347,12 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "node_modules/galactus": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/galactus/-/galactus-0.2.1.tgz", @@ -4306,6 +4689,33 @@ "node": ">=0.10" } }, + "node_modules/globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globalthis": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", @@ -4544,6 +4954,31 @@ } ] }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4941,6 +5376,18 @@ "node": ">=4" } }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -4965,6 +5412,12 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -5013,6 +5466,19 @@ "json-buffer": "3.0.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -5070,6 +5536,12 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -5613,6 +6085,12 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "optional": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "node_modules/netmask": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", @@ -5961,6 +6439,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -6097,6 +6592,18 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-author": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", @@ -6351,6 +6858,15 @@ "node": ">=6" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -6360,6 +6876,18 @@ "node": ">=4" } }, + "node_modules/prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/pretty-bytes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", @@ -6695,6 +7223,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", @@ -6797,6 +7337,15 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/resolve-package": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-package/-/resolve-package-1.0.1.tgz", @@ -7513,6 +8062,12 @@ "rimraf": "bin.js" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "node_modules/throttleit": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", @@ -7709,6 +8264,18 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -7803,6 +8370,12 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7899,7 +8472,6 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, - "optional": true, "engines": { "node": ">=0.10.0" } @@ -8799,12 +9371,54 @@ "sumchecker": "^3.0.1" } }, + "@eslint/eslintrc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", + "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.2.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, "@gar/promisify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", "dev": true }, + "@humanwhocodes/config-array": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", + "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "@malept/cross-spawn-promise": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", @@ -9090,6 +9704,19 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -9132,6 +9759,12 @@ "uri-js": "^4.2.2" } }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -9189,6 +9822,12 @@ "readable-stream": "^2.0.6" } }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -9502,6 +10141,12 @@ "get-intrinsic": "^1.0.2" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -9832,6 +10477,12 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "optional": true }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -9914,6 +10565,15 @@ "buffer-indexof": "^1.0.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -10752,6 +11412,15 @@ "once": "^1.4.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -10790,8 +11459,160 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", + "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", "dev": true, - "optional": true + "requires": { + "@eslint/eslintrc": "^1.0.5", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.0", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.3.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.2.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", + "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", + "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "dev": true + }, + "espree": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", + "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", + "dev": true, + "requires": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.1.0" + } + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "execa": { "version": "1.0.0", @@ -10951,6 +11772,12 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -10986,6 +11813,15 @@ } } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -11035,6 +11871,22 @@ "path-exists": "^4.0.0" } }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, "flora-colossus": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.1.tgz", @@ -11118,6 +11970,12 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "galactus": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/galactus/-/galactus-0.2.1.tgz", @@ -11404,6 +12262,23 @@ "tunnel": "^0.0.6" } }, + "globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, "globalthis": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", @@ -11575,6 +12450,22 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "devOptional": true }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -11872,6 +12763,15 @@ } } }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -11896,6 +12796,12 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -11938,6 +12844,16 @@ "json-buffer": "3.0.0" } }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -11985,6 +12901,12 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -12415,6 +13337,12 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "optional": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "netmask": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", @@ -12686,6 +13614,20 @@ "is-wsl": "^2.2.0" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -12778,6 +13720,15 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-author": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", @@ -12967,12 +13918,24 @@ "tunnel-agent": "^0.6.0" } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true + }, "pretty-bytes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", @@ -13223,6 +14186,12 @@ "define-properties": "^1.1.3" } }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", @@ -13307,6 +14276,12 @@ "global-modules": "^1.0.0" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "resolve-package": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-package/-/resolve-package-1.0.1.tgz", @@ -13862,6 +14837,12 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "throttleit": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", @@ -14034,6 +15015,15 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -14110,6 +15100,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -14198,8 +15194,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "optional": true + "dev": true }, "wrap-ansi": { "version": "7.0.0", diff --git a/package.json b/package.json index 96750b1..20dbc9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Cue View", - "version": "0.9.2", + "version": "0.9.3-pre", "description": "A dashboard for everything in your show", "main": "main.js", "scripts": { @@ -18,7 +18,10 @@ "@electron-forge/maker-rpm": "^6.0.0-beta.61", "@electron-forge/maker-squirrel": "^6.0.0-beta.61", "@electron-forge/maker-zip": "^6.0.0-beta.61", - "electron": "^15.2.0" + "electron": "^15.2.0", + "eslint": "^8.6.0", + "eslint-config-prettier": "^8.3.0", + "prettier": "^2.5.1" }, "dependencies": { "bonjour": "^3.5.0", diff --git a/plugins/eos/eos.css b/plugins/eos/eos.css index 0cf4477..c9a5c93 100644 --- a/plugins/eos/eos.css +++ b/plugins/eos/eos.css @@ -1,69 +1,68 @@ -table{ - background-color: #141414; - border: #404040 1px solid; - border-radius: 4px; - color: #a59baa; +table { + background-color: #141414; + border: #404040 1px solid; + border-radius: 4px; + color: #a59baa; } -th{ - font-size: 14px; - font-weight: normal; - padding: 5px; +th { + font-size: 14px; + font-weight: normal; + padding: 5px; } -td{ - text-align: center; - padding: 6px; +td { + text-align: center; + padding: 6px; } -td:first-child{ - text-align: left; +td:first-child { + text-align: left; } -td.black{ - background-color: black; - border-right: #212021 1px solid; +td.black { + background-color: black; + border-right: #212021 1px solid; } -td.num{ - color: white; - font-weight: 600; - font-size: 16px; +td.num { + color: white; + font-weight: 600; + font-size: 16px; } -.scene{ - background-color: black; - border-top: #141414 2px solid; - border-bottom: #141414 2px solid; +.scene { + background-color: black; + border-top: #141414 2px solid; + border-bottom: #141414 2px solid; } -.scene hr{ - border: #001f10 4px solid; +.scene hr { + border: #001f10 4px solid; } -.scene span{ - display: table; - margin: 0px auto; - margin-top: -25px; - padding: 4px; - background-color: black; - font-weight: bold; - font-size: 14px; +.scene span { + display: table; + margin: 0px auto; + margin-top: -25px; + padding: 4px; + background-color: black; + font-weight: bold; + font-size: 14px; } -.time{ - border: #2f2b35 2px solid; - border-radius: 5px; +.time { + border: #2f2b35 2px solid; + border-radius: 5px; } -tr.active-cue{ - color: #d49800; +tr.active-cue { + color: #d49800; +} +tr.active-cue td.num { + color: #d49800; +} +tr.active-cue .time { + border-color: #d49800; } - tr.active-cue td.num{ - color: #d49800; - } - tr.active-cue .time{ - border-color: #d49800; - } - @media screen and (min-width: 0px) and (max-width: 750px) { - .hide-medium{ - display: none; - } + .hide-medium { + display: none; + } } @media screen and (min-width: 0px) and (max-width: 550px) { - .hide-small{ - display: none; - } -} \ No newline at end of file + .hide-small { + display: none; + } +} diff --git a/plugins/eos/eos.js b/plugins/eos/eos.js index 811a1fb..ab54d18 100644 --- a/plugins/eos/eos.js +++ b/plugins/eos/eos.js @@ -1,115 +1,144 @@ -exports.defaultName = "ETC Eos"; -exports.connectionType = "osc"; +exports.defaultName = 'ETC Eos'; +exports.connectionType = 'osc'; exports.searchOptions = { - type: "TCPport", - searchBuffer: Buffer.from("\xc0/eos/ping\x00\x00\x2c\x00\x00\x00\xc0", 'ascii'), - testPort: 3032, - validateResponse: function(msg, info){ - return (msg.toString().indexOf("/eos/out")); - } -} + type: 'TCPport', + searchBuffer: Buffer.from( + '\xc0/eos/ping\x00\x00\x2c\x00\x00\x00\xc0', + 'ascii' + ), + testPort: 3032, + validateResponse: function (msg, info) { + return msg.toString().indexOf('/eos/out'); + }, +}; exports.defaultPort = 3032; -//"\xc0/eos/ping\x00\x00\x2c\x00\x00\x00\xc0" +// "\xc0/eos/ping\x00\x00\x2c\x00\x00\x00\xc0" +exports.ready = function (device) { + device.send('/eos/get/cuelist/count'); + device.send('/eos/get/version'); + device.send('/eos/subscribe', [{ type: 'i', value: 1 }]); +}; -exports.ready = function(device){ - device.send("/eos/get/cuelist/count"); - device.send("/eos/get/version"); - device.send("/eos/subscribe", [{type: "i", value: 1}]); -} +exports.data = function (device, osc) { + const address = osc.address; + const p = osc.address.split('/'); + p.shift(); -exports.data = function(device, osc){ - var address = osc.address; - var p = osc.address.split("/"); - p.shift(); + if (p[1] == 'out' && p[2] == 'show' && p[3] == 'name') { + device.data.showName = osc.args[0]; + device.data.cuelists = {}; + this.deviceInfoUpdate(device, 'defaultName', osc.args[0]); + } else if (osc.address == '/eos/out/get/cuelist/count') { + for (let i = 0; i < osc.args[0]; i++) { + device.send(`/eos/get/cuelist/index/${i}`); + } + } else if ( + p[1] == 'out' && + p[2] == 'get' && + p[3] == 'cuelist' && + p[5] == 'list' + ) { + device.data.cuelists[p[4]] = {}; + device.send(`/eos/get/cue/${p[4]}/count`); + } else if ( + p[1] == 'out' && + p[2] == 'get' && + p[3] == 'cue' && + p[5] == 'count' + ) { + for (let i = 0; i < osc.args[0]; i++) { + device.send(`'/eos/get/cue/${p[4]}/index/${i}`); + } + } else if ( + p[1] == 'out' && + p[2] == 'get' && + p[3] == 'cue' && + p[7] == 'list' + ) { + this.deviceInfoUpdate(device, 'status', 'ok'); + if (device.data.cuelists[p[4]][p[5]] == undefined) { + device.data.cuelists[p[4]][p[5]] = {}; + } + device.data.cuelists[p[4]][p[5]][p[6]] = { + uid: osc.args[1], + label: osc.args[2], + uptimeduration: osc.args[3], + uptimedelay: osc.args[4], + downtimeduration: osc.args[5], + downtimedelay: osc.args[6], + focustimeduration: osc.args[7], + focustimedelay: osc.args[8], + colortimeduration: osc.args[9], + colortimedelay: osc.args[10], + beamtimeduration: osc.args[11], + beamtimedelay: osc.args[12], + mark: osc.args[16], + block: osc.args[17], + assert: osc.args[18], + follow: osc.args[20], + hang: osc.args[21], + partcount: osc.args[26], + scene: osc.args[28], + duration: Math.max( + osc.args[3], + osc.args[5], + osc.args[7], + osc.args[9], + osc.args[11] + ), + }; - if(p[1]=="out" && p[2]=="show" && p[3]=="name"){ - device.data.showName = osc.args[0]; - device.data.cuelists = {}; - this.deviceInfoUpdate(device, "defaultName", osc.args[0]); - }else if(osc.address=="/eos/out/get/cuelist/count"){ - for(var i=0; i -

<%= listName %>

-

<%= data.model %>

+

<%= listName %>

+

<%= data.model %>

- - - - - - - - - - - - - - - <% for(var i=0; i<32; i++){ %> - <% if(data.channelNames[i]=="end"){break;} %> - - - - - - - - <% } %> - + + + + + + + + + + + + + + + <% for(var i=0; i<32; i++){ %> <% if(data.channelNames[i]=="end"){break;} %> + + + + + + + + <% } %>
ChannelMutedBFader
LR
MAIN OUT
M
<%- formatAsDB(data.stereoFaderDB) %>
<%= i+1 %>
<%- data.channelNames[i] || i+1 %>
M
<%- formatAsDB(data.channelFadersDB[i]) %>
ChannelMutedBFader
LR
MAIN OUT
M
<%- formatAsDB(data.stereoFaderDB) %> + +
<%= i+1 %> +
+ <%- data.channelNames[i] || i+1 %> +
+
M
<%- formatAsDB(data.channelFadersDB[i]) %> + +
- - -<% -function formatAsDB(val){ - if(val==-90){ - return "-∞"; - } - if(val>0){ - return "+"+val.toFixed(1); - } - return val.toFixed(1); -} - -%> \ No newline at end of file +<% function formatAsDB(val){ if(val==-90){ return "-∞"; } if(val>0){ +return "+"+val.toFixed(1); } return val.toFixed(1); } %> diff --git a/plugins/x32/x32.js b/plugins/x32/x32.js index e63c418..7e20e5b 100644 --- a/plugins/x32/x32.js +++ b/plugins/x32/x32.js @@ -1,129 +1,130 @@ -exports.defaultName = "X32 Mixer"; -exports.connectionType = "UDPsocket"; +exports.defaultName = 'X32 Mixer'; +exports.connectionType = 'UDPsocket'; exports.heartbeatInterval = 10000; exports.searchOptions = { - type: "UDPsocket", - searchBuffer: Buffer.from([0x2f, 0x78, 0x69, 0x6e, 0x66, 0x6f]), - devicePort: 10023, - listenPort: 0, - validateResponse: function(msg, info){ - return (msg.toString().indexOf("/xinfo")==0); - } -} + type: 'UDPsocket', + searchBuffer: Buffer.from([0x2f, 0x78, 0x69, 0x6e, 0x66, 0x6f]), + devicePort: 10023, + listenPort: 0, + validateResponse: function (msg, info) { + return msg.toString().indexOf('/xinfo') == 0; + }, +}; exports.defaultPort = 10023; -exports.ready = function(device){ +exports.ready = function (device) { + device.data.channelFaders = new Array(32).fill(0); + device.data.channelFadersDB = new Array(32).fill(0); + device.data.channelMutes = new Array(32).fill(0); + device.data.channelNames = new Array(32).fill('end'); + device.data.channelColors = new Array(32); - device.data.channelFaders = new Array(32).fill(0); - device.data.channelFadersDB = new Array(32).fill(0); - device.data.channelMutes = new Array(32).fill(0); - device.data.channelNames = new Array(32).fill("end"); - device.data.channelColors = new Array(32); + device.data.stereoFader = 0; + device.data.stereoFaderDB = 0; + device.data.stereoMute = 0; - device.data.stereoFader = 0; - device.data.stereoFaderDB = 0; - device.data.stereoMute = 0; + device.send(Buffer.from('/xinfo')); - device.send(Buffer.from("/xinfo")); + // device.send(Buffer.from("\x2f\x62\x61\x74\x63\x68\x73\x75\x62\x73\x63\x72\x69\x62\x65\x00\x2c\x73\x73\x69\x69\x69\x00\x00\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x2f\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); + // device.send(Buffer.from("/batchsubscribe\x00,ssiii\x00\x00meters/0\x00\x00\x00\x00/meters/0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); + // device.send(Buffer.from("/subscribe\x00,si\x00/-stat/solosw/01\x001")); +}; - //device.send(Buffer.from("\x2f\x62\x61\x74\x63\x68\x73\x75\x62\x73\x63\x72\x69\x62\x65\x00\x2c\x73\x73\x69\x69\x69\x00\x00\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x2f\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); - //device.send(Buffer.from("/batchsubscribe\x00,ssiii\x00\x00meters/0\x00\x00\x00\x00/meters/0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); - - //device.send(Buffer.from("/subscribe\x00,si\x00/-stat/solosw/01\x001")); - +function parseAddress(msg) { + const addr = msg.split('/'); + addr.shift(); + return addr; } -exports.data = function(device, buf){ - this.deviceInfoUpdate(device, "status", "ok"); - var msg = buf.toString().split('\u0000\u0000') - - if(msg[0]=="/xinfo"){ - this.deviceInfoUpdate(device, "defaultName", msg[4]); - device.data.name = msg[4]; - device.data.ip = msg[2]; - device.data.firmware = msg[7]; - device.data.model = msg[5]; - - - device.send(Buffer.from("/lr/mix/fader\u0000\u0000\u0000\u0000")); - device.send(Buffer.from("/lr/mix/on\u0000\u0000\u0000\u0000")); - - for(var i=0; i<=32; i++){ - device.send(Buffer.from("/ch/"+i.toString().padStart(2, "0")+"/config/name\u0000\u0000\u0000\u0000")); - } - device.draw(); - - - }else if(msg[0]=="/meters/0"){ - //console.log(msg) - }else if(msg[0].indexOf("/mix/fader")>=0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - - if(addr[0]=="ch"){ - device.data.channelFaders[channel-1] = buf.readFloatBE(24); - device.data.channelFadersDB[channel-1] = convertToDBTheBehringerWay(buf.readFloatBE(24)); - }else if(addr[0]=="lr"){ - device.data.stereoFader = buf.readFloatBE(20); - device.data.stereoFaderDB = convertToDBTheBehringerWay(buf.readFloatBE(20)); - } - - device.draw(); - - }else if(msg[0].indexOf("/mix/on")>=0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - - if(addr[0]=="ch"){ - device.data.channelMutes[channel-1] = buf[23]; - }else if(addr[0]=="lr"){ - device.data.stereoMute = buf[19]; - } - device.draw(); - device.send(Buffer.from("/ch/"+addr[1]+"/mix/fader\u0000\u0000\u0000\u0000")); - - }else if(msg[0].indexOf("/config/name")>0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - device.data.channelNames[channel-1] = msg[2]; - device.draw(); - device.send(Buffer.from("/ch/"+addr[1]+"/config/color\u0000\u0000\u0000\u0000")); - - }else if(msg[0].indexOf("/config/color")>0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - device.data.channelColors[channel-1] = buf.readInt8(27); - device.draw(); - device.send(Buffer.from("/ch/"+addr[1]+"/mix/on\u0000\u0000\u0000\u0000")); - - }else{ - //console.log(msg) - } - //console.log(msg) - +function convertToDBTheBehringerWay(f) { + if (f >= 0.5) { + return f * 40 - 30; + } else if (f >= 0.25) { + return f * 80 - 50; + } else if (f >= 0.0625) { + return f * 160 - 70; + } else { + return f * 480 - 90; + } } -exports.heartbeat = function(device){ - device.send(Buffer.from("/xremote")); -} +exports.data = function (device, buf) { + this.deviceInfoUpdate(device, 'status', 'ok'); + const msg = buf.toString().split('\u0000\u0000'); + if (msg[0] == '/xinfo') { + this.deviceInfoUpdate(device, 'defaultName', msg[4]); + device.data.name = msg[4]; + device.data.ip = msg[2]; + device.data.firmware = msg[7]; + device.data.model = msg[5]; -function parseAddress(msg){ - var addr = msg.split("/"); - addr.shift(); - return addr; -} + device.send(Buffer.from('/lr/mix/fader\u0000\u0000\u0000\u0000')); + device.send(Buffer.from('/lr/mix/on\u0000\u0000\u0000\u0000')); -function convertToDBTheBehringerWay(f){ - if(f>=0.5){ - return f*40-30; - }else if(f>=0.25){ - return f*80-50; - }else if(f>=0.0625){ - return f*160-70; - }else{ - return f*480-90; - } -} + for (let i = 0; i <= 32; i++) { + device.send( + Buffer.from( + `/ch/${i + .toString() + .padStart(2, '0')}/config/name\u0000\u0000\u0000\u0000` + ) + ); + } + device.draw(); + } else if (msg[0] == '/meters/0') { + // console.log(msg) + } else if (msg[0].indexOf('/mix/fader') >= 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + if (addr[0] == 'ch') { + device.data.channelFaders[channel - 1] = buf.readFloatBE(24); + device.data.channelFadersDB[channel - 1] = convertToDBTheBehringerWay( + buf.readFloatBE(24) + ); + } else if (addr[0] == 'lr') { + device.data.stereoFader = buf.readFloatBE(20); + device.data.stereoFaderDB = convertToDBTheBehringerWay( + buf.readFloatBE(20) + ); + } + + device.draw(); + } else if (msg[0].indexOf('/mix/on') >= 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + + if (addr[0] == 'ch') { + device.data.channelMutes[channel - 1] = buf[23]; + } else if (addr[0] == 'lr') { + device.data.stereoMute = buf[19]; + } + device.draw(); + device.send( + Buffer.from(`/ch/${addr[1]}/mix/fader\u0000\u0000\u0000\u0000`) + ); + } else if (msg[0].indexOf('/config/name') > 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + device.data.channelNames[channel - 1] = msg[2]; + device.draw(); + device.send( + Buffer.from(`/ch/${addr[1]}/config/color\u0000\u0000\u0000\u0000`) + ); + } else if (msg[0].indexOf('/config/color') > 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + device.data.channelColors[channel - 1] = buf.readInt8(27); + device.draw(); + device.send(Buffer.from(`/ch/${addr[1]}/mix/on\u0000\u0000\u0000\u0000`)); + } else { + // console.log(msg) + } + // console.log(msg) +}; + +exports.heartbeat = function (device) { + device.send(Buffer.from('/xremote')); +}; diff --git a/plugins/xair/xair.css b/plugins/xair/xair.css index c95aead..1f25d39 100644 --- a/plugins/xair/xair.css +++ b/plugins/xair/xair.css @@ -1,103 +1,119 @@ -td{ - padding: 3px 16px !important; +td { + padding: 3px 16px !important; } -tr td:first-child{ - text-align: center; +tr td:first-child { + text-align: center; } -.mute-0, .mute-1{ - width: 30px; - padding: 4px; - font-size: 14px; - border: black 2px solid; - text-align: center; - border-radius: 10px; +.mute-0, +.mute-1 { + width: 30px; + padding: 4px; + font-size: 14px; + border: black 2px solid; + text-align: center; + border-radius: 10px; } -.mute-1{ - border-color: gray; - color: gray; +.mute-1 { + border-color: gray; + color: gray; } -.mute-0{ - border-color: #fc3344; - color: #fc3344; +.mute-0 { + border-color: #fc3344; + color: #fc3344; } -.white{ - color: white; +.white { + color: white; } -.color{ - padding: 1px 6px; - border-radius: 10px; - color: black; - font-family: PlexMono !important; - text-align: center; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; +.color { + padding: 1px 6px; + border-radius: 10px; + color: black; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } -.color-0{ /*Black*/ - background-color: #212121; - color: white; +.color-0 { + /*Black*/ + background-color: #212121; + color: white; } -.color-1{ /*Red*/ - background-color: #fc545b; +.color-1 { + /*Red*/ + background-color: #fc545b; } -.color-2{ /*Green*/ - background-color: #65b84d; +.color-2 { + /*Green*/ + background-color: #65b84d; } -.color-3{ /*Yellow*/ - background-color: #fec52e; +.color-3 { + /*Yellow*/ + background-color: #fec52e; } -.color-4{ /*Blue*/ - background-color: #157efb; +.color-4 { + /*Blue*/ + background-color: #157efb; } -.color-5{ /*Purple*/ - background-color: #a453a5; +.color-5 { + /*Purple*/ + background-color: #a453a5; } -.color-6{ /*Teal*/ - background-color: #00dae3; +.color-6 { + /*Teal*/ + background-color: #00dae3; } -.color-7{ /*White*/ - background-color: #e0e0e0; +.color-7 { + /*White*/ + background-color: #e0e0e0; } -.color-8{ /*Gray*/ - background-color: #8c8c8c; +.color-8 { + /*Gray*/ + background-color: #8c8c8c; } -.color-9{ /*Red*/ - color: #fc545b; - border: #fc545b 1px solid; +.color-9 { + /*Red*/ + color: #fc545b; + border: #fc545b 1px solid; } -.color-10{ /*Green*/ - color: #65b84d; - border: #65b84d 1px solid; +.color-10 { + /*Green*/ + color: #65b84d; + border: #65b84d 1px solid; } -.color-11{ /*Yellow*/ - color: #fec52e; - border: #fec52e 1px solid; +.color-11 { + /*Yellow*/ + color: #fec52e; + border: #fec52e 1px solid; } -.color-12{ /*Blue*/ - color: #157efb; - border: #157efb 1px solid; +.color-12 { + /*Blue*/ + color: #157efb; + border: #157efb 1px solid; } -.color-13{ /*Purple*/ - color: #a453a5; - border: #a453a5 1px solid; +.color-13 { + /*Purple*/ + color: #a453a5; + border: #a453a5 1px solid; } -.color-14{ /*Teal*/ - color: #00dae3; - border: #00dae3 1px solid; +.color-14 { + /*Teal*/ + color: #00dae3; + border: #00dae3 1px solid; } -.color-15{ /*White*/ - color: #e0e0e0; - border: #e0e0e0 1px solid; +.color-15 { + /*White*/ + color: #e0e0e0; + border: #e0e0e0 1px solid; } -input[type=range] { +input[type='range'] { -webkit-appearance: none; margin: 0px; width: 100%; } -input[type=range]::-webkit-slider-thumb { +input[type='range']::-webkit-slider-thumb { -webkit-appearance: none; margin-top: -9px; height: 26px; @@ -105,9 +121,9 @@ input[type=range]::-webkit-slider-thumb { border-radius: 4px; background: #929292; } -input[type=range]::-webkit-slider-runnable-track { +input[type='range']::-webkit-slider-runnable-track { width: 100%; height: 8px; background: #3b3b3b; border-radius: 4px; -} \ No newline at end of file +} diff --git a/plugins/xair/xair.html b/plugins/xair/xair.html index a534112..c0f95c1 100644 --- a/plugins/xair/xair.html +++ b/plugins/xair/xair.html @@ -1,47 +1,51 @@
-

<%= listName %>

-

<%= data.model %>

+

<%= listName %>

+

<%= data.model %>

- - - - - - - - - - - - - - - <% for(var i=0; i<32; i++){ %> - <% if(data.channelNames[i]=="end"){break;} %> - - - - - - - - <% } %> - + + + + + + + + + + + + + + + <% for(var i=0; i<32; i++){ %> <% if(data.channelNames[i]=="end"){break;} %> + + + + + + + + <% } %>
ChannelMutedBFader
LR
MAIN OUT
M
<%- formatAsDB(data.stereoFaderDB) %>
<%= i+1 %>
<%- data.channelNames[i] || i+1 %>
M
<%- formatAsDB(data.channelFadersDB[i]) %>
ChannelMutedBFader
LR
MAIN OUT
M
<%- formatAsDB(data.stereoFaderDB) %> + +
<%= i+1 %> +
+ <%- data.channelNames[i] || i+1 %> +
+
M
<%- formatAsDB(data.channelFadersDB[i]) %> + +
- - -<% -function formatAsDB(val){ - if(val==-90){ - return "-∞"; - } - if(val>0){ - return "+"+val.toFixed(1); - } - return val.toFixed(1); -} - -%> \ No newline at end of file +<% function formatAsDB(val){ if(val==-90){ return "-∞"; } if(val>0){ +return "+"+val.toFixed(1); } return val.toFixed(1); } %> diff --git a/plugins/xair/xair.js b/plugins/xair/xair.js index 85f5ea3..f7ec70b 100644 --- a/plugins/xair/xair.js +++ b/plugins/xair/xair.js @@ -1,129 +1,135 @@ -exports.defaultName = "X Air Mixer"; -exports.connectionType = "UDPsocket"; +exports.defaultName = 'X Air Mixer'; +exports.connectionType = 'UDPsocket'; exports.heartbeatInterval = 10000; exports.searchOptions = { - type: "UDPsocket", - searchBuffer: Buffer.from([0x2f, 0x78, 0x69, 0x6e, 0x66, 0x6f]), - devicePort: 10024, - listenPort: 0, - validateResponse: function(msg, info){ - return (msg.toString().indexOf("/xinfo")==0); - } -} + type: 'UDPsocket', + searchBuffer: Buffer.from([0x2f, 0x78, 0x69, 0x6e, 0x66, 0x6f]), + devicePort: 10024, + listenPort: 0, + validateResponse: function (msg, info) { + return msg.toString().indexOf('/xinfo') == 0; + }, +}; exports.defaultPort = 10024; -exports.ready = function(device){ +exports.ready = function (device) { + device.data.channelFaders = new Array(32).fill(0); + device.data.channelFadersDB = new Array(32).fill(0); + device.data.channelMutes = new Array(32).fill(0); + device.data.channelNames = new Array(32).fill('end'); + device.data.channelColors = new Array(32); - device.data.channelFaders = new Array(32).fill(0); - device.data.channelFadersDB = new Array(32).fill(0); - device.data.channelMutes = new Array(32).fill(0); - device.data.channelNames = new Array(32).fill("end"); - device.data.channelColors = new Array(32); + device.data.stereoFader = 0; + device.data.stereoFaderDB = 0; + device.data.stereoMute = 0; - device.data.stereoFader = 0; - device.data.stereoFaderDB = 0; - device.data.stereoMute = 0; + device.send(Buffer.from('/xinfo')); - device.send(Buffer.from("/xinfo")); + // device.send(Buffer.from("\x2f\x62\x61\x74\x63\x68\x73\x75\x62\x73\x63\x72\x69\x62\x65\x00\x2c\x73\x73\x69\x69\x69\x00\x00\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x2f\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); + // device.send(Buffer.from("/batchsubscribe\x00,ssiii\x00\x00meters/0\x00\x00\x00\x00/meters/0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); + // device.send(Buffer.from("/subscribe\x00,si\x00/-stat/solosw/01\x001")); +}; - //device.send(Buffer.from("\x2f\x62\x61\x74\x63\x68\x73\x75\x62\x73\x63\x72\x69\x62\x65\x00\x2c\x73\x73\x69\x69\x69\x00\x00\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x2f\x6d\x65\x74\x65\x72\x73\x2f\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); - //device.send(Buffer.from("/batchsubscribe\x00,ssiii\x00\x00meters/0\x00\x00\x00\x00/meters/0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")); - - //device.send(Buffer.from("/subscribe\x00,si\x00/-stat/solosw/01\x001")); - +function parseAddress(msg) { + const addr = msg.split('/'); + addr.shift(); + return addr; } -exports.data = function(device, buf){ - this.deviceInfoUpdate(device, "status", "ok"); - var msg = buf.toString().split('\u0000\u0000') - - if(msg[0]=="/xinfo"){ - this.deviceInfoUpdate(device, "defaultName", msg[4]); - device.data.name = msg[4]; - device.data.ip = msg[2]; - device.data.firmware = msg[7]; - device.data.model = msg[5]; - - - device.send(Buffer.from("/lr/mix/fader\u0000\u0000\u0000\u0000")); - device.send(Buffer.from("/lr/mix/on\u0000\u0000\u0000\u0000")); - - for(var i=0; i<=32; i++){ - device.send(Buffer.from("/ch/"+i.toString().padStart(2, "0")+"/config/name\u0000\u0000\u0000\u0000")); - } - device.draw(); - - - }else if(msg[0]=="/meters/0"){ - //console.log(msg) - }else if(msg[0].indexOf("/mix/fader")>=0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - - if(addr[0]=="ch"){ - device.data.channelFaders[channel-1] = buf.readFloatBE(24); - device.data.channelFadersDB[channel-1] = convertToDBTheBehringerWay(buf.readFloatBE(24)); - }else if(addr[0]=="lr"){ - device.data.stereoFader = buf.readFloatBE(20); - device.data.stereoFaderDB = convertToDBTheBehringerWay(buf.readFloatBE(20)); - } - - device.draw(); - - }else if(msg[0].indexOf("/mix/on")>=0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - - if(addr[0]=="ch"){ - device.data.channelMutes[channel-1] = buf[23]; - }else if(addr[0]=="lr"){ - device.data.stereoMute = buf[19]; - } - device.draw(); - device.send(Buffer.from("/ch/"+addr[1]+"/mix/fader\u0000\u0000\u0000\u0000")); - - }else if(msg[0].indexOf("/config/name")>0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - device.data.channelNames[channel-1] = msg[2]; - device.draw(); - device.send(Buffer.from("/ch/"+addr[1]+"/config/color\u0000\u0000\u0000\u0000")); - - }else if(msg[0].indexOf("/config/color")>0){ - var addr = parseAddress(msg[0]); - var channel = Number(addr[1]); - device.data.channelColors[channel-1] = buf.readInt8(27); - device.draw(); - device.send(Buffer.from("/ch/"+addr[1]+"/mix/on\u0000\u0000\u0000\u0000")); - - }else{ - //console.log(msg) - } - //console.log(msg) - +function convertToDBTheBehringerWay(f) { + if (f >= 0.5) { + return f * 40 - 30; + } else if (f >= 0.25) { + return f * 80 - 50; + } else if (f >= 0.0625) { + return f * 160 - 70; + } else { + return f * 480 - 90; + } } -exports.heartbeat = function(device){ - device.send(Buffer.from("/xremote")); -} +exports.data = function (device, buf) { + this.deviceInfoUpdate(device, 'status', 'ok'); + const msg = buf.toString().split('\u0000'); + if (msg[0] == '/xinfo') { + if (msg[7].length > 0) { + device.data.name = msg[7]; + } else { + device.data.name = msg[6]; + } -function parseAddress(msg){ - var addr = msg.split("/"); - addr.shift(); - return addr; -} + device.data.ip = msg[5]; + device.data.firmware = msg[13]; + device.data.model = msg[9]; + this.deviceInfoUpdate(device, 'defaultName', device.data.name); -function convertToDBTheBehringerWay(f){ - if(f>=0.5){ - return f*40-30; - }else if(f>=0.25){ - return f*80-50; - }else if(f>=0.0625){ - return f*160-70; - }else{ - return f*480-90; - } -} + device.send(Buffer.from('/lr/mix/fader\u0000\u0000\u0000\u0000')); + device.send(Buffer.from('/lr/mix/on\u0000\u0000\u0000\u0000')); + for (let i = 0; i <= 32; i++) { + device.send( + Buffer.from( + `/ch/${i + .toString() + .padStart(2, '0')}/config/name\u0000\u0000\u0000\u0000` + ) + ); + } + device.draw(); + } else if (msg[0] == '/meters/0') { + // console.log(msg) + } else if (msg[0].indexOf('/mix/fader') >= 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + + if (addr[0] == 'ch') { + device.data.channelFaders[channel - 1] = buf.readFloatBE(24); + device.data.channelFadersDB[channel - 1] = convertToDBTheBehringerWay( + buf.readFloatBE(24) + ); + } else if (addr[0] == 'lr') { + device.data.stereoFader = buf.readFloatBE(20); + device.data.stereoFaderDB = convertToDBTheBehringerWay( + buf.readFloatBE(20) + ); + } + + device.draw(); + } else if (msg[0].indexOf('/mix/on') >= 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + + if (addr[0] == 'ch') { + device.data.channelMutes[channel - 1] = buf[23]; + } else if (addr[0] == 'lr') { + device.data.stereoMute = buf[19]; + } + device.draw(); + device.send( + Buffer.from(`/ch/${addr[1]}/mix/fader\u0000\u0000\u0000\u0000`) + ); + } else if (msg[0].indexOf('/config/name') > 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + device.data.channelNames[channel - 1] = msg[4]; + device.draw(); + device.send( + Buffer.from(`/ch/${addr[1]}/config/color\u0000\u0000\u0000\u0000`) + ); + } else if (msg[0].indexOf('/config/color') > 0) { + const addr = parseAddress(msg[0]); + const channel = Number(addr[1]); + device.data.channelColors[channel - 1] = buf.readInt8(27); + device.draw(); + device.send(Buffer.from(`/ch/${addr[1]}/mix/on\u0000\u0000\u0000\u0000`)); + } else { + // console.log(msg) + } + // console.log(msg) +}; + +exports.heartbeat = function (device) { + device.send(Buffer.from('/xremote')); +}; diff --git a/preload.js b/preload.js index 26075e0..d415e87 100644 --- a/preload.js +++ b/preload.js @@ -1,215 +1,181 @@ - -const { remote } = require('electron'); +// const { remote } = require('electron'); const { ipcRenderer } = require('electron'); -//let currWindow = remote.BrowserWindow.getFocusedWindow(); -const { v4: uuid } = require('uuid'); -let ejs = require('ejs'); +// let currWindow = remote.BrowserWindow.getFocusedWindow(); +// const { v4: uuid } = require('uuid'); +// const ejs = require('ejs'); -let net = require("net"); +// const net = require('net'); - - -let DEVICE = require("./src/device.js"); -let PLUGINS = require("./src/plugins.js"); -let SEARCH = require("./src/search.js"); -let VIEW = require("./src/view.js"); -let SAVESLOTS = require("./src/saveSlots.js"); +const DEVICE = require('./src/device.js'); +const PLUGINS = require('./src/plugins.js'); +// const SEARCH = require('./src/search.js'); +const VIEW = require('./src/view.js'); +const SAVESLOTS = require('./src/saveSlots.js'); window.addDevice = DEVICE.addDevice; +window.init = function () { + console.log('init!'); + ipcRenderer.send('enableDeviceDropdown'); + ipcRenderer.send('enableSearchAll'); -window.init = function(){ - - console.log("init!") - - ipcRenderer.send("enableDeviceDropdown"); - ipcRenderer.send("enableSearchAll"); - - PLUGINS.init(function(){ + PLUGINS.init(() => { VIEW.init(); SAVESLOTS.loadDevices(); SAVESLOTS.loadSlot(1); }); - document.getElementById("device-settings-table").onclick = function(e){ + document.getElementById('device-settings-table').onclick = function (e) { e.stopPropagation(); - } - document.getElementById("device-settings-name").onchange = function(e){ + }; + document.getElementById('device-settings-name').onchange = function (e) { e.stopPropagation(); - DEVICE.changeActiveName(e.target.value) - } - document.getElementById("device-settings-plugin-dropdown").onchange = function(e){ + DEVICE.changeActiveName(e.target.value); + }; + document.getElementById('device-settings-plugin-dropdown').onchange = + function (e) { + e.stopPropagation(); + DEVICE.changeActiveType(e.target.value); + }; + document.getElementById('device-settings-ip').onchange = function (e) { e.stopPropagation(); - DEVICE.changeActiveType(e.target.value) - } - document.getElementById("device-settings-ip").onchange = function(e){ + DEVICE.changeActiveIP(e.target.value); + }; + document.getElementById('device-settings-port').onchange = function (e) { e.stopPropagation(); - DEVICE.changeActiveIP(e.target.value) - } - document.getElementById("device-settings-port").onchange = function(e){ + DEVICE.changeActivePort(e.target.value); + }; + document.getElementById('device-settings-pin').onchange = function (e) { e.stopPropagation(); - DEVICE.changeActivePort(e.target.value) - } - document.getElementById("device-settings-pin").onchange = function(e){ - e.stopPropagation(); - if(e.target.checked){ + if (e.target.checked) { VIEW.pinActiveDevice(); - }else{ + } else { VIEW.unpinActiveDevice(); } - } + }; - document.getElementById("save-slot-1").onclick = function(e){ - e.stopPropagation(); - SAVESLOTS.loadSlot(1); - } - document.getElementById("save-slot-2").onclick = function(e){ - e.stopPropagation(); - SAVESLOTS.loadSlot(2); - } - document.getElementById("save-slot-3").onclick = function(e){ - e.stopPropagation(); - SAVESLOTS.loadSlot(3); - } - - document.getElementById("refresh-device-button").onclick = function(e){ + document.getElementById('save-slot-1').onclick = function (e) { e.stopPropagation(); - DEVICE.refreshActive() - } + SAVESLOTS.loadSlot(1); + }; + document.getElementById('save-slot-2').onclick = function (e) { + e.stopPropagation(); + SAVESLOTS.loadSlot(2); + }; + document.getElementById('save-slot-3').onclick = function (e) { + e.stopPropagation(); + SAVESLOTS.loadSlot(3); + }; - document.getElementById("device-list").onclick = function(e){ - e.stopPropagation(); - var deviceID = e.srcElement.id; - if(e.srcElement.id != "device-list"){ - VIEW.switchDevice(deviceID); - } - } + document.getElementById('refresh-device-button').onclick = function (e) { + e.stopPropagation(); + DEVICE.refreshActive(); + }; - document.getElementById("add-device-button").onchange = function(e){ + document.getElementById('device-list').onclick = function (e) { + e.stopPropagation(); + const deviceID = e.srcElement.id; + if (e.srcElement.id != 'device-list') { + VIEW.switchDevice(deviceID); + } + }; - DEVICE.registerDevice({ + document.getElementById('add-device-button').onchange = function (e) { + DEVICE.registerDevice({ type: e.target.value, - defaultName: "New Device", + defaultName: 'New Device', port: undefined, - addresses: [] + addresses: [], }); e.target.selectedIndex = 0; SAVESLOTS.saveAll(); + }; - } - - - - document.onkeyup = function(e){ - switch(e.key){ - case "ArrowUp": + document.onkeyup = function (e) { + switch (e.key) { + case 'ArrowUp': VIEW.selectPreviousDevice(); break; - case "ArrowDown": + case 'ArrowDown': VIEW.selectNextDevice(); break; - case "Tab": - if(document.activeElement.tagName!="INPUT" && document.activeElement.tagName!="SELECT"){ - document.getElementById("device-settings-name").select(); + case 'Tab': + if ( + document.activeElement.tagName != 'INPUT' && + document.activeElement.tagName != 'SELECT' + ) { + document.getElementById('device-settings-name').select(); } break; } - } - + }; // document.getElementById("device-settings-delete").onclick = function(e){ // e.stopPropagation(); // confirm("Are you sure you want to delete device \n\""+VIEW.getActiveDevice().name+"\"?") // } + document.getElementById('device-list-col').onclick = function (e) { + try { + document + .querySelector('#device-list .active-device') + .classList.remove('active-device'); + ipcRenderer.send('disableDeviceDropdown', ''); + } catch (err) { + // console.log(err) + } + try { + document + .getElementsByClassName('active-device-outline')[0] + .classList.remove('active-device-outline'); + } catch (err) { + // console.log(err) + } - - document.getElementById("device-list-col").onclick = function(e){ - - try{ - document.querySelector("#device-list .active-device").classList.remove("active-device"); - ipcRenderer.send("disableDeviceDropdown", ""); - }catch(err){ - //console.log(err) - } - try{ - document.getElementsByClassName("active-device-outline")[0].classList.remove("active-device-outline"); - }catch(err){ - //console.log(err) - } - VIEW.switchDevice(); - } + }; +}; - - - - -} - - - - - - - - - - - -ipcRenderer.on("setActiveDevicePinned", function(event, message){ - if(!message){ +ipcRenderer.on('setActiveDevicePinned', (event, message) => { + if (!message) { VIEW.unpinActiveDevice(); - }else{ + } else { VIEW.pinActiveDevice(); } }); -ipcRenderer.on("doSearch", function(event, message){ +ipcRenderer.on('doSearch', (event, message) => { window.searchAll(); }); -ipcRenderer.on("doDelete", function(event, message){ +ipcRenderer.on('doDelete', (event, message) => { DEVICE.deleteActive(); }); -ipcRenderer.on("resetViews", function(event, message){ +ipcRenderer.on('resetViews', (event, message) => { SAVESLOTS.resetSlots(); }); -ipcRenderer.on("doSlots1", function(event, message){ +ipcRenderer.on('doSlots1', (event, message) => { SAVESLOTS.loadSlot(1); }); -ipcRenderer.on("doSlots2", function(event, message){ +ipcRenderer.on('doSlots2', (event, message) => { SAVESLOTS.loadSlot(2); }); -ipcRenderer.on("doSlots3", function(event, message){ +ipcRenderer.on('doSlots3', (event, message) => { SAVESLOTS.loadSlot(3); }); - - - - - - -function log(type, message){ - -} - -function switchClass(element, className){ - try{ +function switchClass(element, className) { + try { document.getElementsByClassName(className)[0].classList.remove(className); - }catch(err){ - //console.log(err) + } catch (err) { + // console.log(err) } element.classList.add(className); } -window.switchClass = function(element, className){ +window.switchClass = function (element, className) { switchClass(element, className); -} - - - +}; diff --git a/src/defaultPlugin.css b/src/defaultPlugin.css index 7dddec1..82d485e 100644 --- a/src/defaultPlugin.css +++ b/src/defaultPlugin.css @@ -1,96 +1,86 @@ -body{ - color: #6e6c6f; - font-family: sans-serif; - margin: 0px; - margin-top: 40px; - user-select: none; - /*overflow-x: hidden;*/ - visibility: visible !important; - max-width: 100%; - padding: 10px; - +body { + color: #6e6c6f; + font-family: sans-serif; + margin: 0px; + margin-top: 40px; + user-select: none; + /*overflow-x: hidden;*/ + visibility: visible !important; + max-width: 100%; + padding: 10px; } -header{ - position: fixed; - top: 0px; - left: 0px; - height: 36px; - width: 100%; - box-sizing:content-box; +header { + position: fixed; + top: 0px; + left: 0px; + height: 36px; + width: 100%; + box-sizing: content-box; - background-color: rgba(0, 0, 0, 0.2); - border-bottom: black 1px solid; - -webkit-app-region: drag; + background-color: rgba(0, 0, 0, 0.2); + border-bottom: black 1px solid; + -webkit-app-region: drag; } -h1, h2, h3, h4, h5, h6{ - color: white; +h1, +h2, +h3, +h4, +h5, +h6 { + color: white; } -header h1, header h2{ - margin: 8px; - margin-left: 20px; - font-weight: normal; - font-size: 18px; - float: left; +header h1, +header h2 { + margin: 8px; + margin-left: 20px; + font-weight: normal; + font-size: 18px; + float: left; } -header h2{ - color: #b6b6b6; +header h2 { + color: #b6b6b6; } - -table.cv-table{ - border: none; - table-layout: fixed; - border-collapse: collapse; - color: #dddddd; - font-size: 15px; +table.cv-table { + border: none; + table-layout: fixed; + border-collapse: collapse; + color: #dddddd; + font-size: 15px; } - table.cv-table th{ - padding: 6px 16px; - color: #969696; - text-align: left; - border-bottom: #555 1px solid; - border-bottom: #555 1px solid; - font-weight: normal; - background-color: #1e1e1e; - } - table.cv-table tr:nth-child(odd){ - background-color: #292929; - } - table.cv-table tr td:first-child{ - padding-left: 10px; - -webkit-border-top-left-radius: 10px; - -webkit-border-bottom-left-radius: 10px; - } - table.cv-table tr td:last-child{ - padding-right: 10px; - -webkit-border-top-right-radius: 10px; - -webkit-border-bottom-right-radius: 10px; - } - table.cv-table td{ - padding: 7px 16px; - } - - - - - -.not-responding{ +table.cv-table th { + padding: 6px 16px; + color: #969696; + text-align: left; + border-bottom: #555 1px solid; + border-bottom: #555 1px solid; + font-weight: normal; + background-color: #1e1e1e; } -.not-responding em{ - background-color: #3f3f3f; - color: white; - padding: 2px 10px; - display: inline-block; - border-radius: 5px; +table.cv-table tr:nth-child(odd) { + background-color: #292929; +} +table.cv-table tr td:first-child { + padding-left: 10px; + -webkit-border-top-left-radius: 10px; + -webkit-border-bottom-left-radius: 10px; +} +table.cv-table tr td:last-child { + padding-right: 10px; + -webkit-border-top-right-radius: 10px; + -webkit-border-bottom-right-radius: 10px; +} +table.cv-table td { + padding: 7px 16px; } -@font-face { - font-family: PlexMono; - src: url("media/IBMPlexMono-Text.otf") format("opentype"); +.not-responding { } - -@font-face { - font-family: PlexSans; - src: url("media/IBMPlexSans-Light.otf") format("opentype"); +.not-responding em { + background-color: #3f3f3f; + color: white; + padding: 2px 10px; + display: inline-block; + border-radius: 5px; } diff --git a/src/device.js b/src/device.js index a45d680..39b4d80 100644 --- a/src/device.js +++ b/src/device.js @@ -1,274 +1,259 @@ const { v4: uuid } = require('uuid'); -let osc = require("osc"); -let net = require("net"); -let udp = require('dgram'); -var _ = require('lodash/function'); +const osc = require('osc'); +const net = require('net'); +const udp = require('dgram'); +const { debounce } = require('lodash/function'); +const PLUGINS = require('./plugins.js'); +const VIEW = require('./view.js'); +const SAVESLOTS = require('./saveSlots.js'); -let PLUGINS = require("./plugins.js"); -let VIEW = require("./view.js"); -let SAVESLOTS = require("./saveSlots.js"); - - -var devices = {}; +const devices = {}; module.exports.all = devices; +registerDevice = function (newDevice) { + console.log(PLUGINS.all); -registerDevice = function(newDevice){ + if (PLUGINS.all[newDevice.type] == undefined) { + console.error(`Plugin for device ${newDevice.type} does not exist.`); + return true; + } - console.log(PLUGINS.all) + const initElements = document.getElementsByClassName('init'); + for (let i = 0; i < initElements.length; i++) { + initElements[i].style.display = 'none'; + } - if(PLUGINS.all[newDevice.type]==undefined){ - console.error("Plugin for device "+newDevice.type+" does not exist."); - return true; - } + // only register device if it hasn't already been added + if (newDevice.addresses.length > 0) { + for (let i in devices) { + if ( + devices[i].type == newDevice.type && + JSON.stringify(devices[i].addresses) == + JSON.stringify(newDevice.addresses) + ) { + // This device has already been added + infoUpdate(devices[i], 'status', 'ok'); + return false; + } + } + } - var initElements = document.getElementsByClassName('init'); - for(var i=0; i0){ - for(var i in devices){ - if(devices[i].type==newDevice.type && JSON.stringify(devices[i].addresses) == JSON.stringify(newDevice.addresses)){ - // This device has already been added - infoUpdate(devices[i], "status", "ok"); - return false; - } - } - } + const id = newDevice.id || uuid(); + devices[id] = { + id, + status: 'new', + type: newDevice.type, + displayName: newDevice.displayName, + defaultName: newDevice.defaultName, + port: newDevice.port, + addresses: newDevice.addresses, + data: {}, + pinIndex: false, + lastDrawn: 0, + lastHeartbeat: 0, + heartbeatInterval: PLUGINS.all[newDevice.type].heartbeatInterval, + draw: debounce( + function () { + VIEW.draw(this); + }, + 30, + { leading: true, trailing: true } + ), + }; - //console.log("Registered new "+newDevice.type) - - var id = newDevice.id || uuid(); - devices[id] = { - id: id, - status: "new", - type: newDevice.type, - displayName: newDevice.displayName, - defaultName: newDevice.defaultName, - port: newDevice.port, - addresses: newDevice.addresses, - data: {}, - pinIndex: false, - lastDrawn: 0, - lastHeartbeat: 0, - heartbeatInterval: PLUGINS.all[newDevice.type].heartbeatInterval, - draw: _.debounce(function(){ VIEW.draw(this); }, 30, { leading: true, trailing: true}) - } - - VIEW.addDeviceToList(devices[id]); - initDeviceConnection(id); - -} + VIEW.addDeviceToList(devices[id]); + initDeviceConnection(id); +}; module.exports.registerDevice = registerDevice; +initDeviceConnection = function (id) { + const device = devices[id]; -initDeviceConnection = function(id){ + infoUpdate(device, 'status', 'new'); + if (device.port == undefined || device.addresses.length == 0) { + return true; + } + try { + // mostly only useful for UDP + device.connection.close(); + } catch (err) {} - var device = devices[id]; + const { type } = devices[id]; + const plugins = PLUGINS.all; - infoUpdate(device, "status", "new"); + if (plugins[type].connectionType == 'osc') { + device.connection = new osc.TCPSocketPort({ + address: device.addresses[0], + port: device.port, + }); + device.connection.open(); + device.connection.on('error', (error) => { + // console.error(error) + device.connection.close(); + }); + device.connection.on('ready', () => { + plugins[type].ready(device); + if (Object.keys(devices).length == 1) { + VIEW.switchDevice(device.id); + } + }); + device.connection.on('message', (message) => { + // log("OSC IN", message.address); + plugins[type].data(device, message); + device.lastMessage = Date.now(); + }); + device.send = function (address, args) { + device.connection.send({ address: address, args: args }); + }; + device.plugin = plugins[type]; + } else if (plugins[type].connectionType == 'TCPsocket') { + device.connection = new net.Socket(); - if(device.port==undefined || device.addresses.length==0){ - return true; - } - try{ - // mostly only useful for UDP - device.connection.close(); - }catch(err){} - - const type = devices[id].type; - var plugins = PLUGINS.all; + device.connection.connect( + { port: device.port, host: device.addresses[0] }, + () => {} + ); - if(plugins[type].connectionType == "osc"){ - device.connection = new osc.TCPSocketPort({ - address: device.addresses[0], - port: device.port - }); - device.connection.open(); - device.connection.on("error", function (error) { - //console.error(error) - device.connection.close(); - }); - device.connection.on("ready", function () { - plugins[type].ready(device); - if(Object.keys(devices).length==1){ - VIEW.switchDevice(device.id); - } - }); - device.connection.on("message", function(message){ - //log("OSC IN", message.address); - plugins[type].data(device, message); - device.lastMessage = Date.now(); - }); - device.send = function(address, args){ - device.connection.send({address: address, args: args}); - } - device.plugin = plugins[type]; + device.connection.on('error', (error) => { + // console.error(error) + }); + device.connection.on('ready', () => { + plugins[type].ready(device); + if (Object.keys(devices).length == 1) { + VIEW.switchDevice(device.id); + } + }); + device.connection.on('data', (message) => { + // log("SOCK IN", message); + plugins[type].data(device, message); + device.lastMessage = Date.now(); + infoUpdate(device, 'status', 'ok'); + }); + device.send = function (data) { + // log("SOCK OUT", data); + device.connection.write(data); + }; + } else if (plugins[type].connectionType == 'UDPsocket') { + device.connection = udp.createSocket('udp4'); - }else if(plugins[type].connectionType == "TCPsocket"){ - device.connection = new net.Socket(); + device.connection.bind(() => { + plugins[type].ready(device); - device.connection.connect({port: device.port, host: device.addresses[0]}, function() { - - }); - - device.connection.on("error", function (error) { - //console.error(error) - }); - device.connection.on("ready", function () { - plugins[type].ready(device); - if(Object.keys(devices).length==1){ - VIEW.switchDevice(device.id); - } - }); - device.connection.on("data", function(message){ - //log("SOCK IN", message); - plugins[type].data(device, message); - device.lastMessage = Date.now(); - infoUpdate(device, "status", "ok"); - }); - device.send = function(data){ - //log("SOCK OUT", data); - device.connection.write(data); - } + device.connection.on('message', (msg, info) => { + plugins[type].data(device, msg); + infoUpdate(device, 'status', 'ok'); + }); + }); - }else if(plugins[type].connectionType == "UDPsocket"){ - - device.connection = udp.createSocket('udp4'); - - device.connection.bind(function(){ - - plugins[type].ready(device); - - device.connection.on('message',function(msg,info){ - plugins[type].data(device, msg); - infoUpdate(device, "status", "ok"); - }); - }); - - device.send = function(data){ - device.connection.send(data, device.port, device.addresses[0], function(err){ - //console.log(err); - }); - } - - - } - -} + device.send = function (data) { + device.connection.send(data, device.port, device.addresses[0], (err) => { + // console.log(err); + }); + }; + } +}; module.exports.initDeviceConnection = initDeviceConnection; +module.exports.deleteActive = function () { + const device = VIEW.getActiveDevice(); + const choice = confirm( + `Are you sure you want to delete ${device.type} device "${ + device.displayName || device.defaultName + }"?` + ); -module.exports.deleteActive = function(){ - var device = VIEW.getActiveDevice(); - var choice = confirm("Are you sure you want to delete "+device.type+" device \""+(device.displayName || device.defaultName)+"\"?"); + if (choice) { + VIEW.removeDeviceFromList(device); + delete devices[device.id]; + SAVESLOTS.deleteFromSlots(device); + SAVESLOTS.saveAll(); + SAVESLOTS.reloadActiveSlot(); + } +}; - if(choice){ - VIEW.removeDeviceFromList(device); - delete devices[device.id]; - SAVESLOTS.deleteFromSlots(device); - SAVESLOTS.saveAll(); - SAVESLOTS.reloadActiveSlot(); - } +module.exports.changeActiveType = function (newType) { + const device = VIEW.getActiveDevice(); + device.type = newType; -} + initDeviceConnection(device.id); + VIEW.draw(device); + // SAVESLOTS.saveAll(); +}; -module.exports.changeActiveType = function(newType){ - var device = VIEW.getActiveDevice(); - device.type = newType; +module.exports.changeActiveIP = function (newIP) { + const device = VIEW.getActiveDevice(); + device.addresses[0] = newIP; + initDeviceConnection(device.id); + VIEW.draw(device); + SAVESLOTS.saveAll(); +}; - initDeviceConnection(device.id); - VIEW.draw(device); - //SAVESLOTS.saveAll(); -} +module.exports.changeActivePort = function (newPort) { + const device = VIEW.getActiveDevice(); + device.port = newPort; -module.exports.changeActiveIP = function(newIP){ - var device = VIEW.getActiveDevice(); - device.addresses[0] = newIP; - initDeviceConnection(device.id); - VIEW.draw(device); - SAVESLOTS.saveAll(); -} + initDeviceConnection(device.id); + VIEW.draw(device); + SAVESLOTS.saveAll(); +}; -module.exports.changeActivePort = function(newPort){ - var device = VIEW.getActiveDevice(); - device.port = newPort; +module.exports.changeActiveName = function (newName) { + const device = VIEW.getActiveDevice(); + device.displayName = newName; + infoUpdate(device, 'displayName', newName); + VIEW.draw(device); + SAVESLOTS.saveAll(); +}; +module.exports.changeActivePinIndex = function (newPin) { + const device = VIEW.getActiveDevice(); + device.pinIndex = newPin; + VIEW.draw(device); + SAVESLOTS.saveAll(); +}; +module.exports.changePinIndex = function (device, newPin) { + device.pinIndex = newPin; + // SAVESLOTS.saveAll(); +}; +module.exports.refreshActive = function () { + const device = VIEW.getActiveDevice(); + if (device == undefined) { + return true; + } + initDeviceConnection(device.id); + VIEW.draw(device); +}; - initDeviceConnection(device.id); - VIEW.draw(device); - SAVESLOTS.saveAll(); -} - -module.exports.changeActiveName = function(newName){ - var device = VIEW.getActiveDevice(); - device.displayName = newName; - infoUpdate(device, "displayName", newName); - VIEW.draw(device); - SAVESLOTS.saveAll(); -} -module.exports.changeActivePinIndex = function(newPin){ - var device = VIEW.getActiveDevice(); - device.pinIndex = newPin; - VIEW.draw(device); - SAVESLOTS.saveAll(); -} -module.exports.changePinIndex = function(device, newPin){ - device.pinIndex = newPin; - //SAVESLOTS.saveAll(); -} -module.exports.refreshActive = function(){ - var device = VIEW.getActiveDevice(); - if(device==undefined){ - return true; - } - initDeviceConnection(device.id); - VIEW.draw(device); -} - - - - -infoUpdate = function(device, param, value){ - if(param=="addresses"){ - device.addresses = value.replace(/\s+/g, '').split(","); - }else{ - device[param] = value; - } - VIEW.addDeviceToList(device); -} +infoUpdate = function (device, param, value) { + if (param == 'addresses') { + device.addresses = value.replace(/\s+/g, '').split(','); + } else { + device[param] = value; + } + VIEW.addDeviceToList(device); +}; module.exports.infoUpdate = infoUpdate; - -setInterval(heartbeat, 100); -function heartbeat(){ - for(var i in devices){ - var device = devices[i]; - if(Date.now()>=device.lastHeartbeat+device.heartbeatInterval){ - - if(device.status=="broken"){ - initDeviceConnection(i); - }else if(Date.now()-device.lastMessage>10000){ - infoUpdate(device, "status", "broken"); - }else{ - if(device.port!=undefined && device.addresses.length>0){ - PLUGINS.all[device.type].heartbeat(device); - }else{ - //console.error("Invalid IP/Port on device "+device.name) - } - } - device.lastHeartbeat = Date.now(); - } - - } +function heartbeat() { + for (let i in devices) { + const device = devices[i]; + if (Date.now() >= device.lastHeartbeat + device.heartbeatInterval) { + if (device.status == 'broken') { + initDeviceConnection(i); + } else if (Date.now() - device.lastMessage > 10000) { + infoUpdate(device, 'status', 'broken'); + } else { + if (device.port != undefined && device.addresses.length > 0) { + PLUGINS.all[device.type].heartbeat(device); + } else { + // console.error("Invalid IP/Port on device "+device.name) + } + } + device.lastHeartbeat = Date.now(); + } + } } - - - - - - - +setInterval(heartbeat, 100); diff --git a/src/index.css b/src/index.css index 5670761..6b489bc 100644 --- a/src/index.css +++ b/src/index.css @@ -2,343 +2,317 @@ html { font-size: 1rem; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont; } -*, a, button { - cursor: default; - user-select: none; +*, +a, +button { + cursor: default; + user-select: none; } - - -body{ - color: #6e6c6f; - margin: 0px; - user-select: none; - overflow-x: hidden; +body { + color: #6e6c6f; + margin: 0px; + user-select: none; + overflow-x: hidden; } -a{ - text-decoration: none; +a { + text-decoration: none; } -.red{ - color: #eb6b5e; +.red { + color: #eb6b5e; } -.green{ - color: #61c650; +.green { + color: #61c650; } -.left{ - float: left; +.left { + float: left; } - -#main{ - box-sizing: border-box; - display: grid; - width: 100%; - height: 100vh; - grid-template-columns: 270px 1fr; +#main { + box-sizing: border-box; + display: grid; + width: 100%; + height: 100vh; + grid-template-columns: 270px 1fr; } -.col{ - border-right: rgba(0, 0, 0, 0.5) 1px solid; - height: 100vh !important; - overflow: hidden; - box-sizing: border-box; - position: relative; +.col { + border-right: rgba(0, 0, 0, 0.5) 1px solid; + height: 100vh !important; + overflow: hidden; + box-sizing: border-box; + position: relative; } /* FIRST COL */ -#device-list-col{ - background-color: transparent; - color: #707070; +#device-list-col { + background-color: transparent; + color: #707070; } -#view-buttons-bar{ - box-sizing: border-box; - text-align: right; - padding-left: 100px; - padding-right: 7px; - user-select: text; - -webkit-app-region: drag; - z-index: 1000; - /*border-bottom: black 1px solid;*/ - /*background: linear-gradient(#3f3f3f 0%, #343434 100%);*/ - /*background-color: #363636;*/ - /*background-color: rgba(0, 0, 0, 0.4);*/ +#view-buttons-bar { + box-sizing: border-box; + text-align: right; + padding-left: 100px; + padding-right: 7px; + user-select: text; + -webkit-app-region: drag; + z-index: 1000; + /*border-bottom: black 1px solid;*/ + /*background: linear-gradient(#3f3f3f 0%, #343434 100%);*/ + /*background-color: #363636;*/ + /*background-color: rgba(0, 0, 0, 0.4);*/ } -#view-buttons-bar button{ - background-color: rgba(255, 255, 255, 0.07); - width: 26px; - border-radius: 10px; - font-size: 0.8rem; +#view-buttons-bar button { + background-color: rgba(255, 255, 255, 0.07); + width: 26px; + border-radius: 10px; + font-size: 0.8rem; } -#view-buttons-bar button:hover{ - background-color: rgba(255, 255, 255, 0.25); +#view-buttons-bar button:hover { + background-color: rgba(255, 255, 255, 0.25); } - - - -#device-list{ - box-sizing: border-box; - width: 100%; - padding: 0px 10px; +#device-list { + box-sizing: border-box; + width: 100%; + padding: 0px 10px; } - #device-list div{ - pointer-events: none; - } - #device-list .device{ - box-sizing: border-box; - clear: both; - display: block; - width: 100%; - height: 40px; - padding: 10px 5px; - overflow: hidden; - border-radius: 5px; - } - #device-list .device.active-device{ - /*background-color: #0e5ccd;*/ - /*background-color: #c9961f;*/ - background-color: rgba(255, 255, 255, 0.2); - } - #device-list .status{ - float: left; - width: 25px; - font-size: 18px; - } - #device-list .type{ - float: left; - width: 30px; - color: #f6bd26; - } - #device-list .name{ - position: relative; - left: 0px; - color: white; - font-weight: 600; - - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } - #device-list h3.init{ - margin: 0px auto; - padding-top: 200px; - text-align: center; - font-weight: 300; - font-size: 16px; - width: 210px; - pointer-events: none; - } - - - - -#device-tools{ - position: absolute; - bottom: 210px; - left: 0px; - width: 100%; - height: 30px; - padding-right: 10px; - /*background: linear-gradient(#2f2f2f 0%, #2c2c2c 100%);*/ - background-color: rgba(0, 0, 0, 0.2); - text-align: center; - border-top: rgba(0, 0, 0, 0.3) 1px solid; - /*border-bottom: #3a3a3a 1px solid;*/ +#device-list div { + pointer-events: none; } -#device-tools select{ - text-align: center; +#device-list .device { + box-sizing: border-box; + clear: both; + display: block; + width: 100%; + height: 40px; + padding: 10px 5px; + overflow: hidden; + border-radius: 5px; +} +#device-list .device.active-device { + /*background-color: #0e5ccd;*/ + /*background-color: #c9961f;*/ + background-color: rgba(255, 255, 255, 0.2); +} +#device-list .status { + float: left; + width: 25px; + font-size: 18px; +} +#device-list .type { + float: left; + width: 30px; + color: #f6bd26; +} +#device-list .name { + position: relative; + left: 0px; + color: white; + font-weight: 600; + + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +#device-list h3.init { + margin: 0px auto; + padding-top: 200px; + text-align: center; + font-weight: 300; + font-size: 16px; + width: 210px; + pointer-events: none; } - - -#device-settings{ - position: absolute; - left: 0px; - bottom: 0px; - height: 200px; - padding: 5px; - color: white; - font-weight: 300; - width: 100%; - background-color: rgba(0, 0, 0, 0.2); +#device-tools { + position: absolute; + bottom: 210px; + left: 0px; + width: 100%; + height: 30px; + padding-right: 10px; + /*background: linear-gradient(#2f2f2f 0%, #2c2c2c 100%);*/ + background-color: rgba(0, 0, 0, 0.2); + text-align: center; + border-top: rgba(0, 0, 0, 0.3) 1px solid; + /*border-bottom: #3a3a3a 1px solid;*/ +} +#device-tools select { + text-align: center; } - #device-settings th{ - text-align: right; - padding-right: 3px; - color: white; - font-weight: normal; - } - #device-settings td{ - padding: 6px; - } - #device-settings-table{ - display: none; - } - #device-settings h3{ - padding-top: 20px; - text-align: center; - font-weight: 300; - } - #device-settings #device-settings-name, - #device-settings #device-settings-ip, - #device-settings #device-settings-plugin-dropdown{ - width: 170px; - } - #device-settings #device-settings-port{ - width: 70px; - } - +#device-settings { + position: absolute; + left: 0px; + bottom: 0px; + height: 200px; + padding: 5px; + color: white; + font-weight: 300; + width: 100%; + background-color: rgba(0, 0, 0, 0.2); +} +#device-settings th { + text-align: right; + padding-right: 3px; + color: white; + font-weight: normal; +} +#device-settings td { + padding: 6px; +} +#device-settings-table { + display: none; +} +#device-settings h3 { + padding-top: 20px; + text-align: center; + font-weight: 300; +} +#device-settings #device-settings-name, +#device-settings #device-settings-ip, +#device-settings #device-settings-plugin-dropdown { + width: 170px; +} +#device-settings #device-settings-port { + width: 70px; +} /* SECOND COL */ -#all-devices{ - display: grid; - grid-template-columns: repeat(4, 1fr); - background-color: rgba(0, 0, 0, 0.3); +#all-devices { + display: grid; + grid-template-columns: repeat(4, 1fr); + background-color: rgba(0, 0, 0, 0.3); } -.device-pin{ - position:absolute; - right: 15px; - top: 8px; - height: 20px; +.device-pin { + position: absolute; + right: 15px; + top: 8px; + height: 20px; } -.device-wrapper{ - box-sizing: border-box; - border-top: rgba(0, 0, 0, 0) 2px solid; - border-bottom: rgba(0, 0, 0, 0) 2px solid; +.device-wrapper { + box-sizing: border-box; + border-top: rgba(0, 0, 0, 0) 2px solid; + border-bottom: rgba(0, 0, 0, 0) 2px solid; } -.draw-area{ - height: 100%; - overflow-y: scroll; - width: 100%; - height: 100%; - border: 0; - +.draw-area { + height: 100%; + overflow-y: scroll; + width: 100%; + height: 100%; + border: 0; } -.active-device-outline{ - outline: #fdea08 2px solid; - border-top: #fdea08 2px solid; - border-bottom: #fdea08 2px solid; +.active-device-outline { + outline: #fdea08 2px solid; + border-top: #fdea08 2px solid; + border-bottom: #fdea08 2px solid; } - - - - - -input{ - display: block; - box-sizing:content-box; - background-color: rgba(0, 0, 0, 0.2); - height: 28px; - padding: 2px 6px; - margin: 0px; - border: rgba(255, 255, 255, 0.1) 1px solid; - border-radius: 4px; - color: #fff; - font-size: 16px; - font-weight: 500; +input { + display: block; + box-sizing: content-box; + background-color: rgba(0, 0, 0, 0.2); + height: 28px; + padding: 2px 6px; + margin: 0px; + border: rgba(255, 255, 255, 0.1) 1px solid; + border-radius: 4px; + color: #fff; + font-size: 16px; + font-weight: 500; } -select{ - display: block; - box-sizing:content-box; - background-color: rgba(255, 255, 255, 0.15); - height: 28px; - padding: 2px 6px; - margin: 0px; - border: rgba(255, 255, 255, 0.1) 1px solid; - border-radius: 4px; - color: #fff; - font-size: 16px; - font-weight: 500; +select { + display: block; + box-sizing: content-box; + background-color: rgba(255, 255, 255, 0.15); + height: 28px; + padding: 2px 6px; + margin: 0px; + border: rgba(255, 255, 255, 0.1) 1px solid; + border-radius: 4px; + color: #fff; + font-size: 16px; + font-weight: 500; } -input:focus, select:focus{ - outline: #fdea08 2px solid; - color: white; +input:focus, +select:focus { + outline: #fdea08 2px solid; + color: white; } -input[type='checkbox']{ - position: relative; - height: 14px; - width: 14px; - padding: 2px; - -webkit-appearance: none; +input[type='checkbox'] { + position: relative; + height: 14px; + width: 14px; + padding: 2px; + -webkit-appearance: none; } -input[type='checkbox']:checked{ - background-color: #616064; +input[type='checkbox']:checked { + background-color: #616064; } input[type='checkbox']:checked:after { - content: '\2713'; - font-size: 18px; - position: absolute; - top: -1px; - left: 1px; - color: white; + content: '\2713'; + font-size: 18px; + position: absolute; + top: -1px; + left: 1px; + color: white; } input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } -button, select.button{ - box-sizing:content-box; - width: 40px; - height: 25px; - margin-top: 7px; - margin-bottom: 7px; - margin-left: 4px; - border: none; - outline: none; - padding: 0px; +button, +select.button { + box-sizing: content-box; + width: 40px; + height: 25px; + margin-top: 7px; + margin-bottom: 7px; + margin-left: 4px; + border: none; + outline: none; + padding: 0px; - color: white; - background: rgba(255, 255, 255, 0.15); - border-radius: 4px; - font-size: 1rem; - user-select: none; + color: white; + background: rgba(255, 255, 255, 0.15); + border-radius: 4px; + font-size: 1rem; + user-select: none; } - button:hover{ - background-color: rgba(255, 255, 255, 0.2); - } - button:focus{ - outline: none; - } - button.active{ - background-color: rgba(255, 255, 255, 0.3); - color: white; - } - button:disabled{ - background: rgba(255, 255, 255, 0.03); - } - button img{ - height: 18px; - } - -select.button:focus{ - outline: none; +button:hover { + background-color: rgba(255, 255, 255, 0.2); +} +button:focus { + outline: none; +} +button.active { + background-color: rgba(255, 255, 255, 0.3); + color: white; +} +button:disabled { + background: rgba(255, 255, 255, 0.03); +} +button img { + height: 18px; } - - - - - - - - - +select.button:focus { + outline: none; +} @font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; - src: local('img/Material Icons'), - local('img/MaterialIcons-Regular'), + src: local('img/Material Icons'), local('img/MaterialIcons-Regular'), url(img/MaterialIcons-Regular.ttf) format('truetype'); } .material-icons { font-family: 'Material Icons'; font-weight: normal; font-style: normal; - font-size: 24px; /* Preferred icon size */ + font-size: 24px; /* Preferred icon size */ display: inline-block; line-height: 1; text-transform: none; diff --git a/src/index.js b/src/index.js index 47a78df..b5656ad 100644 --- a/src/index.js +++ b/src/index.js @@ -1,23 +1,17 @@ -document.onclick = function(e){ - window.closePopovers(); -} +document.onclick = function (e) { + window.closePopovers(); +}; window.init(); +document.getElementById('search-button').onclick = function (e) { + window.searchAll(); +}; +document.getElementById('add-device-button').onclick = function (e) { + // e.stopPropagation(); + // document.getElementById("add-device-popover").style.display = "block"; +}; -document.getElementById("search-button").onclick = function(e){ - window.searchAll(); -} -document.getElementById("add-device-button").onclick = function(e){ - //e.stopPropagation(); - //document.getElementById("add-device-popover").style.display = "block"; -} - - - -window.closePopovers = function(){ - //document.getElementById("add-device-popover").style.display = "none"; -} - - - +window.closePopovers = function () { + // document.getElementById("add-device-popover").style.display = "none"; +}; diff --git a/src/plugins.js b/src/plugins.js index 425e7cf..662e7c8 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -1,38 +1,46 @@ -let fs = require('fs'); -let DEVICE = require("./device.js"); -let VIEW = require("./view.js"); +const fs = require('fs'); +const ejs = require('ejs'); +const DEVICE = require('./device.js'); +const VIEW = require('./view.js'); - -var allPlugins = {}; +const allPlugins = {}; module.exports.all = allPlugins; -module.exports.init = function(callback){ +module.exports.init = function (callback) { + console.log(`Loading plugin files... ${__dirname}/../plugins`); - console.log("Loading plugin files... "+__dirname+"/../plugins") + fs.readdir(`${__dirname}/../plugins`, (err, files) => { + for (let i in files) { + const plugin = files[i]; - fs.readdir(__dirname+"/../plugins", function(err, files){ - for(var i in files){ - var plugin = files[i]; + if (plugin[0] != '.') { + console.log(`${i} ${plugin}`); + allPlugins[ + plugin + ] = require(`${__dirname}/../plugins/${plugin}/${plugin}.js`); + allPlugins[plugin].deviceInfoUpdate = function (device, param, value) { + DEVICE.infoUpdate(device, param, value); + }; + allPlugins[plugin].draw = function (device) { + VIEW.draw(device); + }; - if(plugin[0]!="."){ - console.log(i+" "+plugin); - allPlugins[plugin] = require(__dirname+"/../plugins/"+plugin+"/"+plugin+".js"); + allPlugins[plugin].template = ejs.compile( + fs.readFileSync( + `${__dirname}/../plugins/${plugin}/${plugin}.html`, + 'utf8' + ) + ); - allPlugins[plugin].deviceInfoUpdate = function(device, param, value){ - DEVICE.infoUpdate(device, param, value) - } - allPlugins[plugin].draw = function(device){ - VIEW.draw(device); - } - - allPlugins[plugin].template = ejs.compile(fs.readFileSync(__dirname+"/../plugins/"+plugin+"/"+plugin+".html", 'utf8')); - - if(allPlugins[plugin].heartbeatInterval==undefined || allPlugins[plugin].heartbeatInterval<50){ - allPlugins[plugin].heartbeatInterval = 5000; - } - } - } - callback(); - }); -} \ No newline at end of file + if ( + allPlugins[plugin].heartbeatInterval == undefined || + allPlugins[plugin].heartbeatInterval < 50 + ) { + allPlugins[plugin].heartbeatInterval = 5000; + } + } + } + callback(); + }); +}; diff --git a/src/saveSlots.js b/src/saveSlots.js index 32b0620..2037652 100644 --- a/src/saveSlots.js +++ b/src/saveSlots.js @@ -1,118 +1,115 @@ -let VIEW = require("./view.js"); -let DEVICE = require("./device.js"); +const VIEW = require('./view.js'); +const DEVICE = require('./device.js'); +let activeSlot = false; +let savedSlots = [[], [], [], []]; +let savedDevices = []; -var activeSlot = false; -var savedSlots = [[], [], [], []]; -var savedDevices = []; - -var storedSlots = localStorage.getItem('savedSlots');; -if(storedSlots){ - savedSlots = JSON.parse(storedSlots); +const storedSlots = localStorage.getItem('savedSlots'); +if (storedSlots) { + savedSlots = JSON.parse(storedSlots); } -var storedDevices = localStorage.getItem('savedDevices');; -if(storedDevices){ - savedDevices = JSON.parse(storedDevices); +const storedDevices = localStorage.getItem('savedDevices'); +if (storedDevices) { + savedDevices = JSON.parse(storedDevices); } -loadSlot = function(slotIndex){ - - VIEW.toggleSlotButtons(slotIndex); - activeSlot = slotIndex; +loadSlot = function (slotIndex) { + VIEW.toggleSlotButtons(slotIndex); + activeSlot = slotIndex; - for(var d in DEVICE.all){ - DEVICE.changePinIndex(DEVICE.all[d], false); - } - VIEW.resetPinned(); + for (var d in DEVICE.all) { + DEVICE.changePinIndex(DEVICE.all[d], false); + } + VIEW.resetPinned(); - for(var d in savedSlots[slotIndex]){ - var savedDevice = savedSlots[slotIndex][d]; - for(var d in DEVICE.all){ - var device = DEVICE.all[d]; - //if(device.addresses[0] == savedDevice.addresses[0] && device.type == savedDevice.type){ - if(device.id == savedDevice.id){ - VIEW.pinDevice(device); - VIEW.switchDevice(device.id) - }else if(device.addresses[0] == savedDevice.addresses[0] && device.type == savedDevice.type && savedDevice.addresses[0]!=undefined ){ - VIEW.pinDevice(device); - VIEW.switchDevice(device.id) - } - } - } -} + for (var d in savedSlots[slotIndex]) { + const savedDevice = savedSlots[slotIndex][d]; + for (var d in DEVICE.all) { + const device = DEVICE.all[d]; + // if(device.addresses[0] == savedDevice.addresses[0] && device.type == savedDevice.type){ + if (device.id == savedDevice.id) { + VIEW.pinDevice(device); + VIEW.switchDevice(device.id); + } else if ( + device.addresses[0] == savedDevice.addresses[0] && + device.type == savedDevice.type && + savedDevice.addresses[0] != undefined + ) { + VIEW.pinDevice(device); + VIEW.switchDevice(device.id); + } + } + } +}; module.exports.loadSlot = loadSlot; -module.exports.loadDevices = function(){ - console.log("Loading "+savedDevices.length+" saved devices...") - console.log(savedDevices) +module.exports.loadDevices = function () { + console.log(`Loading ${savedDevices.length} saved devices...`); + console.log(savedDevices); - for(var i=0; i2046){ - alert("Unable to search for TCP devices - subnet too large!\n\nCue View requires subnet 255.255.248.0 (/21) or smaller.") - TCPFlag = false; - } - - console.log(PLUGINS) - - for(var p in PLUGINS.all){ - var plugin = PLUGINS.all[p]; - console.log(p) - try{ - switch(plugin.searchOptions.type){ - case "TCPport": - if(TCPFlag){ - newSearchTCP(p, plugin); - } - break; - case "Bonjour": - newSearchBonjour(p, plugin) - break; - case "UDPsocket": - newSearchUDP(p, plugin) - break; - } - }catch(err){ - console.error("Unable to search for plugin "+p) - } - } - - //searchBonjour(); - //searchTCP(); - //searchUDP(); - - setTimeout(function(){ - searching = false; - document.getElementById("search-button").style.opacity = ""; - - for(var i=0; i 2046) { + alert( + 'Unable to search for TCP devices - subnet too large!\n\nCue View requires subnet 255.255.248.0 (/21) or smaller.' + ); + TCPFlag = false; + } + + console.log(PLUGINS); + + for (let p in PLUGINS.all) { + const plugin = PLUGINS.all[p]; + console.log(p); + try { + switch (plugin.searchOptions.type) { + case 'TCPport': + if (TCPFlag) { + newSearchTCP(p, plugin); + } + break; + case 'Bonjour': + newSearchBonjour(p, plugin); + break; + case 'UDPsocket': + newSearchUDP(p, plugin); + break; + } + } catch (err) { + console.error(`Unable to search for plugin ${p}`); + } + } + + // searchBonjour(); + // searchTCP(); + // searchUDP(); + + setTimeout(() => { + searching = false; + document.getElementById('search-button').style.opacity = ''; + + for (let i = 0; i < searchSockets.length; i++) { + try { + searchSockets[i].close(); + } catch (err) {} + } + + ipcRenderer.send('enableSearchAll', ''); + }, 5000); +}; module.exports.searchAll = searchAll; +// ____ _ +// | _ \ (_) +// | |_) | ___ _ __ _ ___ _ _ _ __ +// | _ < / _ \| '_ \| |/ _ \| | | | '__| +// | |_) | (_) | | | | | (_) | |_| | | +// |____/ \___/|_| |_| |\___/ \__,_|_| +// _/ | +// |__/ +newSearchBonjour = function (pluginType, plugin) { + bonjour.find({ type: plugin.searchOptions.bonjourName }, (e) => { + console.log(pluginType); + const validAddresses = []; + for (let i in e.addresses) { + if (e.addresses[i].indexOf(':') == -1) { + validAddresses.push(e.addresses[i]); + } + } - // ____ _ - // | _ \ (_) - // | |_) | ___ _ __ _ ___ _ _ _ __ - // | _ < / _ \| '_ \| |/ _ \| | | | '__| - // | |_) | (_) | | | | | (_) | |_| | | - // |____/ \___/|_| |_| |\___/ \__,_|_| - // _/ | - // |__/ - -newSearchBonjour = function(pluginType, plugin){ - bonjour.find({type: plugin.searchOptions.bonjourName}, function(e){ - console.log(pluginType) - - var validAddresses = []; - for(var i in e.addresses){ - if(e.addresses[i].indexOf(":")==-1){ - validAddresses.push(e.addresses[i]) - } - } - - DEVICE.registerDevice({ - type: pluginType, - defaultName: e.name, - port: e.port, - addresses: validAddresses - }) - }); -} - + DEVICE.registerDevice({ + type: pluginType, + defaultName: e.name, + port: e.port, + addresses: validAddresses, + }); + }); +}; // searchBonjour = function(){ // bonjour.find({type: "qlab"}, function(e){ @@ -129,108 +148,79 @@ newSearchBonjour = function(pluginType, plugin){ // }) // }); - // } +// _______ _____ _____ +// |__ __/ ____| __ \ +// | | | | | |__) | +// | | | | | ___/ +// | | | |____| | +// |_| \_____|_| +newSearchTCP = function (pluginType, plugin) { + for (let i = 0; i < allServers.length; i++) { + TCPtest(allServers[i], pluginType, plugin); + } +}; - // _______ _____ _____ - // |__ __/ ____| __ \ - // | | | | | |__) | - // | | | | | ___/ - // | | | |____| | - // |_| \_____|_| - +TCPtest = function (ip, pluginType, plugin) { + const client = net.createConnection(plugin.searchOptions.testPort, ip, () => { + client.write(plugin.searchOptions.searchBuffer); + // DEVICE.registerDevice({ + // type: pluginType, + // defaultName: plugin.defaultName, + // port: plugin.defaultPort, + // addresses: [ip] + // }) + }); + client.on('data', (data) => { + if (plugin.searchOptions.validateResponse(data)) { + DEVICE.registerDevice({ + type: pluginType, + defaultName: plugin.defaultName, + port: plugin.defaultPort, + addresses: [ip], + }); + } + client.end(); + }); + client.on('error', (err) => { + // no device here + }); +}; +findOnlineDevices = function () { + const allInterfaces = os.networkInterfaces(); + const validInterfaces = []; + for (let i in allInterfaces) { + for (let j = 0; j < allInterfaces[i].length; j++) { + const iface = allInterfaces[i][j]; -newSearchTCP = function(pluginType, plugin){ - for(var i=0; i { - if(plugin.searchOptions.validateResponse(data)){ - DEVICE.registerDevice({ - type: pluginType, - defaultName: plugin.defaultName, - port: plugin.defaultPort, - addresses: [ip] - }) - } - client.end(); - }); - client.on("error", function(err){ - //no device here - }); -} - - - -// from local-devices library -function getServers () { - var interfaces = os.networkInterfaces() - var result = [] - - for (var key in interfaces) { - var addresses = interfaces[key] - for (var i = addresses.length; i--;) { - var address = addresses[i] - if (address.family === 'IPv4' && !address.internal) { - var subnet = ip.subnet(address.address, address.netmask) - var current = ip.toLong(subnet.firstAddress) - var last = ip.toLong(subnet.lastAddress) - 1 - while (current++ < last) result.push(ip.fromLong(current)) + if ( + iface.family == 'IPv4' && + iface.internal == false && + iface.address.split('.')[0] != '169' + ) { + validInterfaces.push(iface); } } } - return result; -} - - - -findOnlineDevices = function(){ - var allInterfaces = require('os').networkInterfaces(); - var validInterfaces = []; - for(var i in allInterfaces){ - for(var j=0; j { - //console.log(err) - }); - setTimeout(function(){ - searchSockets[i].send(plugin.searchOptions.searchBuffer, plugin.searchOptions.devicePort, '255.255.255.255', (err) => { - //console.log(err) - }); - }, 100); - setTimeout(function(){ - searchSockets[i].send(plugin.searchOptions.searchBuffer, plugin.searchOptions.devicePort, '255.255.255.255', (err) => { - //console.log(err) - }); - }, 400); - - searchSockets[i].on('message',function(msg,info){ - if(plugin.searchOptions.validateResponse(msg, info)){ - DEVICE.registerDevice({ - type: pluginType, - defaultName: plugin.defaultName, - port: plugin.defaultPort, - addresses: [info.address] - }) - } - }); - - }); - searchSockets[i].on('listening', function(){ - searchSockets[i].setBroadcast(true); - }); -} +newSearchUDP = function (pluginType, plugin) { + const i = searchSockets.push(dgram.createSocket('udp4')) - 1; + searchSockets[i].bind(plugin.searchOptions.listenPort, () => { + searchSockets[i].send( + plugin.searchOptions.searchBuffer, + plugin.searchOptions.devicePort, + '255.255.255.255', + (err) => { + // console.log(err) + } + ); + setTimeout(() => { + searchSockets[i].send( + plugin.searchOptions.searchBuffer, + plugin.searchOptions.devicePort, + '255.255.255.255', + (err) => { + // console.log(err) + } + ); + }, 100); + setTimeout(() => { + searchSockets[i].send( + plugin.searchOptions.searchBuffer, + plugin.searchOptions.devicePort, + '255.255.255.255', + (err) => { + // console.log(err) + } + ); + }, 400); + searchSockets[i].on('message', (msg, info) => { + if (plugin.searchOptions.validateResponse(msg, info)) { + DEVICE.registerDevice({ + type: pluginType, + defaultName: plugin.defaultName, + port: plugin.defaultPort, + addresses: [info.address], + }); + } + }); + }); + searchSockets[i].on('listening', () => { + searchSockets[i].setBroadcast(true); + }); +}; // searchUDP = function(){ @@ -362,7 +360,6 @@ newSearchUDP = function(pluginType, plugin){ // dgramPJLink.setBroadcast(true); // }); - // dgramXAir = dgram.createSocket('udp4'); // dgramXAir.bind(function(){ // dgramXAir.send(xAirMessage, 10024, '255.255.255.255', (err) => { @@ -389,11 +386,5 @@ newSearchUDP = function(pluginType, plugin){ // dgramXAir.on('listening', function(){ // dgramXAir.setBroadcast(true); // }); - // } - - - - - diff --git a/src/view.js b/src/view.js index e8790e9..77b8662 100644 --- a/src/view.js +++ b/src/view.js @@ -1,293 +1,299 @@ const { ipcRenderer } = require('electron'); -let DEVICE = require("./device.js"); -let PLUGINS = require("./plugins.js"); -var _ = require('lodash/function'); +const DEVICE = require('./device.js'); +const PLUGINS = require('./plugins.js'); +// const _ = require('lodash/function'); -var pinnedDevices = []; +const pinnedDevices = []; module.exports.pinnedDevices = pinnedDevices; let activeDevice = false; +module.exports.init = function () { + populatePluginLists(); +}; +drawDeviceInterface = function (id) { + // console.log("DRAW") -module.exports.init = function(){ - populatePluginLists(); -} + const $deviceDrawArea = document.getElementById(`device-${id}-draw-area`); + const $devicePinned = document.getElementById(`device-${id}-pinned`); + if ($deviceDrawArea == null) { + return true; + } + d = DEVICE.all[id]; -drawDeviceInterface = function(id){ + let str = ''; + if (d.status == 'ok') { + str += + ""; + } - // console.log("DRAW") + // scrollbar styles are inline to prevent the styles flickering in + str += ''; + str += ""; + str += ''; - var $deviceDrawArea = document.getElementById("device-"+id+"-draw-area"); - var $devicePinned = document.getElementById("device-"+id+"-pinned"); + if (d.status == 'ok') { + try { + str += PLUGINS.all[d.type].template({ + data: d.data, + listName: d.displayName || d.defaultName, + }); + } catch (err) { + console.log(err); + str += '

Plugin Template Error

'; + } + } else { + str += '

' + (d.displayName || d.defaultName) + '

'; + str += "
"; + str += + '

' + + d.type + + ' is not responding to requests for data.

'; + str += '

IP ' + d.addresses[0] + '

'; + str += '

Port ' + d.port + '

'; + } - if($deviceDrawArea==null){ - return true; - } + str += ''; - d = DEVICE.all[id]; + $deviceDrawArea.setAttribute('class', `${d.type} draw-area`); + $deviceDrawArea.contentWindow.document.open(); + $deviceDrawArea.contentWindow.document.write(str); - var str = ""; - if(d.status=="ok"){ - str+=""; - } - + if (d.pinIndex) { + $devicePinned.style.display = 'block'; + } else { + $devicePinned.style.display = 'none'; + } +}; - //scrollbar styles are inline to prevent the styles flickering in - str+=""; - str+=""; - str+=""; +module.exports.draw = function (device) { + if (device == undefined) { + return true; + } + drawDeviceInterface(device.id); +}; - if(d.status=="ok"){ - try{ - str += PLUGINS.all[d.type].template({data: d.data, listName: d.displayName || d.defaultName}); - }catch(err){ - console.log(err) - str += "

Plugin Template Error

"; - } - }else{ - str+="

"+(d.displayName || d.defaultName)+"

"; - str+="
"; - str+="

"+d.type+" is not responding to requests for data.

"; - str+="

IP "+d.addresses[0]+"

"; - str+="

Port "+d.port+"

"; - } - - str+=""; +module.exports.addDeviceToList = function (device) { + var d = device; + var addressStr = d.addresses[0] || ''; + for (var i = 1; i < d.addresses.length; i++) { + addressStr += ', ' + d.addresses[i]; + } + var html = ''; + if (d.status == 'ok') { + html += "
done
"; + } else if (d.status == 'refresh') { + html += "
refresh
"; + } else { + html += "
clear
"; + } + html += + "
"; + html += "
" + (d.displayName || d.defaultName) + '
'; - - $deviceDrawArea.setAttribute("class", d.type+" draw-area"); - $deviceDrawArea.contentWindow.document.open(); - $deviceDrawArea.contentWindow.document.write(str); + let elem = document.getElementById(d.id); + if (elem == null) { + document + .getElementById('device-list') + .insertAdjacentHTML( + 'beforeend', + "" + html + '' + ); + } else { + elem.innerHTML = html; + } +}; +module.exports.removeDeviceFromList = function (device) { + var d = device; + document.getElementById(device.id).remove(); +}; +switchDevice = function (id) { + if (activeDevice && activeDevice.pinIndex == false) { + document.getElementById('device-' + activeDevice.id).remove(); + activeDevice = false; + } + activeDevice = DEVICE.all[id]; - if(d.pinIndex){ - $devicePinned.style.display = "block"; - }else{ - $devicePinned.style.display = "none"; - } -} + var cols = 1; + if (pinnedDevices.length > 0) { + cols += pinnedDevices.length; + } + if (pinnedDevices.indexOf(activeDevice) >= 0 || id == undefined) { + cols--; + } -module.exports.draw = function(device){ - if(device==undefined){ - return true; - } - drawDeviceInterface(device.id) -} + document.getElementById('all-devices').style.gridTemplateColumns = + 'repeat(' + cols + ', 1fr)'; + if (id == undefined) { + // document.getElementById('refresh-device-button').style.opacity = 0.2; + document.getElementById('refresh-device-button').disabled = true; + document.getElementById('device-settings-table').style.display = 'none'; + return true; + } else { + document.getElementById('refresh-device-button').disabled = false; + // document.getElementById('refresh-device-button').style.opacity = 1; + } + var i = DEVICE.all[id].id; + var $deviceWrapper = document.getElementById('device-' + i); + if (!$deviceWrapper) { + var html = `
`; + document + .getElementById('all-devices') + .insertAdjacentHTML('afterbegin', html); -module.exports.addDeviceToList = function(device){ - var d = device; - var addressStr = d.addresses[0] || ""; - for(var i=1; i
"; - html+="
"+(d.displayName || d.defaultName)+"
"; + $deviceWrapper = document.getElementById(`device-${i}`); + } - let elem = document.getElementById(d.id); - if(elem==null){ - document.getElementById("device-list").insertAdjacentHTML("beforeend", ""+html+""); - }else{ - elem.innerHTML = html; - } -} -module.exports.removeDeviceFromList = function(device){ - var d = device; - document.getElementById(device.id).remove(); -} + switchClass(document.getElementById(id), 'active-device'); + drawDeviceInterface(id); + switchClass(document.getElementById(`device-${id}`), 'active-device-outline'); + document.getElementById('device-settings-table').style.display = 'block'; + document.getElementById('device-settings-plugin-dropdown').value = + activeDevice.type; + document.getElementById('device-settings-name').value = + activeDevice.displayName || activeDevice.defaultName || ''; + document.getElementById('device-settings-ip').value = + activeDevice.addresses[0] || ''; + document.getElementById('device-settings-port').value = + activeDevice.port || ''; + document.getElementById('device-settings-pin').checked = + activeDevice.pinIndex; - -switchDevice = function(id){ - - if(activeDevice && activeDevice.pinIndex==false){ - document.getElementById("device-"+activeDevice.id).remove(); - activeDevice = false; - } - activeDevice = DEVICE.all[id]; - - - var cols = 1; - if(pinnedDevices.length>0){ - cols+=pinnedDevices.length; - } - if(pinnedDevices.indexOf(activeDevice)>=0 || id==undefined){ - cols--; - } - - document.getElementById("all-devices").style.gridTemplateColumns = "repeat("+(cols)+", 1fr)"; - - if(id==undefined){ - //document.getElementById('refresh-device-button').style.opacity = 0.2; - document.getElementById('refresh-device-button').disabled = true; - document.getElementById('device-settings-table').style.display = "none"; - return true; - }else{ - document.getElementById('refresh-device-button').disabled = false; - //document.getElementById('refresh-device-button').style.opacity = 1; - } - - - var i = DEVICE.all[id].id; - - var $deviceWrapper = document.getElementById("device-"+i); - if(!$deviceWrapper){ - var html = '
' - +'' - +'' - +'
'; - document.getElementById("all-devices").insertAdjacentHTML("afterbegin", html); - - $deviceWrapper = document.getElementById("device-"+i); - } - - switchClass(document.getElementById(id), "active-device"); - drawDeviceInterface(id); - switchClass(document.getElementById("device-"+id), "active-device-outline"); - - - - document.getElementById('device-settings-table').style.display = "block"; - document.getElementById('device-settings-plugin-dropdown').value=activeDevice.type; - document.getElementById("device-settings-name").value = activeDevice.displayName || activeDevice.defaultName || ""; - document.getElementById("device-settings-ip").value = activeDevice.addresses[0] || ""; - document.getElementById("device-settings-port").value = activeDevice.port || ""; - document.getElementById("device-settings-pin").checked = activeDevice.pinIndex; - - - ipcRenderer.send("enableDeviceDropdown", ""); - ipcRenderer.send("setDevicePin", !DEVICE.all[id].pinIndex==false); - -} + ipcRenderer.send('enableDeviceDropdown', ''); + ipcRenderer.send('setDevicePin', !DEVICE.all[id].pinIndex == false); +}; module.exports.switchDevice = switchDevice; +module.exports.getActiveDevice = function () { + return activeDevice; +}; -module.exports.getActiveDevice = function(){ - return activeDevice; -} +module.exports.pinActiveDevice = function () { + if (activeDevice == undefined) { + return true; + } + if (pinnedDevices.indexOf(DEVICE.all[activeDevice.id]) == -1) { + pinnedDevices.push(DEVICE.all[activeDevice.id]); + } + DEVICE.changeActivePinIndex(true); +}; -module.exports.pinActiveDevice = function(){ - if(activeDevice==undefined){ - return true; - } - if(pinnedDevices.indexOf(DEVICE.all[activeDevice.id])==-1){ - pinnedDevices.push(DEVICE.all[activeDevice.id]); - } - DEVICE.changeActivePinIndex(true); -} +module.exports.unpinActiveDevice = function () { + if (activeDevice == undefined) { + return true; + } + pinnedDevices.splice(pinnedDevices.indexOf(DEVICE.all[activeDevice.id]), 1); + DEVICE.changeActivePinIndex(false); +}; -module.exports.unpinActiveDevice = function(){ - if(activeDevice==undefined){ - return true; - } - pinnedDevices.splice(pinnedDevices.indexOf(DEVICE.all[activeDevice.id]), 1); - DEVICE.changeActivePinIndex(false); -} +module.exports.pinDevice = function (device) { + pinnedDevices.push(device); + DEVICE.changePinIndex(device, true); +}; +module.exports.unpinDevice = function (device) { + pinnedDevices.push(device); + DEVICE.changePinIndex(device, false); +}; -module.exports.pinDevice = function(device){ - pinnedDevices.push(device) - DEVICE.changePinIndex(device, true); -} -module.exports.unpinDevice = function(device){ - pinnedDevices.push(device) - DEVICE.changePinIndex(device, false); -} +module.exports.resetPinned = function () { + pinnedDevices.length = 0; + activeDevice = false; + // switchDevice(); + try { + document + .querySelector('#device-list .active-device') + .classList.remove('active-device'); + } catch (err) {} + document.getElementById('all-devices').innerHTML = ''; +}; -module.exports.resetPinned = function(){ - pinnedDevices.length = 0; - activeDevice = false; - //switchDevice(); - try{ - document.querySelector("#device-list .active-device").classList.remove("active-device"); - }catch(err){} - document.getElementById("all-devices").innerHTML = ""; -} +module.exports.getPinnedDevices = function () { + return pinnedDevices; +}; -module.exports.getPinnedDevices = function(){ - return pinnedDevices; -} +module.exports.toggleSlotButtons = function (slotIndex) { + if (slotIndex == 1) { + document.getElementById('save-slot-1').classList.add('active'); + document.getElementById('save-slot-2').classList.remove('active'); + document.getElementById('save-slot-3').classList.remove('active'); + } else if (slotIndex == 2) { + document.getElementById('save-slot-1').classList.remove('active'); + document.getElementById('save-slot-2').classList.add('active'); + document.getElementById('save-slot-3').classList.remove('active'); + } else if (slotIndex == 3) { + document.getElementById('save-slot-1').classList.remove('active'); + document.getElementById('save-slot-2').classList.remove('active'); + document.getElementById('save-slot-3').classList.add('active'); + } +}; +module.exports.selectPreviousDevice = function () { + if (activeDevice == undefined) { + return true; + } + var keys = Object.keys(DEVICE.all); + var prevIndex = Math.max(0, keys.indexOf(activeDevice.id) - 1); + switchDevice(keys[prevIndex]); +}; +module.exports.selectNextDevice = function () { + if (activeDevice == undefined) { + return true; + } + var keys = Object.keys(DEVICE.all); + var prevIndex = Math.min(keys.length - 1, keys.indexOf(activeDevice.id) + 1); + switchDevice(keys[prevIndex]); +}; -module.exports.toggleSlotButtons = function(slotIndex){ - if(slotIndex==1){ - document.getElementById("save-slot-1").classList.add("active"); - document.getElementById("save-slot-2").classList.remove("active"); - document.getElementById("save-slot-3").classList.remove("active"); - }else if(slotIndex==2){ - document.getElementById("save-slot-1").classList.remove("active"); - document.getElementById("save-slot-2").classList.add("active"); - document.getElementById("save-slot-3").classList.remove("active"); - }else if(slotIndex==3){ - document.getElementById("save-slot-1").classList.remove("active"); - document.getElementById("save-slot-2").classList.remove("active"); - document.getElementById("save-slot-3").classList.add("active"); - } -} +populatePluginLists = function () { + var typeSelect = ''; + var addSelect = ''; -module.exports.selectPreviousDevice = function(){ - if(activeDevice==undefined){ - return true; - } - var keys = Object.keys(DEVICE.all); - var prevIndex = Math.max(0, keys.indexOf(activeDevice.id)-1); - switchDevice(keys[prevIndex]) -} -module.exports.selectNextDevice = function(){ - if(activeDevice==undefined){ - return true; - } - var keys = Object.keys(DEVICE.all); - var prevIndex = Math.min(keys.length-1, keys.indexOf(activeDevice.id)+1); - switchDevice(keys[prevIndex]) -} + for (const pluginType in PLUGINS.all) { + var plugin = PLUGINS.all[pluginType]; + addSelect += + "'; + typeSelect += + "'; + } - -populatePluginLists = function(){ - - var typeSelect = ""; - var addSelect = ''; - - for(const pluginType in PLUGINS.all){ - var plugin = PLUGINS.all[pluginType]; - - addSelect+=""; - typeSelect+=""; - } - - document.getElementById("device-settings-plugin-dropdown").innerHTML = typeSelect; - document.getElementById("add-device-button").innerHTML = addSelect; -} + document.getElementById('device-settings-plugin-dropdown').innerHTML = + typeSelect; + document.getElementById('add-device-button').innerHTML = addSelect; +}; function debounce(func, wait, immediate) { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; -}; + var timeout; + return function () { + var context = this, + args = arguments; + var later = function () { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +}