diff --git a/.eslintrc.json b/.eslintrc.json index f9a15c24..c72e130d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,20 +1,25 @@ { "root": true, "extends": [ - "plugin:react/recommended", + "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", "plugin:import/errors", "plugin:import/warnings", "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier + "plugin:react/recommended", + "prettier/react", + "prettier/standard", "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. + ], "parser": "@typescript-eslint/parser", "plugins": [ "@typescript-eslint", "jsdoc", "import", - "prettier" + "prettier", + "react-hooks" ], "parserOptions": { "project": ["tsconfig.json"], @@ -26,20 +31,28 @@ "ecmaVersion": 2020 // Allows for the parsing of modern ECMAScript features }, "rules": { - "react/forbid-prop-types": "off", - "react/jsx-filename-extension": "off", - "react/no-string-refs": "off", - "react/require-default-props": "off", + "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks + "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies, + "@typescript-eslint/explicit-function-return-type": "off", - "no-console": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-misused-promises": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-unnecessary-type-assertion": "off", + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/require-await": "off", + + // "comma-dangle": ["error", "never"], + "object-curly-spacing": ["error", "always"], + "default-case": "off", + "import/extensions": "off", "no-constant-condition": ["error", { "checkLoops": false }], "no-param-reassign": "off", "no-restricted-syntax": "off", - "no-underscore-dangle": "off", - "default-case": "off", - "react/jsx-closing-tag-location": "off", - "import/extensions": "off", - "@typescript-eslint/explicit-module-boundary-types": "off" + "prettier/prettier": "error" }, "settings": { "import/resolver": { diff --git a/fake-runtime/FakeRuntime.ts b/fake-runtime/FakeRuntime.ts index 22d5e391..4df0db59 100644 --- a/fake-runtime/FakeRuntime.ts +++ b/fake-runtime/FakeRuntime.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ + /* * Fake Runtime is not handled by webpack like most of the other JS code but instead * will be run "as is" as a child-process of the rest of the application. @@ -53,7 +55,7 @@ class FakeRuntime { }); this.tcpServer.listen(TCP_PORT, () => { print('server bound'); - }) + }); setInterval(this.onInterval, MSGINTERVAL); } @@ -82,13 +84,13 @@ class FakeRuntime { // sensor('Ignored', 5, [param('is_unsafe', 'bool', Math.random() < 0.5), param('v_batt', 'float', randomFloat(0, 15))], 0), ], }; - } + }; onInterval = () => { const fakeData: DevData = this.generateFakeData(); this.sendSocket.send(DevData.encode(fakeData).finish(), UDP_SEND_PORT, 'localhost'); // TODO: Handle TCP writes to console - } + }; } -new FakeRuntime(); // eslint-disable-line no-new \ No newline at end of file +new FakeRuntime(); // eslint-disable-line no-new diff --git a/main/MenuTemplate/DawnMenu.ts b/main/MenuTemplate/DawnMenu.ts index 594a7731..3332a923 100644 --- a/main/MenuTemplate/DawnMenu.ts +++ b/main/MenuTemplate/DawnMenu.ts @@ -13,17 +13,17 @@ const DawnMenu: MenuItemConstructorOptions = { accelerator: 'CommandOrControl+Q', click() { app.quit(); - }, + } }, { label: 'Field Control Mode', click() { RendererBridge.reduxDispatch({ - type: 'TOGGLE_FIELD_CONTROL', + type: 'TOGGLE_FIELD_CONTROL' }); - }, - }, - ], + } + } + ] }; export default DawnMenu; diff --git a/main/MenuTemplate/DebugMenu.ts b/main/MenuTemplate/DebugMenu.ts index 1dc43060..b15b463d 100644 --- a/main/MenuTemplate/DebugMenu.ts +++ b/main/MenuTemplate/DebugMenu.ts @@ -23,15 +23,15 @@ const DebugMenu: MenuItemConstructorOptions = { RendererBridge.registeredWindow.webContents.toggleDevTools(); } }, - accelerator: 'CommandOrControl+alt+I', + accelerator: 'CommandOrControl+alt+I' }, { label: 'Restart Runtime', click() { RendererBridge.reduxDispatch({ - type: 'RESTART_RUNTIME', + type: 'RESTART_RUNTIME' }); - }, + } }, { label: 'Restart FC', @@ -42,15 +42,15 @@ const DebugMenu: MenuItemConstructorOptions = { } else { console.log('Field Control not active'); } - }, + } }, { label: 'Toggle Console Autoscroll', click() { RendererBridge.reduxDispatch({ - type: 'TOGGLE_SCROLL', + type: 'TOGGLE_SCROLL' }); - }, + } }, { @@ -60,30 +60,31 @@ const DebugMenu: MenuItemConstructorOptions = { if (RendererBridge.registeredWindow) { RendererBridge.registeredWindow.reload(); } - }, + } }, { label: 'Full Stack Timestamp', click() { RendererBridge.reduxDispatch({ - type: 'TIMESTAMP_CHECK', + type: 'TIMESTAMP_CHECK' }); - }, - }, - ], + } + } + ] }; if (process.env.NODE_ENV === 'development') { - (DebugMenu.submenu as MenuItemConstructorOptions[]).push({ // Need to type cast since submenu's type isn't always array + (DebugMenu.submenu as MenuItemConstructorOptions[]).push({ + // Need to type cast since submenu's type isn't always array label: 'Toggle Fake Runtime', click() { if (fakeRuntime) { killFakeRuntime(); } else { - fakeRuntime = fork('./fake-runtime/FakeRuntime.ts', [], { execArgv: ['-r', 'ts-node/register']}); + fakeRuntime = fork('./fake-runtime/FakeRuntime.ts', [], { execArgv: ['-r', 'ts-node/register'] }); } - }, + } }); } diff --git a/main/MenuTemplate/EditMenu.ts b/main/MenuTemplate/EditMenu.ts index fe4e6eb8..ba90249e 100644 --- a/main/MenuTemplate/EditMenu.ts +++ b/main/MenuTemplate/EditMenu.ts @@ -2,7 +2,7 @@ * Defines the edit menu. */ -import { MenuItemConstructorOptions } from "electron"; +import { MenuItemConstructorOptions } from 'electron'; const EditMenu: MenuItemConstructorOptions = { label: 'Edit', @@ -10,19 +10,19 @@ const EditMenu: MenuItemConstructorOptions = { { label: 'Cut', accelerator: 'CommandOrControl+X', - role: 'cut', + role: 'cut' }, { label: 'Copy', accelerator: 'CommandOrControl+C', - role: 'copy', + role: 'copy' }, { label: 'Paste', accelerator: 'CommandOrControl+V', - role: 'paste', - }, - ], + role: 'paste' + } + ] }; export default EditMenu; diff --git a/main/MenuTemplate/FileMenu.ts b/main/MenuTemplate/FileMenu.ts index 13bf72da..3a1fdf55 100644 --- a/main/MenuTemplate/FileMenu.ts +++ b/main/MenuTemplate/FileMenu.ts @@ -3,11 +3,7 @@ */ import RendererBridge from '../RendererBridge'; -import { - openFile, - saveFile, - createNewFile, -} from '../../renderer/actions/EditorActions'; +import { openFile, saveFile, createNewFile } from '../../renderer/actions/EditorActions'; import { MenuItemConstructorOptions } from 'electron'; const FileMenu: MenuItemConstructorOptions = { @@ -18,30 +14,30 @@ const FileMenu: MenuItemConstructorOptions = { click() { RendererBridge.reduxDispatch(createNewFile()); }, - accelerator: 'CommandOrControl+N', + accelerator: 'CommandOrControl+N' }, { label: 'Open file', click() { RendererBridge.reduxDispatch(openFile()); }, - accelerator: 'CommandOrControl+O', + accelerator: 'CommandOrControl+O' }, { label: 'Save file', click() { RendererBridge.reduxDispatch(saveFile()); }, - accelerator: 'CommandOrControl+S', + accelerator: 'CommandOrControl+S' }, { label: 'Save file as', click() { RendererBridge.reduxDispatch(saveFile(true)); }, - accelerator: 'CommandOrControl+Shift+S', - }, - ], + accelerator: 'CommandOrControl+Shift+S' + } + ] }; export default FileMenu; diff --git a/main/MenuTemplate/HelpMenu.ts b/main/MenuTemplate/HelpMenu.ts index 7cdc04a0..0c4541fc 100644 --- a/main/MenuTemplate/HelpMenu.ts +++ b/main/MenuTemplate/HelpMenu.ts @@ -15,16 +15,16 @@ const HelpMenu: MenuItemConstructorOptions = { RendererBridge.registeredWindow.webContents.send('start-interactive-tour'); } }, - accelerator: 'CommandOrControl+T', + accelerator: 'CommandOrControl+T' }, { label: 'PiE API', click() { showAPI(); }, - accelerator: 'CommandOrControl+P', - }, - ], + accelerator: 'CommandOrControl+P' + } + ] }; export default HelpMenu; diff --git a/main/MenuTemplate/Template.ts b/main/MenuTemplate/Template.ts index c7c7cff9..334dec0c 100644 --- a/main/MenuTemplate/Template.ts +++ b/main/MenuTemplate/Template.ts @@ -8,12 +8,6 @@ import FileMenu from './FileMenu'; import DebugMenu from './DebugMenu'; import HelpMenu from './HelpMenu'; -const Template = [ - DawnMenu, - FileMenu, - EditMenu, - DebugMenu, - HelpMenu, -]; +const Template = [DawnMenu, FileMenu, EditMenu, DebugMenu, HelpMenu]; export default Template; diff --git a/main/RendererBridge.ts b/main/RendererBridge.ts index 7d8e708a..442c2c18 100644 --- a/main/RendererBridge.ts +++ b/main/RendererBridge.ts @@ -1,12 +1,10 @@ +import { BrowserWindow } from 'electron'; + /** * RendererBridge connects the main process to the renderer's Redux flow. * Maintains a real-time copy of the renderer's Redux state in the main process, and * allows the main process to dispatch redux actions to the renderer. */ - -import _ from 'lodash'; -import { BrowserWindow } from "electron"; - class RendererBridge { registeredWindow: BrowserWindow | null = null; @@ -19,6 +17,6 @@ class RendererBridge { this.registeredWindow.webContents.send('dispatch', action); } }; -}; +} export default new RendererBridge(); diff --git a/main/main-process.ts b/main/main-process.ts index 24bb8011..e40e8ca7 100644 --- a/main/main-process.ts +++ b/main/main-process.ts @@ -26,7 +26,7 @@ app.on('will-quit', () => { } }); -function initializeFC(_event: any) { // eslint-disable-line no-unused-vars +function initializeFC(_event: any) { try { FCObject.setup(); } catch (err) { @@ -34,7 +34,8 @@ function initializeFC(_event: any) { // eslint-disable-line no-unused-vars } } -function teardownFC(_event: any) { // eslint-disable-line no-unused-vars +function teardownFC(_event: any) { + // eslint-disable-line no-unused-vars if (FCObject.FCInternal !== null) { FCObject.FCInternal.quit(); } @@ -43,18 +44,18 @@ function teardownFC(_event: any) { // eslint-disable-line no-unused-vars export default function showAPI() { let api: BrowserWindow | null = new BrowserWindow({ webPreferences: { - nodeIntegration: true, + nodeIntegration: true }, width: 1400, height: 900, - show: false, + show: false }); api.on('closed', () => { api = null; }); api.loadURL(`file://${__dirname}/../static/website-robot-api-master/robot_api.html`); api.once('ready-to-show', () => { - if (api) { + if (api !== null) { api.show(); } }); @@ -83,16 +84,20 @@ app.on('ready', () => { Menu.setApplicationMenu(menu); if (process.env.NODE_ENV !== 'production') { - installExtension(REACT_DEVELOPER_TOOLS).then((name: string) => { - console.log(`Added Extension: ${name}`); - }).catch((err: Error) => { - console.log('An error occurred: ', err); - }); + installExtension(REACT_DEVELOPER_TOOLS) + .then((name: string) => { + console.log(`Added Extension: ${name}`); + }) + .catch((err: Error) => { + console.log('An error occurred: ', err); + }); - installExtension(REDUX_DEVTOOLS).then((name: string) => { - console.log(`Added Extension: ${name}`); - }).catch((err: Error) => { - console.log('An error occurred: ', err); - }); + installExtension(REDUX_DEVTOOLS) + .then((name: string) => { + console.log(`Added Extension: ${name}`); + }) + .catch((err: Error) => { + console.log('An error occurred: ', err); + }); } }); diff --git a/main/networking/FieldControl.ts b/main/networking/FieldControl.ts index b968aea1..48c2780a 100644 --- a/main/networking/FieldControl.ts +++ b/main/networking/FieldControl.ts @@ -1,8 +1,19 @@ +import { IpcMainEvent } from 'electron'; import io from 'socket.io-client'; import { updateRobot, updateHeart, updateMaster } from '../../renderer/actions/FieldActions'; import RendererBridge from '../RendererBridge'; import { Logger } from '../../renderer/utils/utils'; +interface FCObjectInterface { + FCInternal: FCInternals | null; + stationNumber: number; + bridgeAddress: string; + logger: Logger; + + setup: () => void; + changeFCInfo: (_event: IpcMainEvent, arg: any) => void; +} + class FCInternals { socket: SocketIOClient.Socket | null; stationNumber: number; @@ -15,11 +26,9 @@ class FCInternals { this.bridgeAddress = bridgeAddress; this.logger = logger; this.logger.log(`Field Control: SN-${this.stationNumber} BA-${this.bridgeAddress}`); - this.init = this.init.bind(this); - this.quit = this.quit.bind(this); } - init() { + init = () => { this.socket = io(`http://${this.bridgeAddress}:7000`); this.socket.on('connect', () => { this.logger.log('Connected to Field Control Socket'); @@ -41,9 +50,9 @@ class FCInternals { RendererBridge.reduxDispatch(updateMaster(JSON.parse(data))); }); }); - } + }; - quit() { + quit = () => { try { if (this.socket) { this.socket.close(); @@ -52,32 +61,32 @@ class FCInternals { this.logger.log(err); } this.socket = null; - } + }; } -const FCInternalInit: any = null; - -export const FCObject = { - FCInternal: FCInternalInit, +export const FCObject: FCObjectInterface = { + FCInternal: null, stationNumber: 4, bridgeAddress: 'localhost', logger: new Logger('fieldControl', 'Field Control Debug'), + setup() { if (this.FCInternal !== null) { - this.FCInternal.quit(); + this.FCInternal!.quit(); } this.FCInternal = new FCInternals(this.stationNumber, this.bridgeAddress, FCObject.logger); this.FCInternal.init(); }, - changeFCInfo(_event: any, arg: any) { - if (arg.stationNumber !== null) { - FCObject.stationNumber = arg.stationNumber; + + changeFCInfo(_event: IpcMainEvent, args: { stationNumber: number; bridgeAddress: string }) { + if (args.stationNumber !== null) { + FCObject.stationNumber = args.stationNumber; FCObject.logger.log(`stationNumber set to ${FCObject.stationNumber}`); } - if (arg.bridgeAddress !== null) { - FCObject.bridgeAddress = arg.bridgeAddress; + if (args.bridgeAddress !== null) { + FCObject.bridgeAddress = args.bridgeAddress; FCObject.logger.log(`bridgeAddress set to ${FCObject.bridgeAddress}`); } - }, + } }; diff --git a/main/networking/Runtime.ts b/main/networking/Runtime.ts index c31e60ed..120c675d 100644 --- a/main/networking/Runtime.ts +++ b/main/networking/Runtime.ts @@ -29,7 +29,7 @@ enum MsgType { START_POS, CHALLENGE_DATA, LOG, - DEVICE_DATA, + DEVICE_DATA } interface TCPPacket { @@ -52,7 +52,7 @@ function readPacket(data: any): TCPPacket { return { messageType: msgType, messageLength: msgLength, - payload: load, + payload: load }; } @@ -106,8 +106,7 @@ class TCPConn { this.socket.connect(TCP_PORT, runtimeIP, () => { this.logger.log('Runtime connected'); this.socket.write(new Uint8Array([1])); // Runtime needs first byte to be 1 to recognize client as Dawn (instead of Shepherd) - } - ) + }); } } }, 1000); @@ -197,7 +196,7 @@ class TCPConn { this.socket.write(message, () => { this.logger.debug(`Challenge inputs sent: ${textData.toString()}`); }); - } + }; sendRobotStartPos = (_event: IpcMainEvent, startPosData: protos.IStartPos) => { // TODO: Get start pos from sagas @@ -249,7 +248,7 @@ class UDPConn { try { RendererBridge.reduxDispatch(infoPerMessage()); const sensorData: protos.Device[] = protos.DevData.decode(msg).devices; - + sensorData.forEach((device) => { if (device.uid.toString() === '0') { device.uid = 0; @@ -282,7 +281,7 @@ class UDPConn { if (data.length === 0) { data.push( protos.GpState.create({ - connected: false, + connected: false }) ); } @@ -310,5 +309,5 @@ export const Runtime = { close() { this.conns.forEach((conn) => conn.close()); // Logger's fs closes automatically - }, + } }; diff --git a/package.json b/package.json index 3458bea4..81bebdd0 100644 --- a/package.json +++ b/package.json @@ -14,20 +14,13 @@ "printWidth": 140, "arrowParens": "always", "parser": "typescript", - "bracketSpacing": true + "bracketSpacing": true, + "trailingComma": "none" }, "main": "build/main.js", "scripts": { "start": "better-npm-run start", "build": "rm -rf build && tsc --build", - "lint-actions": "eslint renderer/actions/**/*.ts", - "lint-reducers": "eslint renderer/reducers/**/*.ts", - "lint-types": "eslint renderer/types/**/*.ts", - "lint-components": "eslint renderer/components/**/*.ts", - "lint-actions-fix": "eslint renderer/actions/**/*.ts --fix", - "lint-reducers-fix": "eslint renderer/reducers/**/*.ts --fix", - "lint-types-fix": "eslint renderer/types/**/*.ts --fix", - "lint-components-fix": "eslint renderer/components/**/*.ts --fix", "lint": "eslint '*/**/*.ts?(x)'", "lintfix": "eslint '*/**/*.ts?(x)' --fix", "postinstall": "patch-package", @@ -86,6 +79,7 @@ "eslint-plugin-jsx-a11y": "6.0.3", "eslint-plugin-prettier": "^3.1.4", "eslint-plugin-react": "7.5.1", + "eslint-plugin-react-hooks": "^4.2.0", "file-loader": "^6.1.0", "fs-extra": "5.0.0", "jszip": "3.1.5", diff --git a/protos/protos.d.ts b/protos/protos.d.ts index 55d321a2..f495d84f 100644 --- a/protos/protos.d.ts +++ b/protos/protos.d.ts @@ -1,3 +1,5 @@ +/* eslint-disable */ + import * as $protobuf from 'protobufjs'; /** Properties of a Param. */ export interface IParam { diff --git a/protos/protos.js b/protos/protos.js index 16d0fe9d..32a75fce 100644 --- a/protos/protos.js +++ b/protos/protos.js @@ -1,1049 +1,959 @@ -import * as $protobuf from "protobufjs/minimal"; +import * as $protobuf from 'protobufjs/minimal'; // Common aliases -const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; +const $Reader = $protobuf.Reader, + $Writer = $protobuf.Writer, + $util = $protobuf.util; // Exported root namespace -const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); - -export const Param = $root.Param = (() => { - - /** - * Properties of a Param. - * @exports IParam - * @interface IParam - * @property {string|null} [name] Param name - * @property {number|null} [fval] Param fval - * @property {number|null} [ival] Param ival - * @property {boolean|null} [bval] Param bval - */ - - /** - * Constructs a new Param. - * @exports Param - * @classdesc Represents a Param. - * @implements IParam - * @constructor - * @param {IParam=} [properties] Properties to set - */ - function Param(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; +const $root = $protobuf.roots['default'] || ($protobuf.roots['default'] = {}); + +export const Param = ($root.Param = (() => { + /** + * Properties of a Param. + * @exports IParam + * @interface IParam + * @property {string|null} [name] Param name + * @property {number|null} [fval] Param fval + * @property {number|null} [ival] Param ival + * @property {boolean|null} [bval] Param bval + */ + + /** + * Constructs a new Param. + * @exports Param + * @classdesc Represents a Param. + * @implements IParam + * @constructor + * @param {IParam=} [properties] Properties to set + */ + function Param(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Param name. + * @member {string} name + * @memberof Param + * @instance + */ + Param.prototype.name = ''; + + /** + * Param fval. + * @member {number} fval + * @memberof Param + * @instance + */ + Param.prototype.fval = 0; + + /** + * Param ival. + * @member {number} ival + * @memberof Param + * @instance + */ + Param.prototype.ival = 0; + + /** + * Param bval. + * @member {boolean} bval + * @memberof Param + * @instance + */ + Param.prototype.bval = false; + + // OneOf field names bound to virtual getters and setters + let $oneOfFields; + + /** + * Param val. + * @member {"fval"|"ival"|"bval"|undefined} val + * @memberof Param + * @instance + */ + Object.defineProperty(Param.prototype, 'val', { + get: $util.oneOfGetter(($oneOfFields = ['fval', 'ival', 'bval'])), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new Param instance using the specified properties. + * @function create + * @memberof Param + * @static + * @param {IParam=} [properties] Properties to set + * @returns {Param} Param instance + */ + Param.create = function create(properties) { + return new Param(properties); + }; + + /** + * Encodes the specified Param message. Does not implicitly {@link Param.verify|verify} messages. + * @function encode + * @memberof Param + * @static + * @param {IParam} message Param message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Param.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && message.hasOwnProperty('name')) writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.fval != null && message.hasOwnProperty('fval')) writer.uint32(/* id 2, wireType 5 =*/ 21).float(message.fval); + if (message.ival != null && message.hasOwnProperty('ival')) writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.ival); + if (message.bval != null && message.hasOwnProperty('bval')) writer.uint32(/* id 4, wireType 0 =*/ 32).bool(message.bval); + return writer; + }; + + /** + * Encodes the specified Param message, length delimited. Does not implicitly {@link Param.verify|verify} messages. + * @function encodeDelimited + * @memberof Param + * @static + * @param {IParam} message Param message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Param.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Param message from the specified reader or buffer. + * @function decode + * @memberof Param + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {Param} Param + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Param.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Param(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.name = reader.string(); + break; + case 2: + message.fval = reader.float(); + break; + case 3: + message.ival = reader.int32(); + break; + case 4: + message.bval = reader.bool(); + break; + default: + reader.skipType(tag & 7); + break; + } } - - /** - * Param name. - * @member {string} name - * @memberof Param - * @instance - */ - Param.prototype.name = ""; - - /** - * Param fval. - * @member {number} fval - * @memberof Param - * @instance - */ - Param.prototype.fval = 0; - - /** - * Param ival. - * @member {number} ival - * @memberof Param - * @instance - */ - Param.prototype.ival = 0; - - /** - * Param bval. - * @member {boolean} bval - * @memberof Param - * @instance - */ - Param.prototype.bval = false; - - // OneOf field names bound to virtual getters and setters - let $oneOfFields; - - /** - * Param val. - * @member {"fval"|"ival"|"bval"|undefined} val - * @memberof Param - * @instance - */ - Object.defineProperty(Param.prototype, "val", { - get: $util.oneOfGetter($oneOfFields = ["fval", "ival", "bval"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new Param instance using the specified properties. - * @function create - * @memberof Param - * @static - * @param {IParam=} [properties] Properties to set - * @returns {Param} Param instance - */ - Param.create = function create(properties) { - return new Param(properties); - }; - - /** - * Encodes the specified Param message. Does not implicitly {@link Param.verify|verify} messages. - * @function encode - * @memberof Param - * @static - * @param {IParam} message Param message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Param.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && message.hasOwnProperty("name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.fval != null && message.hasOwnProperty("fval")) - writer.uint32(/* id 2, wireType 5 =*/21).float(message.fval); - if (message.ival != null && message.hasOwnProperty("ival")) - writer.uint32(/* id 3, wireType 0 =*/24).int32(message.ival); - if (message.bval != null && message.hasOwnProperty("bval")) - writer.uint32(/* id 4, wireType 0 =*/32).bool(message.bval); - return writer; - }; - - /** - * Encodes the specified Param message, length delimited. Does not implicitly {@link Param.verify|verify} messages. - * @function encodeDelimited - * @memberof Param - * @static - * @param {IParam} message Param message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Param.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Param message from the specified reader or buffer. - * @function decode - * @memberof Param - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {Param} Param - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Param.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.Param(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.name = reader.string(); - break; - case 2: - message.fval = reader.float(); - break; - case 3: - message.ival = reader.int32(); - break; - case 4: - message.bval = reader.bool(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Param message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof Param - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {Param} Param - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Param.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Param message. - * @function verify - * @memberof Param - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Param.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - let properties = {}; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.fval != null && message.hasOwnProperty("fval")) { - properties.val = 1; - if (typeof message.fval !== "number") - return "fval: number expected"; - } - if (message.ival != null && message.hasOwnProperty("ival")) { - if (properties.val === 1) - return "val: multiple values"; - properties.val = 1; - if (!$util.isInteger(message.ival)) - return "ival: integer expected"; - } - if (message.bval != null && message.hasOwnProperty("bval")) { - if (properties.val === 1) - return "val: multiple values"; - properties.val = 1; - if (typeof message.bval !== "boolean") - return "bval: boolean expected"; - } - return null; - }; - - /** - * Creates a Param message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof Param - * @static - * @param {Object.} object Plain object - * @returns {Param} Param - */ - Param.fromObject = function fromObject(object) { - if (object instanceof $root.Param) - return object; - let message = new $root.Param(); - if (object.name != null) - message.name = String(object.name); - if (object.fval != null) - message.fval = Number(object.fval); - if (object.ival != null) - message.ival = object.ival | 0; - if (object.bval != null) - message.bval = Boolean(object.bval); - return message; - }; - - /** - * Creates a plain object from a Param message. Also converts values to other types if specified. - * @function toObject - * @memberof Param - * @static - * @param {Param} message Param - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Param.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) - object.name = ""; - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.fval != null && message.hasOwnProperty("fval")) { - object.fval = options.json && !isFinite(message.fval) ? String(message.fval) : message.fval; - if (options.oneofs) - object.val = "fval"; - } - if (message.ival != null && message.hasOwnProperty("ival")) { - object.ival = message.ival; - if (options.oneofs) - object.val = "ival"; - } - if (message.bval != null && message.hasOwnProperty("bval")) { - object.bval = message.bval; - if (options.oneofs) - object.val = "bval"; - } - return object; - }; - - /** - * Converts this Param to JSON. - * @function toJSON - * @memberof Param - * @instance - * @returns {Object.} JSON object - */ - Param.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return Param; -})(); - -export const Device = $root.Device = (() => { - - /** - * Properties of a Device. - * @exports IDevice - * @interface IDevice - * @property {string|null} [name] Device name - * @property {number|null} [uid] Device uid - * @property {number|null} [type] Device type - * @property {Array.|null} [params] Device params - */ - - /** - * Constructs a new Device. - * @exports Device - * @classdesc Represents a Device. - * @implements IDevice - * @constructor - * @param {IDevice=} [properties] Properties to set - */ - function Device(properties) { - this.params = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + return message; + }; + + /** + * Decodes a Param message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof Param + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {Param} Param + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Param.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Param message. + * @function verify + * @memberof Param + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Param.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + let properties = {}; + if (message.name != null && message.hasOwnProperty('name')) if (!$util.isString(message.name)) return 'name: string expected'; + if (message.fval != null && message.hasOwnProperty('fval')) { + properties.val = 1; + if (typeof message.fval !== 'number') return 'fval: number expected'; } - - /** - * Device name. - * @member {string} name - * @memberof Device - * @instance - */ - Device.prototype.name = ""; - - /** - * Device uid. - * @member {number|Long} uid - * @memberof Device - * @instance - */ - Device.prototype.uid = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - - /** - * Device type. - * @member {number} type - * @memberof Device - * @instance - */ - Device.prototype.type = 0; - - /** - * Device params. - * @member {Array.} params - * @memberof Device - * @instance - */ - Device.prototype.params = $util.emptyArray; - - /** - * Creates a new Device instance using the specified properties. - * @function create - * @memberof Device - * @static - * @param {IDevice=} [properties] Properties to set - * @returns {Device} Device instance - */ - Device.create = function create(properties) { - return new Device(properties); - }; - - /** - * Encodes the specified Device message. Does not implicitly {@link Device.verify|verify} messages. - * @function encode - * @memberof Device - * @static - * @param {IDevice} message Device message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Device.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.name != null && message.hasOwnProperty("name")) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.name); - if (message.uid != null && message.hasOwnProperty("uid")) - writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.uid); - if (message.type != null && message.hasOwnProperty("type")) - writer.uint32(/* id 3, wireType 0 =*/24).int32(message.type); - if (message.params != null && message.params.length) - for (let i = 0; i < message.params.length; ++i) - $root.Param.encode(message.params[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified Device message, length delimited. Does not implicitly {@link Device.verify|verify} messages. - * @function encodeDelimited - * @memberof Device - * @static - * @param {IDevice} message Device message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Device.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Device message from the specified reader or buffer. - * @function decode - * @memberof Device - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {Device} Device - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Device.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.Device(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.name = reader.string(); - break; - case 2: - message.uid = reader.uint64(); - break; - case 3: - message.type = reader.int32(); - break; - case 4: - if (!(message.params && message.params.length)) - message.params = []; - message.params.push($root.Param.decode(reader, reader.uint32())); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Device message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof Device - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {Device} Device - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Device.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Device message. - * @function verify - * @memberof Device - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Device.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.name != null && message.hasOwnProperty("name")) - if (!$util.isString(message.name)) - return "name: string expected"; - if (message.uid != null && message.hasOwnProperty("uid")) - if (!$util.isInteger(message.uid) && !(message.uid && $util.isInteger(message.uid.low) && $util.isInteger(message.uid.high))) - return "uid: integer|Long expected"; - if (message.type != null && message.hasOwnProperty("type")) - if (!$util.isInteger(message.type)) - return "type: integer expected"; - if (message.params != null && message.hasOwnProperty("params")) { - if (!Array.isArray(message.params)) - return "params: array expected"; - for (let i = 0; i < message.params.length; ++i) { - let error = $root.Param.verify(message.params[i]); - if (error) - return "params." + error; - } - } - return null; - }; - - /** - * Creates a Device message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof Device - * @static - * @param {Object.} object Plain object - * @returns {Device} Device - */ - Device.fromObject = function fromObject(object) { - if (object instanceof $root.Device) - return object; - let message = new $root.Device(); - if (object.name != null) - message.name = String(object.name); - if (object.uid != null) - if ($util.Long) - (message.uid = $util.Long.fromValue(object.uid)).unsigned = true; - else if (typeof object.uid === "string") - message.uid = parseInt(object.uid, 10); - else if (typeof object.uid === "number") - message.uid = object.uid; - else if (typeof object.uid === "object") - message.uid = new $util.LongBits(object.uid.low >>> 0, object.uid.high >>> 0).toNumber(true); - if (object.type != null) - message.type = object.type | 0; - if (object.params) { - if (!Array.isArray(object.params)) - throw TypeError(".Device.params: array expected"); - message.params = []; - for (let i = 0; i < object.params.length; ++i) { - if (typeof object.params[i] !== "object") - throw TypeError(".Device.params: object expected"); - message.params[i] = $root.Param.fromObject(object.params[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a Device message. Also converts values to other types if specified. - * @function toObject - * @memberof Device - * @static - * @param {Device} message Device - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Device.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.params = []; - if (options.defaults) { - object.name = ""; - if ($util.Long) { - let long = new $util.Long(0, 0, true); - object.uid = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.uid = options.longs === String ? "0" : 0; - object.type = 0; - } - if (message.name != null && message.hasOwnProperty("name")) - object.name = message.name; - if (message.uid != null && message.hasOwnProperty("uid")) - if (typeof message.uid === "number") - object.uid = options.longs === String ? String(message.uid) : message.uid; - else - object.uid = options.longs === String ? $util.Long.prototype.toString.call(message.uid) : options.longs === Number ? new $util.LongBits(message.uid.low >>> 0, message.uid.high >>> 0).toNumber(true) : message.uid; - if (message.type != null && message.hasOwnProperty("type")) - object.type = message.type; - if (message.params && message.params.length) { - object.params = []; - for (let j = 0; j < message.params.length; ++j) - object.params[j] = $root.Param.toObject(message.params[j], options); - } - return object; - }; - - /** - * Converts this Device to JSON. - * @function toJSON - * @memberof Device - * @instance - * @returns {Object.} JSON object - */ - Device.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return Device; -})(); - -export const DevData = $root.DevData = (() => { - - /** - * Properties of a DevData. - * @exports IDevData - * @interface IDevData - * @property {Array.|null} [devices] DevData devices - */ - - /** - * Constructs a new DevData. - * @exports DevData - * @classdesc Represents a DevData. - * @implements IDevData - * @constructor - * @param {IDevData=} [properties] Properties to set - */ - function DevData(properties) { - this.devices = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + if (message.ival != null && message.hasOwnProperty('ival')) { + if (properties.val === 1) return 'val: multiple values'; + properties.val = 1; + if (!$util.isInteger(message.ival)) return 'ival: integer expected'; } - - /** - * DevData devices. - * @member {Array.} devices - * @memberof DevData - * @instance - */ - DevData.prototype.devices = $util.emptyArray; - - /** - * Creates a new DevData instance using the specified properties. - * @function create - * @memberof DevData - * @static - * @param {IDevData=} [properties] Properties to set - * @returns {DevData} DevData instance - */ - DevData.create = function create(properties) { - return new DevData(properties); - }; - - /** - * Encodes the specified DevData message. Does not implicitly {@link DevData.verify|verify} messages. - * @function encode - * @memberof DevData - * @static - * @param {IDevData} message DevData message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - DevData.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.devices != null && message.devices.length) - for (let i = 0; i < message.devices.length; ++i) - $root.Device.encode(message.devices[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified DevData message, length delimited. Does not implicitly {@link DevData.verify|verify} messages. - * @function encodeDelimited - * @memberof DevData - * @static - * @param {IDevData} message DevData message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - DevData.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a DevData message from the specified reader or buffer. - * @function decode - * @memberof DevData - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {DevData} DevData - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - DevData.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.DevData(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (!(message.devices && message.devices.length)) - message.devices = []; - message.devices.push($root.Device.decode(reader, reader.uint32())); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a DevData message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof DevData - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {DevData} DevData - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - DevData.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a DevData message. - * @function verify - * @memberof DevData - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - DevData.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.devices != null && message.hasOwnProperty("devices")) { - if (!Array.isArray(message.devices)) - return "devices: array expected"; - for (let i = 0; i < message.devices.length; ++i) { - let error = $root.Device.verify(message.devices[i]); - if (error) - return "devices." + error; - } - } - return null; - }; - - /** - * Creates a DevData message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof DevData - * @static - * @param {Object.} object Plain object - * @returns {DevData} DevData - */ - DevData.fromObject = function fromObject(object) { - if (object instanceof $root.DevData) - return object; - let message = new $root.DevData(); - if (object.devices) { - if (!Array.isArray(object.devices)) - throw TypeError(".DevData.devices: array expected"); - message.devices = []; - for (let i = 0; i < object.devices.length; ++i) { - if (typeof object.devices[i] !== "object") - throw TypeError(".DevData.devices: object expected"); - message.devices[i] = $root.Device.fromObject(object.devices[i]); - } - } - return message; - }; - - /** - * Creates a plain object from a DevData message. Also converts values to other types if specified. - * @function toObject - * @memberof DevData - * @static - * @param {DevData} message DevData - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - DevData.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.devices = []; - if (message.devices && message.devices.length) { - object.devices = []; - for (let j = 0; j < message.devices.length; ++j) - object.devices[j] = $root.Device.toObject(message.devices[j], options); - } - return object; - }; - - /** - * Converts this DevData to JSON. - * @function toJSON - * @memberof DevData - * @instance - * @returns {Object.} JSON object - */ - DevData.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return DevData; -})(); - -export const GpState = $root.GpState = (() => { - - /** - * Properties of a GpState. - * @exports IGpState - * @interface IGpState - * @property {boolean|null} [connected] GpState connected - * @property {number|null} [buttons] GpState buttons - * @property {Array.|null} [axes] GpState axes - */ - - /** - * Constructs a new GpState. - * @exports GpState - * @classdesc Represents a GpState. - * @implements IGpState - * @constructor - * @param {IGpState=} [properties] Properties to set - */ - function GpState(properties) { - this.axes = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + if (message.bval != null && message.hasOwnProperty('bval')) { + if (properties.val === 1) return 'val: multiple values'; + properties.val = 1; + if (typeof message.bval !== 'boolean') return 'bval: boolean expected'; } - - /** - * GpState connected. - * @member {boolean} connected - * @memberof GpState - * @instance - */ - GpState.prototype.connected = false; - - /** - * GpState buttons. - * @member {number} buttons - * @memberof GpState - * @instance - */ - GpState.prototype.buttons = 0; - - /** - * GpState axes. - * @member {Array.} axes - * @memberof GpState - * @instance - */ - GpState.prototype.axes = $util.emptyArray; - - /** - * Creates a new GpState instance using the specified properties. - * @function create - * @memberof GpState - * @static - * @param {IGpState=} [properties] Properties to set - * @returns {GpState} GpState instance - */ - GpState.create = function create(properties) { - return new GpState(properties); - }; - - /** - * Encodes the specified GpState message. Does not implicitly {@link GpState.verify|verify} messages. - * @function encode - * @memberof GpState - * @static - * @param {IGpState} message GpState message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GpState.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.connected != null && message.hasOwnProperty("connected")) - writer.uint32(/* id 1, wireType 0 =*/8).bool(message.connected); - if (message.buttons != null && message.hasOwnProperty("buttons")) - writer.uint32(/* id 2, wireType 5 =*/21).fixed32(message.buttons); - if (message.axes != null && message.axes.length) { - writer.uint32(/* id 3, wireType 2 =*/26).fork(); - for (let i = 0; i < message.axes.length; ++i) - writer.float(message.axes[i]); - writer.ldelim(); - } - return writer; - }; - - /** - * Encodes the specified GpState message, length delimited. Does not implicitly {@link GpState.verify|verify} messages. - * @function encodeDelimited - * @memberof GpState - * @static - * @param {IGpState} message GpState message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GpState.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GpState message from the specified reader or buffer. - * @function decode - * @memberof GpState - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {GpState} GpState - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GpState.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.GpState(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.connected = reader.bool(); - break; - case 2: - message.buttons = reader.fixed32(); - break; - case 3: - if (!(message.axes && message.axes.length)) - message.axes = []; - if ((tag & 7) === 2) { - let end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) - message.axes.push(reader.float()); - } else - message.axes.push(reader.float()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GpState message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof GpState - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {GpState} GpState - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GpState.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GpState message. - * @function verify - * @memberof GpState - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GpState.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.connected != null && message.hasOwnProperty("connected")) - if (typeof message.connected !== "boolean") - return "connected: boolean expected"; - if (message.buttons != null && message.hasOwnProperty("buttons")) - if (!$util.isInteger(message.buttons)) - return "buttons: integer expected"; - if (message.axes != null && message.hasOwnProperty("axes")) { - if (!Array.isArray(message.axes)) - return "axes: array expected"; - for (let i = 0; i < message.axes.length; ++i) - if (typeof message.axes[i] !== "number") - return "axes: number[] expected"; - } - return null; - }; - - /** - * Creates a GpState message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof GpState - * @static - * @param {Object.} object Plain object - * @returns {GpState} GpState - */ - GpState.fromObject = function fromObject(object) { - if (object instanceof $root.GpState) - return object; - let message = new $root.GpState(); - if (object.connected != null) - message.connected = Boolean(object.connected); - if (object.buttons != null) - message.buttons = object.buttons >>> 0; - if (object.axes) { - if (!Array.isArray(object.axes)) - throw TypeError(".GpState.axes: array expected"); - message.axes = []; - for (let i = 0; i < object.axes.length; ++i) - message.axes[i] = Number(object.axes[i]); - } - return message; - }; - - /** - * Creates a plain object from a GpState message. Also converts values to other types if specified. - * @function toObject - * @memberof GpState - * @static - * @param {GpState} message GpState - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GpState.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.axes = []; - if (options.defaults) { - object.connected = false; - object.buttons = 0; - } - if (message.connected != null && message.hasOwnProperty("connected")) - object.connected = message.connected; - if (message.buttons != null && message.hasOwnProperty("buttons")) - object.buttons = message.buttons; - if (message.axes && message.axes.length) { - object.axes = []; - for (let j = 0; j < message.axes.length; ++j) - object.axes[j] = options.json && !isFinite(message.axes[j]) ? String(message.axes[j]) : message.axes[j]; - } - return object; - }; - - /** - * Converts this GpState to JSON. - * @function toJSON - * @memberof GpState - * @instance - * @returns {Object.} JSON object - */ - GpState.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return GpState; -})(); + return null; + }; + + /** + * Creates a Param message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Param + * @static + * @param {Object.} object Plain object + * @returns {Param} Param + */ + Param.fromObject = function fromObject(object) { + if (object instanceof $root.Param) return object; + let message = new $root.Param(); + if (object.name != null) message.name = String(object.name); + if (object.fval != null) message.fval = Number(object.fval); + if (object.ival != null) message.ival = object.ival | 0; + if (object.bval != null) message.bval = Boolean(object.bval); + return message; + }; + + /** + * Creates a plain object from a Param message. Also converts values to other types if specified. + * @function toObject + * @memberof Param + * @static + * @param {Param} message Param + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Param.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) object.name = ''; + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.fval != null && message.hasOwnProperty('fval')) { + object.fval = options.json && !isFinite(message.fval) ? String(message.fval) : message.fval; + if (options.oneofs) object.val = 'fval'; + } + if (message.ival != null && message.hasOwnProperty('ival')) { + object.ival = message.ival; + if (options.oneofs) object.val = 'ival'; + } + if (message.bval != null && message.hasOwnProperty('bval')) { + object.bval = message.bval; + if (options.oneofs) object.val = 'bval'; + } + return object; + }; + + /** + * Converts this Param to JSON. + * @function toJSON + * @memberof Param + * @instance + * @returns {Object.} JSON object + */ + Param.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Param; +})()); + +export const Device = ($root.Device = (() => { + /** + * Properties of a Device. + * @exports IDevice + * @interface IDevice + * @property {string|null} [name] Device name + * @property {number|null} [uid] Device uid + * @property {number|null} [type] Device type + * @property {Array.|null} [params] Device params + */ + + /** + * Constructs a new Device. + * @exports Device + * @classdesc Represents a Device. + * @implements IDevice + * @constructor + * @param {IDevice=} [properties] Properties to set + */ + function Device(properties) { + this.params = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Device name. + * @member {string} name + * @memberof Device + * @instance + */ + Device.prototype.name = ''; + + /** + * Device uid. + * @member {number|Long} uid + * @memberof Device + * @instance + */ + Device.prototype.uid = $util.Long ? $util.Long.fromBits(0, 0, true) : 0; + + /** + * Device type. + * @member {number} type + * @memberof Device + * @instance + */ + Device.prototype.type = 0; + + /** + * Device params. + * @member {Array.} params + * @memberof Device + * @instance + */ + Device.prototype.params = $util.emptyArray; + + /** + * Creates a new Device instance using the specified properties. + * @function create + * @memberof Device + * @static + * @param {IDevice=} [properties] Properties to set + * @returns {Device} Device instance + */ + Device.create = function create(properties) { + return new Device(properties); + }; + + /** + * Encodes the specified Device message. Does not implicitly {@link Device.verify|verify} messages. + * @function encode + * @memberof Device + * @static + * @param {IDevice} message Device message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Device.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.name != null && message.hasOwnProperty('name')) writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.name); + if (message.uid != null && message.hasOwnProperty('uid')) writer.uint32(/* id 2, wireType 0 =*/ 16).uint64(message.uid); + if (message.type != null && message.hasOwnProperty('type')) writer.uint32(/* id 3, wireType 0 =*/ 24).int32(message.type); + if (message.params != null && message.params.length) + for (let i = 0; i < message.params.length; ++i) + $root.Param.encode(message.params[i], writer.uint32(/* id 4, wireType 2 =*/ 34).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Device message, length delimited. Does not implicitly {@link Device.verify|verify} messages. + * @function encodeDelimited + * @memberof Device + * @static + * @param {IDevice} message Device message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Device.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Device message from the specified reader or buffer. + * @function decode + * @memberof Device + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {Device} Device + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Device.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Device(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.name = reader.string(); + break; + case 2: + message.uid = reader.uint64(); + break; + case 3: + message.type = reader.int32(); + break; + case 4: + if (!(message.params && message.params.length)) message.params = []; + message.params.push($root.Param.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Device message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof Device + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {Device} Device + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Device.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Device message. + * @function verify + * @memberof Device + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Device.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.name != null && message.hasOwnProperty('name')) if (!$util.isString(message.name)) return 'name: string expected'; + if (message.uid != null && message.hasOwnProperty('uid')) + if (!$util.isInteger(message.uid) && !(message.uid && $util.isInteger(message.uid.low) && $util.isInteger(message.uid.high))) + return 'uid: integer|Long expected'; + if (message.type != null && message.hasOwnProperty('type')) if (!$util.isInteger(message.type)) return 'type: integer expected'; + if (message.params != null && message.hasOwnProperty('params')) { + if (!Array.isArray(message.params)) return 'params: array expected'; + for (let i = 0; i < message.params.length; ++i) { + let error = $root.Param.verify(message.params[i]); + if (error) return 'params.' + error; + } + } + return null; + }; + + /** + * Creates a Device message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Device + * @static + * @param {Object.} object Plain object + * @returns {Device} Device + */ + Device.fromObject = function fromObject(object) { + if (object instanceof $root.Device) return object; + let message = new $root.Device(); + if (object.name != null) message.name = String(object.name); + if (object.uid != null) + if ($util.Long) (message.uid = $util.Long.fromValue(object.uid)).unsigned = true; + else if (typeof object.uid === 'string') message.uid = parseInt(object.uid, 10); + else if (typeof object.uid === 'number') message.uid = object.uid; + else if (typeof object.uid === 'object') message.uid = new $util.LongBits(object.uid.low >>> 0, object.uid.high >>> 0).toNumber(true); + if (object.type != null) message.type = object.type | 0; + if (object.params) { + if (!Array.isArray(object.params)) throw TypeError('.Device.params: array expected'); + message.params = []; + for (let i = 0; i < object.params.length; ++i) { + if (typeof object.params[i] !== 'object') throw TypeError('.Device.params: object expected'); + message.params[i] = $root.Param.fromObject(object.params[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a Device message. Also converts values to other types if specified. + * @function toObject + * @memberof Device + * @static + * @param {Device} message Device + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Device.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.params = []; + if (options.defaults) { + object.name = ''; + if ($util.Long) { + let long = new $util.Long(0, 0, true); + object.uid = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else object.uid = options.longs === String ? '0' : 0; + object.type = 0; + } + if (message.name != null && message.hasOwnProperty('name')) object.name = message.name; + if (message.uid != null && message.hasOwnProperty('uid')) + if (typeof message.uid === 'number') object.uid = options.longs === String ? String(message.uid) : message.uid; + else + object.uid = + options.longs === String + ? $util.Long.prototype.toString.call(message.uid) + : options.longs === Number + ? new $util.LongBits(message.uid.low >>> 0, message.uid.high >>> 0).toNumber(true) + : message.uid; + if (message.type != null && message.hasOwnProperty('type')) object.type = message.type; + if (message.params && message.params.length) { + object.params = []; + for (let j = 0; j < message.params.length; ++j) object.params[j] = $root.Param.toObject(message.params[j], options); + } + return object; + }; + + /** + * Converts this Device to JSON. + * @function toJSON + * @memberof Device + * @instance + * @returns {Object.} JSON object + */ + Device.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Device; +})()); + +export const DevData = ($root.DevData = (() => { + /** + * Properties of a DevData. + * @exports IDevData + * @interface IDevData + * @property {Array.|null} [devices] DevData devices + */ + + /** + * Constructs a new DevData. + * @exports DevData + * @classdesc Represents a DevData. + * @implements IDevData + * @constructor + * @param {IDevData=} [properties] Properties to set + */ + function DevData(properties) { + this.devices = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * DevData devices. + * @member {Array.} devices + * @memberof DevData + * @instance + */ + DevData.prototype.devices = $util.emptyArray; + + /** + * Creates a new DevData instance using the specified properties. + * @function create + * @memberof DevData + * @static + * @param {IDevData=} [properties] Properties to set + * @returns {DevData} DevData instance + */ + DevData.create = function create(properties) { + return new DevData(properties); + }; + + /** + * Encodes the specified DevData message. Does not implicitly {@link DevData.verify|verify} messages. + * @function encode + * @memberof DevData + * @static + * @param {IDevData} message DevData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DevData.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.devices != null && message.devices.length) + for (let i = 0; i < message.devices.length; ++i) + $root.Device.encode(message.devices[i], writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified DevData message, length delimited. Does not implicitly {@link DevData.verify|verify} messages. + * @function encodeDelimited + * @memberof DevData + * @static + * @param {IDevData} message DevData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DevData.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a DevData message from the specified reader or buffer. + * @function decode + * @memberof DevData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {DevData} DevData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DevData.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.DevData(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (!(message.devices && message.devices.length)) message.devices = []; + message.devices.push($root.Device.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a DevData message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof DevData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {DevData} DevData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DevData.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a DevData message. + * @function verify + * @memberof DevData + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + DevData.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.devices != null && message.hasOwnProperty('devices')) { + if (!Array.isArray(message.devices)) return 'devices: array expected'; + for (let i = 0; i < message.devices.length; ++i) { + let error = $root.Device.verify(message.devices[i]); + if (error) return 'devices.' + error; + } + } + return null; + }; + + /** + * Creates a DevData message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof DevData + * @static + * @param {Object.} object Plain object + * @returns {DevData} DevData + */ + DevData.fromObject = function fromObject(object) { + if (object instanceof $root.DevData) return object; + let message = new $root.DevData(); + if (object.devices) { + if (!Array.isArray(object.devices)) throw TypeError('.DevData.devices: array expected'); + message.devices = []; + for (let i = 0; i < object.devices.length; ++i) { + if (typeof object.devices[i] !== 'object') throw TypeError('.DevData.devices: object expected'); + message.devices[i] = $root.Device.fromObject(object.devices[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a DevData message. Also converts values to other types if specified. + * @function toObject + * @memberof DevData + * @static + * @param {DevData} message DevData + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + DevData.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.devices = []; + if (message.devices && message.devices.length) { + object.devices = []; + for (let j = 0; j < message.devices.length; ++j) object.devices[j] = $root.Device.toObject(message.devices[j], options); + } + return object; + }; + + /** + * Converts this DevData to JSON. + * @function toJSON + * @memberof DevData + * @instance + * @returns {Object.} JSON object + */ + DevData.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return DevData; +})()); + +export const GpState = ($root.GpState = (() => { + /** + * Properties of a GpState. + * @exports IGpState + * @interface IGpState + * @property {boolean|null} [connected] GpState connected + * @property {number|null} [buttons] GpState buttons + * @property {Array.|null} [axes] GpState axes + */ + + /** + * Constructs a new GpState. + * @exports GpState + * @classdesc Represents a GpState. + * @implements IGpState + * @constructor + * @param {IGpState=} [properties] Properties to set + */ + function GpState(properties) { + this.axes = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * GpState connected. + * @member {boolean} connected + * @memberof GpState + * @instance + */ + GpState.prototype.connected = false; + + /** + * GpState buttons. + * @member {number} buttons + * @memberof GpState + * @instance + */ + GpState.prototype.buttons = 0; + + /** + * GpState axes. + * @member {Array.} axes + * @memberof GpState + * @instance + */ + GpState.prototype.axes = $util.emptyArray; + + /** + * Creates a new GpState instance using the specified properties. + * @function create + * @memberof GpState + * @static + * @param {IGpState=} [properties] Properties to set + * @returns {GpState} GpState instance + */ + GpState.create = function create(properties) { + return new GpState(properties); + }; + + /** + * Encodes the specified GpState message. Does not implicitly {@link GpState.verify|verify} messages. + * @function encode + * @memberof GpState + * @static + * @param {IGpState} message GpState message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GpState.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.connected != null && message.hasOwnProperty('connected')) writer.uint32(/* id 1, wireType 0 =*/ 8).bool(message.connected); + if (message.buttons != null && message.hasOwnProperty('buttons')) writer.uint32(/* id 2, wireType 5 =*/ 21).fixed32(message.buttons); + if (message.axes != null && message.axes.length) { + writer.uint32(/* id 3, wireType 2 =*/ 26).fork(); + for (let i = 0; i < message.axes.length; ++i) writer.float(message.axes[i]); + writer.ldelim(); + } + return writer; + }; + + /** + * Encodes the specified GpState message, length delimited. Does not implicitly {@link GpState.verify|verify} messages. + * @function encodeDelimited + * @memberof GpState + * @static + * @param {IGpState} message GpState message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GpState.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GpState message from the specified reader or buffer. + * @function decode + * @memberof GpState + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {GpState} GpState + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GpState.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.GpState(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.connected = reader.bool(); + break; + case 2: + message.buttons = reader.fixed32(); + break; + case 3: + if (!(message.axes && message.axes.length)) message.axes = []; + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) message.axes.push(reader.float()); + } else message.axes.push(reader.float()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GpState message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof GpState + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {GpState} GpState + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GpState.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GpState message. + * @function verify + * @memberof GpState + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GpState.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.connected != null && message.hasOwnProperty('connected')) + if (typeof message.connected !== 'boolean') return 'connected: boolean expected'; + if (message.buttons != null && message.hasOwnProperty('buttons')) + if (!$util.isInteger(message.buttons)) return 'buttons: integer expected'; + if (message.axes != null && message.hasOwnProperty('axes')) { + if (!Array.isArray(message.axes)) return 'axes: array expected'; + for (let i = 0; i < message.axes.length; ++i) if (typeof message.axes[i] !== 'number') return 'axes: number[] expected'; + } + return null; + }; + + /** + * Creates a GpState message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof GpState + * @static + * @param {Object.} object Plain object + * @returns {GpState} GpState + */ + GpState.fromObject = function fromObject(object) { + if (object instanceof $root.GpState) return object; + let message = new $root.GpState(); + if (object.connected != null) message.connected = Boolean(object.connected); + if (object.buttons != null) message.buttons = object.buttons >>> 0; + if (object.axes) { + if (!Array.isArray(object.axes)) throw TypeError('.GpState.axes: array expected'); + message.axes = []; + for (let i = 0; i < object.axes.length; ++i) message.axes[i] = Number(object.axes[i]); + } + return message; + }; + + /** + * Creates a plain object from a GpState message. Also converts values to other types if specified. + * @function toObject + * @memberof GpState + * @static + * @param {GpState} message GpState + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GpState.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.axes = []; + if (options.defaults) { + object.connected = false; + object.buttons = 0; + } + if (message.connected != null && message.hasOwnProperty('connected')) object.connected = message.connected; + if (message.buttons != null && message.hasOwnProperty('buttons')) object.buttons = message.buttons; + if (message.axes && message.axes.length) { + object.axes = []; + for (let j = 0; j < message.axes.length; ++j) + object.axes[j] = options.json && !isFinite(message.axes[j]) ? String(message.axes[j]) : message.axes[j]; + } + return object; + }; + + /** + * Converts this GpState to JSON. + * @function toJSON + * @memberof GpState + * @instance + * @returns {Object.} JSON object + */ + GpState.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return GpState; +})()); /** * Mode enum. @@ -1055,230 +965,222 @@ export const GpState = $root.GpState = (() => { * @property {number} ESTOP=3 ESTOP value * @property {number} CHALLENGE=4 CHALLENGE value */ -$root.Mode = (function() { - const valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "IDLE"] = 0; - values[valuesById[1] = "AUTO"] = 1; - values[valuesById[2] = "TELEOP"] = 2; - values[valuesById[3] = "ESTOP"] = 3; - values[valuesById[4] = "CHALLENGE"] = 4; - return values; +$root.Mode = (function () { + const valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'IDLE')] = 0; + values[(valuesById[1] = 'AUTO')] = 1; + values[(valuesById[2] = 'TELEOP')] = 2; + values[(valuesById[3] = 'ESTOP')] = 3; + values[(valuesById[4] = 'CHALLENGE')] = 4; + return values; })(); -export const RunMode = $root.RunMode = (() => { - - /** - * Properties of a RunMode. - * @exports IRunMode - * @interface IRunMode - * @property {Mode|null} [mode] RunMode mode - */ - - /** - * Constructs a new RunMode. - * @exports RunMode - * @classdesc Represents a RunMode. - * @implements IRunMode - * @constructor - * @param {IRunMode=} [properties] Properties to set - */ - function RunMode(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; +export const RunMode = ($root.RunMode = (() => { + /** + * Properties of a RunMode. + * @exports IRunMode + * @interface IRunMode + * @property {Mode|null} [mode] RunMode mode + */ + + /** + * Constructs a new RunMode. + * @exports RunMode + * @classdesc Represents a RunMode. + * @implements IRunMode + * @constructor + * @param {IRunMode=} [properties] Properties to set + */ + function RunMode(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * RunMode mode. + * @member {Mode} mode + * @memberof RunMode + * @instance + */ + RunMode.prototype.mode = 0; + + /** + * Creates a new RunMode instance using the specified properties. + * @function create + * @memberof RunMode + * @static + * @param {IRunMode=} [properties] Properties to set + * @returns {RunMode} RunMode instance + */ + RunMode.create = function create(properties) { + return new RunMode(properties); + }; + + /** + * Encodes the specified RunMode message. Does not implicitly {@link RunMode.verify|verify} messages. + * @function encode + * @memberof RunMode + * @static + * @param {IRunMode} message RunMode message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + RunMode.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.mode != null && message.hasOwnProperty('mode')) writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.mode); + return writer; + }; + + /** + * Encodes the specified RunMode message, length delimited. Does not implicitly {@link RunMode.verify|verify} messages. + * @function encodeDelimited + * @memberof RunMode + * @static + * @param {IRunMode} message RunMode message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + RunMode.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a RunMode message from the specified reader or buffer. + * @function decode + * @memberof RunMode + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {RunMode} RunMode + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + RunMode.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.RunMode(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.mode = reader.int32(); + break; + default: + reader.skipType(tag & 7); + break; + } } - - /** - * RunMode mode. - * @member {Mode} mode - * @memberof RunMode - * @instance - */ - RunMode.prototype.mode = 0; - - /** - * Creates a new RunMode instance using the specified properties. - * @function create - * @memberof RunMode - * @static - * @param {IRunMode=} [properties] Properties to set - * @returns {RunMode} RunMode instance - */ - RunMode.create = function create(properties) { - return new RunMode(properties); - }; - - /** - * Encodes the specified RunMode message. Does not implicitly {@link RunMode.verify|verify} messages. - * @function encode - * @memberof RunMode - * @static - * @param {IRunMode} message RunMode message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - RunMode.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.mode != null && message.hasOwnProperty("mode")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.mode); - return writer; - }; - - /** - * Encodes the specified RunMode message, length delimited. Does not implicitly {@link RunMode.verify|verify} messages. - * @function encodeDelimited - * @memberof RunMode - * @static - * @param {IRunMode} message RunMode message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - RunMode.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a RunMode message from the specified reader or buffer. - * @function decode - * @memberof RunMode - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {RunMode} RunMode - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - RunMode.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.RunMode(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.mode = reader.int32(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a RunMode message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof RunMode - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {RunMode} RunMode - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - RunMode.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a RunMode message. - * @function verify - * @memberof RunMode - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - RunMode.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.mode != null && message.hasOwnProperty("mode")) - switch (message.mode) { - default: - return "mode: enum value expected"; - case 0: - case 1: - case 2: - case 3: - case 4: - break; - } - return null; - }; - - /** - * Creates a RunMode message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof RunMode - * @static - * @param {Object.} object Plain object - * @returns {RunMode} RunMode - */ - RunMode.fromObject = function fromObject(object) { - if (object instanceof $root.RunMode) - return object; - let message = new $root.RunMode(); - switch (object.mode) { - case "IDLE": + return message; + }; + + /** + * Decodes a RunMode message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof RunMode + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {RunMode} RunMode + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + RunMode.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a RunMode message. + * @function verify + * @memberof RunMode + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + RunMode.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.mode != null && message.hasOwnProperty('mode')) + switch (message.mode) { + default: + return 'mode: enum value expected'; case 0: - message.mode = 0; - break; - case "AUTO": case 1: - message.mode = 1; - break; - case "TELEOP": case 2: - message.mode = 2; - break; - case "ESTOP": case 3: - message.mode = 3; - break; - case "CHALLENGE": case 4: - message.mode = 4; - break; - } - return message; - }; - - /** - * Creates a plain object from a RunMode message. Also converts values to other types if specified. - * @function toObject - * @memberof RunMode - * @static - * @param {RunMode} message RunMode - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - RunMode.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) - object.mode = options.enums === String ? "IDLE" : 0; - if (message.mode != null && message.hasOwnProperty("mode")) - object.mode = options.enums === String ? $root.Mode[message.mode] : message.mode; - return object; - }; - - /** - * Converts this RunMode to JSON. - * @function toJSON - * @memberof RunMode - * @instance - * @returns {Object.} JSON object - */ - RunMode.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return RunMode; -})(); + break; + } + return null; + }; + + /** + * Creates a RunMode message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof RunMode + * @static + * @param {Object.} object Plain object + * @returns {RunMode} RunMode + */ + RunMode.fromObject = function fromObject(object) { + if (object instanceof $root.RunMode) return object; + let message = new $root.RunMode(); + switch (object.mode) { + case 'IDLE': + case 0: + message.mode = 0; + break; + case 'AUTO': + case 1: + message.mode = 1; + break; + case 'TELEOP': + case 2: + message.mode = 2; + break; + case 'ESTOP': + case 3: + message.mode = 3; + break; + case 'CHALLENGE': + case 4: + message.mode = 4; + break; + } + return message; + }; + + /** + * Creates a plain object from a RunMode message. Also converts values to other types if specified. + * @function toObject + * @memberof RunMode + * @static + * @param {RunMode} message RunMode + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + RunMode.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) object.mode = options.enums === String ? 'IDLE' : 0; + if (message.mode != null && message.hasOwnProperty('mode')) + object.mode = options.enums === String ? $root.Mode[message.mode] : message.mode; + return object; + }; + + /** + * Converts this RunMode to JSON. + * @function toJSON + * @memberof RunMode + * @instance + * @returns {Object.} JSON object + */ + RunMode.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return RunMode; +})()); /** * Pos enum. @@ -1287,414 +1189,389 @@ export const RunMode = $root.RunMode = (() => { * @property {number} LEFT=0 LEFT value * @property {number} RIGHT=1 RIGHT value */ -$root.Pos = (function() { - const valuesById = {}, values = Object.create(valuesById); - values[valuesById[0] = "LEFT"] = 0; - values[valuesById[1] = "RIGHT"] = 1; - return values; +$root.Pos = (function () { + const valuesById = {}, + values = Object.create(valuesById); + values[(valuesById[0] = 'LEFT')] = 0; + values[(valuesById[1] = 'RIGHT')] = 1; + return values; })(); -export const StartPos = $root.StartPos = (() => { - - /** - * Properties of a StartPos. - * @exports IStartPos - * @interface IStartPos - * @property {Pos|null} [pos] StartPos pos - */ - - /** - * Constructs a new StartPos. - * @exports StartPos - * @classdesc Represents a StartPos. - * @implements IStartPos - * @constructor - * @param {IStartPos=} [properties] Properties to set - */ - function StartPos(properties) { - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; +export const StartPos = ($root.StartPos = (() => { + /** + * Properties of a StartPos. + * @exports IStartPos + * @interface IStartPos + * @property {Pos|null} [pos] StartPos pos + */ + + /** + * Constructs a new StartPos. + * @exports StartPos + * @classdesc Represents a StartPos. + * @implements IStartPos + * @constructor + * @param {IStartPos=} [properties] Properties to set + */ + function StartPos(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * StartPos pos. + * @member {Pos} pos + * @memberof StartPos + * @instance + */ + StartPos.prototype.pos = 0; + + /** + * Creates a new StartPos instance using the specified properties. + * @function create + * @memberof StartPos + * @static + * @param {IStartPos=} [properties] Properties to set + * @returns {StartPos} StartPos instance + */ + StartPos.create = function create(properties) { + return new StartPos(properties); + }; + + /** + * Encodes the specified StartPos message. Does not implicitly {@link StartPos.verify|verify} messages. + * @function encode + * @memberof StartPos + * @static + * @param {IStartPos} message StartPos message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StartPos.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.pos != null && message.hasOwnProperty('pos')) writer.uint32(/* id 1, wireType 0 =*/ 8).int32(message.pos); + return writer; + }; + + /** + * Encodes the specified StartPos message, length delimited. Does not implicitly {@link StartPos.verify|verify} messages. + * @function encodeDelimited + * @memberof StartPos + * @static + * @param {IStartPos} message StartPos message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + StartPos.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a StartPos message from the specified reader or buffer. + * @function decode + * @memberof StartPos + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {StartPos} StartPos + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StartPos.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.StartPos(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.pos = reader.int32(); + break; + default: + reader.skipType(tag & 7); + break; + } } - - /** - * StartPos pos. - * @member {Pos} pos - * @memberof StartPos - * @instance - */ - StartPos.prototype.pos = 0; - - /** - * Creates a new StartPos instance using the specified properties. - * @function create - * @memberof StartPos - * @static - * @param {IStartPos=} [properties] Properties to set - * @returns {StartPos} StartPos instance - */ - StartPos.create = function create(properties) { - return new StartPos(properties); - }; - - /** - * Encodes the specified StartPos message. Does not implicitly {@link StartPos.verify|verify} messages. - * @function encode - * @memberof StartPos - * @static - * @param {IStartPos} message StartPos message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - StartPos.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.pos != null && message.hasOwnProperty("pos")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.pos); - return writer; - }; - - /** - * Encodes the specified StartPos message, length delimited. Does not implicitly {@link StartPos.verify|verify} messages. - * @function encodeDelimited - * @memberof StartPos - * @static - * @param {IStartPos} message StartPos message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - StartPos.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a StartPos message from the specified reader or buffer. - * @function decode - * @memberof StartPos - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {StartPos} StartPos - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - StartPos.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.StartPos(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.pos = reader.int32(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a StartPos message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof StartPos - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {StartPos} StartPos - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - StartPos.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a StartPos message. - * @function verify - * @memberof StartPos - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - StartPos.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.pos != null && message.hasOwnProperty("pos")) - switch (message.pos) { - default: - return "pos: enum value expected"; - case 0: - case 1: - break; - } - return null; - }; - - /** - * Creates a StartPos message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof StartPos - * @static - * @param {Object.} object Plain object - * @returns {StartPos} StartPos - */ - StartPos.fromObject = function fromObject(object) { - if (object instanceof $root.StartPos) - return object; - let message = new $root.StartPos(); - switch (object.pos) { - case "LEFT": + return message; + }; + + /** + * Decodes a StartPos message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof StartPos + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {StartPos} StartPos + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + StartPos.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a StartPos message. + * @function verify + * @memberof StartPos + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + StartPos.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.pos != null && message.hasOwnProperty('pos')) + switch (message.pos) { + default: + return 'pos: enum value expected'; case 0: - message.pos = 0; - break; - case "RIGHT": case 1: - message.pos = 1; - break; - } - return message; - }; - - /** - * Creates a plain object from a StartPos message. Also converts values to other types if specified. - * @function toObject - * @memberof StartPos - * @static - * @param {StartPos} message StartPos - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - StartPos.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.defaults) - object.pos = options.enums === String ? "LEFT" : 0; - if (message.pos != null && message.hasOwnProperty("pos")) - object.pos = options.enums === String ? $root.Pos[message.pos] : message.pos; - return object; - }; - - /** - * Converts this StartPos to JSON. - * @function toJSON - * @memberof StartPos - * @instance - * @returns {Object.} JSON object - */ - StartPos.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return StartPos; -})(); - -export const Text = $root.Text = (() => { - - /** - * Properties of a Text. - * @exports IText - * @interface IText - * @property {Array.|null} [payload] Text payload - */ - - /** - * Constructs a new Text. - * @exports Text - * @classdesc Represents a Text. - * @implements IText - * @constructor - * @param {IText=} [properties] Properties to set - */ - function Text(properties) { - this.payload = []; - if (properties) - for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; + break; + } + return null; + }; + + /** + * Creates a StartPos message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof StartPos + * @static + * @param {Object.} object Plain object + * @returns {StartPos} StartPos + */ + StartPos.fromObject = function fromObject(object) { + if (object instanceof $root.StartPos) return object; + let message = new $root.StartPos(); + switch (object.pos) { + case 'LEFT': + case 0: + message.pos = 0; + break; + case 'RIGHT': + case 1: + message.pos = 1; + break; } - - /** - * Text payload. - * @member {Array.} payload - * @memberof Text - * @instance - */ - Text.prototype.payload = $util.emptyArray; - - /** - * Creates a new Text instance using the specified properties. - * @function create - * @memberof Text - * @static - * @param {IText=} [properties] Properties to set - * @returns {Text} Text instance - */ - Text.create = function create(properties) { - return new Text(properties); - }; - - /** - * Encodes the specified Text message. Does not implicitly {@link Text.verify|verify} messages. - * @function encode - * @memberof Text - * @static - * @param {IText} message Text message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Text.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.payload != null && message.payload.length) - for (let i = 0; i < message.payload.length; ++i) - writer.uint32(/* id 1, wireType 2 =*/10).string(message.payload[i]); - return writer; - }; - - /** - * Encodes the specified Text message, length delimited. Does not implicitly {@link Text.verify|verify} messages. - * @function encodeDelimited - * @memberof Text - * @static - * @param {IText} message Text message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - Text.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a Text message from the specified reader or buffer. - * @function decode - * @memberof Text - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {Text} Text - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Text.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.Text(); - while (reader.pos < end) { - let tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (!(message.payload && message.payload.length)) - message.payload = []; - message.payload.push(reader.string()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a Text message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof Text - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {Text} Text - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - Text.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a Text message. - * @function verify - * @memberof Text - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - Text.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.payload != null && message.hasOwnProperty("payload")) { - if (!Array.isArray(message.payload)) - return "payload: array expected"; - for (let i = 0; i < message.payload.length; ++i) - if (!$util.isString(message.payload[i])) - return "payload: string[] expected"; - } - return null; - }; - - /** - * Creates a Text message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof Text - * @static - * @param {Object.} object Plain object - * @returns {Text} Text - */ - Text.fromObject = function fromObject(object) { - if (object instanceof $root.Text) - return object; - let message = new $root.Text(); - if (object.payload) { - if (!Array.isArray(object.payload)) - throw TypeError(".Text.payload: array expected"); - message.payload = []; - for (let i = 0; i < object.payload.length; ++i) - message.payload[i] = String(object.payload[i]); - } - return message; - }; - - /** - * Creates a plain object from a Text message. Also converts values to other types if specified. - * @function toObject - * @memberof Text - * @static - * @param {Text} message Text - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - Text.toObject = function toObject(message, options) { - if (!options) - options = {}; - let object = {}; - if (options.arrays || options.defaults) - object.payload = []; - if (message.payload && message.payload.length) { - object.payload = []; - for (let j = 0; j < message.payload.length; ++j) - object.payload[j] = message.payload[j]; - } - return object; - }; - - /** - * Converts this Text to JSON. - * @function toJSON - * @memberof Text - * @instance - * @returns {Object.} JSON object - */ - Text.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return Text; -})(); + return message; + }; + + /** + * Creates a plain object from a StartPos message. Also converts values to other types if specified. + * @function toObject + * @memberof StartPos + * @static + * @param {StartPos} message StartPos + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + StartPos.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.defaults) object.pos = options.enums === String ? 'LEFT' : 0; + if (message.pos != null && message.hasOwnProperty('pos')) object.pos = options.enums === String ? $root.Pos[message.pos] : message.pos; + return object; + }; + + /** + * Converts this StartPos to JSON. + * @function toJSON + * @memberof StartPos + * @instance + * @returns {Object.} JSON object + */ + StartPos.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return StartPos; +})()); + +export const Text = ($root.Text = (() => { + /** + * Properties of a Text. + * @exports IText + * @interface IText + * @property {Array.|null} [payload] Text payload + */ + + /** + * Constructs a new Text. + * @exports Text + * @classdesc Represents a Text. + * @implements IText + * @constructor + * @param {IText=} [properties] Properties to set + */ + function Text(properties) { + this.payload = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + /** + * Text payload. + * @member {Array.} payload + * @memberof Text + * @instance + */ + Text.prototype.payload = $util.emptyArray; + + /** + * Creates a new Text instance using the specified properties. + * @function create + * @memberof Text + * @static + * @param {IText=} [properties] Properties to set + * @returns {Text} Text instance + */ + Text.create = function create(properties) { + return new Text(properties); + }; + + /** + * Encodes the specified Text message. Does not implicitly {@link Text.verify|verify} messages. + * @function encode + * @memberof Text + * @static + * @param {IText} message Text message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Text.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.payload != null && message.payload.length) + for (let i = 0; i < message.payload.length; ++i) writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.payload[i]); + return writer; + }; + + /** + * Encodes the specified Text message, length delimited. Does not implicitly {@link Text.verify|verify} messages. + * @function encodeDelimited + * @memberof Text + * @static + * @param {IText} message Text message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Text.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Text message from the specified reader or buffer. + * @function decode + * @memberof Text + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {Text} Text + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Text.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Text(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (!(message.payload && message.payload.length)) message.payload = []; + message.payload.push(reader.string()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Text message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof Text + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {Text} Text + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Text.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Text message. + * @function verify + * @memberof Text + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Text.verify = function verify(message) { + if (typeof message !== 'object' || message === null) return 'object expected'; + if (message.payload != null && message.hasOwnProperty('payload')) { + if (!Array.isArray(message.payload)) return 'payload: array expected'; + for (let i = 0; i < message.payload.length; ++i) if (!$util.isString(message.payload[i])) return 'payload: string[] expected'; + } + return null; + }; + + /** + * Creates a Text message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Text + * @static + * @param {Object.} object Plain object + * @returns {Text} Text + */ + Text.fromObject = function fromObject(object) { + if (object instanceof $root.Text) return object; + let message = new $root.Text(); + if (object.payload) { + if (!Array.isArray(object.payload)) throw TypeError('.Text.payload: array expected'); + message.payload = []; + for (let i = 0; i < object.payload.length; ++i) message.payload[i] = String(object.payload[i]); + } + return message; + }; + + /** + * Creates a plain object from a Text message. Also converts values to other types if specified. + * @function toObject + * @memberof Text + * @static + * @param {Text} message Text + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Text.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.payload = []; + if (message.payload && message.payload.length) { + object.payload = []; + for (let j = 0; j < message.payload.length; ++j) object.payload[j] = message.payload[j]; + } + return object; + }; + + /** + * Converts this Text to JSON. + * @function toJSON + * @memberof Text + * @instance + * @returns {Object.} JSON object + */ + Text.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Text; +})()); export { $root as default }; diff --git a/release.ts b/release.ts index 49d4941f..bf776c20 100644 --- a/release.ts +++ b/release.ts @@ -12,7 +12,7 @@ async function pack(platform: string, arch: string) { name: 'dawn', icon: './icons/pieicon', asar: true, - out: path.resolve('..'), // build in the parent dir + out: path.resolve('..') // build in the parent dir }; if (!platform || !arch) { @@ -26,15 +26,17 @@ async function pack(platform: string, arch: string) { const appPaths: string[] = await packager(packageOptions); - Promise.all(appPaths.map((appPath: string) => { - console.log(`Zipping ${appPath}`); - - return new Promise((resolve) => { - exec(`cd .. && zip -r ${appPath}.zip ${path.basename(appPath)}`, (err, stdout, stderr) => { - resolve(err ? stdout : stderr); - }) + Promise.all( + appPaths.map((appPath: string) => { + console.log(`Zipping ${appPath}`); + + return new Promise((resolve) => { + exec(`cd .. && zip -r ${appPath}.zip ${path.basename(appPath)}`, (err, stdout, stderr) => { + resolve(err ? stdout : stderr); + }); + }); }) - })); + ); } async function main() { diff --git a/renderer/actions/AlertActions.ts b/renderer/actions/AlertActions.ts index 7f90714e..cd4b2399 100644 --- a/renderer/actions/AlertActions.ts +++ b/renderer/actions/AlertActions.ts @@ -11,10 +11,10 @@ export const addAsyncAlert: AlertActions['addAsyncAlert'] = (heading: string, me type: consts.AlertActionsTypes.ADD_ASYNC_ALERT, id: rng.int32(), heading, - message, + message }); export const removeAsyncAlert: AlertActions['removeAsyncAlert'] = (id: number) => ({ type: consts.AlertActionsTypes.REMOVE_ASYNC_ALERT, - id, + id }); diff --git a/renderer/actions/ConsoleActions.ts b/renderer/actions/ConsoleActions.ts index a742f81b..6447778e 100644 --- a/renderer/actions/ConsoleActions.ts +++ b/renderer/actions/ConsoleActions.ts @@ -6,13 +6,13 @@ import { ConsoleActions } from '../types'; export const updateConsole: ConsoleActions['updateConsole'] = (value: string[]) => ({ type: consts.ConsoleActionsTypes.UPDATE_CONSOLE, - consoleOutput: value, + consoleOutput: value }); export const clearConsole: ConsoleActions['clearConsole'] = () => ({ - type: consts.ConsoleActionsTypes.CLEAR_CONSOLE, + type: consts.ConsoleActionsTypes.CLEAR_CONSOLE }); export const toggleConsole: ConsoleActions['toggleConsole'] = () => ({ - type: consts.ConsoleActionsTypes.TOGGLE_CONSOLE, + type: consts.ConsoleActionsTypes.TOGGLE_CONSOLE }); diff --git a/renderer/actions/EditorActions.ts b/renderer/actions/EditorActions.ts index dabbb225..bf04efe1 100644 --- a/renderer/actions/EditorActions.ts +++ b/renderer/actions/EditorActions.ts @@ -3,47 +3,47 @@ import { EditorActions } from '../types'; export const editorUpdate: EditorActions['editorUpdate'] = (newVal: string) => ({ type: consts.EditorActionsTypes.UPDATE_EDITOR, - code: newVal, + code: newVal }); export const openFileSucceeded: EditorActions['openFileSucceeded'] = (data: string, filepath: string) => ({ type: consts.EditorActionsTypes.OPEN_FILE_SUCCEEDED, code: data, - filepath, + filepath }); export const saveFileSucceeded: EditorActions['saveFileSucceeded'] = (data: string, filepath: string) => ({ type: consts.EditorActionsTypes.SAVE_FILE_SUCCEEDED, code: data, - filepath, + filepath }); export const openFile: EditorActions['openFile'] = () => ({ - type: consts.EditorActionsTypes.OPEN_FILE, + type: consts.EditorActionsTypes.OPEN_FILE }); export const dragFile: EditorActions['dragFile'] = (filepath: string) => ({ type: consts.EditorActionsTypes.DRAG_FILE, - filepath, + filepath }); export const saveFile: EditorActions['saveFile'] = (saveAs = false) => ({ type: consts.EditorActionsTypes.SAVE_FILE, - saveAs, + saveAs }); export const deleteFile: EditorActions['deleteFile'] = () => ({ - type: consts.EditorActionsTypes.DELETE_FILE, + type: consts.EditorActionsTypes.DELETE_FILE }); export const createNewFile: EditorActions['createNewFile'] = () => ({ - type: consts.EditorActionsTypes.CREATE_NEW_FILE, + type: consts.EditorActionsTypes.CREATE_NEW_FILE }); export const downloadCode: EditorActions['downloadCode'] = () => ({ - type: consts.EditorActionsTypes.DOWNLOAD_CODE, + type: consts.EditorActionsTypes.DOWNLOAD_CODE }); export const uploadCode: EditorActions['uploadCode'] = () => ({ - type: consts.EditorActionsTypes.UPLOAD_CODE, + type: consts.EditorActionsTypes.UPLOAD_CODE }); diff --git a/renderer/actions/FieldActions.ts b/renderer/actions/FieldActions.ts index 9c22eda9..06e8c1d8 100644 --- a/renderer/actions/FieldActions.ts +++ b/renderer/actions/FieldActions.ts @@ -9,39 +9,39 @@ export const updateTimer: FieldActions['updateTimer'] = (msg: { type: consts.FieldActionsTypes.UPDATE_TIMER, timeLeft: msg.total_stage_time - msg.stage_time_so_far, stage: msg.stage_name, - totalTime: msg.total_stage_time, + totalTime: msg.total_stage_time }); export const updateHeart: FieldActions['updateHeart'] = () => ({ - type: consts.FieldActionsTypes.UPDATE_HEART, + type: consts.FieldActionsTypes.UPDATE_HEART }); export const updateMaster: FieldActions['updateMaster'] = (msg: { blue: number; gold: number }) => ({ type: consts.FieldActionsTypes.UPDATE_MASTER, blueMasterTeamNumber: msg.blue, - goldMasterTeamNumber: msg.gold, + goldMasterTeamNumber: msg.gold }); export const updateMatch: FieldActions['updateMatch'] = (msg: { match_number: number; team_names: string[]; team_numbers: number[] }) => ({ type: consts.FieldActionsTypes.UPDATE_MATCH, matchNumber: msg.match_number, teamNames: msg.team_names, - teamNumbers: msg.team_numbers, + teamNumbers: msg.team_numbers }); export const updateRobot: FieldActions['updateRobot'] = (msg: { autonomous: number; enabled: boolean }) => ({ type: consts.FieldActionsTypes.UPDATE_ROBOT, autonomous: msg.autonomous, - enabled: msg.enabled, + enabled: msg.enabled }); export const toggleFieldControl: FieldActions['toggleFieldControl'] = (msg: boolean) => ({ type: consts.FieldActionsTypes.FIELD_CONTROL, - fieldControl: msg, + fieldControl: msg }); export const updateFieldControl: FieldActions['updateFieldControl'] = (msg: { stationNumber: number; bridgeAddress: string }) => ({ type: consts.FieldActionsTypes.UPDATE_FC_CONFIG, stationNumber: msg.stationNumber, - bridgeAddress: msg.bridgeAddress, + bridgeAddress: msg.bridgeAddress }); diff --git a/renderer/actions/GamepadsActions.ts b/renderer/actions/GamepadsActions.ts index f72a6871..847d1640 100644 --- a/renderer/actions/GamepadsActions.ts +++ b/renderer/actions/GamepadsActions.ts @@ -5,5 +5,5 @@ import { GpState } from '../../protos/protos'; export const updateGamepads: GamepadsActions['updateGamepads'] = (gamepads: GpState[]) => ({ type: consts.GamepadsActionsTypes.UPDATE_GAMEPADS, - gamepads, + gamepads }); diff --git a/renderer/actions/InfoActions.ts b/renderer/actions/InfoActions.ts index 6220801b..abd74be4 100644 --- a/renderer/actions/InfoActions.ts +++ b/renderer/actions/InfoActions.ts @@ -2,27 +2,27 @@ import * as consts from '../consts'; import { InfoActions } from '../types'; export const infoPerMessage: InfoActions['infoPerMessage'] = () => ({ - type: consts.InfoActionsTypes.PER_MESSAGE, + type: consts.InfoActionsTypes.PER_MESSAGE }); export const runtimeConnect: InfoActions['runtimeConnect'] = () => ({ - type: consts.InfoActionsTypes.RUNTIME_CONNECT, + type: consts.InfoActionsTypes.RUNTIME_CONNECT }); export const runtimeDisconnect: InfoActions['runtimeDisconnect'] = () => ({ - type: consts.InfoActionsTypes.RUNTIME_DISCONNECT, + type: consts.InfoActionsTypes.RUNTIME_DISCONNECT }); export const masterStatus: InfoActions['masterStatus'] = () => ({ - type: consts.InfoActionsTypes.MASTER_ROBOT, + type: consts.InfoActionsTypes.MASTER_ROBOT }); export const updateCodeStatus: InfoActions['updateCodeStatus'] = (studentCodeStatus: number) => ({ type: consts.InfoActionsTypes.CODE_STATUS, - studentCodeStatus, + studentCodeStatus }); export const ipChange: InfoActions['ipChange'] = (ipAddress: string) => ({ type: consts.InfoActionsTypes.IP_CHANGE, - ipAddress, + ipAddress }); diff --git a/renderer/actions/PeripheralActions.ts b/renderer/actions/PeripheralActions.ts index 101404f5..e13e9a96 100644 --- a/renderer/actions/PeripheralActions.ts +++ b/renderer/actions/PeripheralActions.ts @@ -4,11 +4,11 @@ import { Device } from '../../protos/protos'; export const updatePeripherals: PeripheralActions['updatePeripherals'] = (sensors: Device[]) => ({ type: consts.PeripheralActionsTypes.UPDATE_PERIPHERALS, - peripherals: sensors, + peripherals: sensors }); export const peripheralRename: PeripheralActions['peripheralRename'] = (uid: number, newName: string) => ({ type: consts.PeripheralActionsTypes.PERIPHERAL_RENAME, id: uid, - name: newName, + name: newName }); diff --git a/renderer/actions/SettingsActions.ts b/renderer/actions/SettingsActions.ts index 887289ea..8855916b 100644 --- a/renderer/actions/SettingsActions.ts +++ b/renderer/actions/SettingsActions.ts @@ -3,10 +3,10 @@ import { SettingsActions } from '../types'; export const changeFontSize: SettingsActions['changeFontSize'] = (newFontSize: number) => ({ type: consts.SettingsActionsTypes.CHANGE_FONT_SIZE, - newFontSize, + newFontSize }); export const changeTheme: SettingsActions['changeTheme'] = (theme: string) => ({ type: consts.SettingsActionsTypes.CHANGE_THEME, - theme, + theme }); diff --git a/renderer/actions/test/AlertActions.test.js b/renderer/actions/test/AlertActions.test.js index 916ad5e8..8f469293 100644 --- a/renderer/actions/test/AlertActions.test.js +++ b/renderer/actions/test/AlertActions.test.js @@ -2,7 +2,6 @@ import seedrandom from 'seedrandom'; import { expect } from 'chai'; import { addAsyncAlert, removeAsyncAlert } from '../AlertActions'; - describe('alerts action creator', () => { // Needs to be using the same seed as the action creator. const rng = seedrandom('alertseed'); diff --git a/renderer/actions/test/ConsoleActions.test.js b/renderer/actions/test/ConsoleActions.test.js index 77ede41b..9fa0a9e4 100644 --- a/renderer/actions/test/ConsoleActions.test.js +++ b/renderer/actions/test/ConsoleActions.test.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import { toggleConsole, updateConsole, clearConsole } from '../ConsoleActions'; - describe('console actions creator', () => { it('should create an action to update console', () => { const expectedAction = { diff --git a/renderer/actions/test/EditorActions.test.js b/renderer/actions/test/EditorActions.test.js index 82dfa449..f613885b 100644 --- a/renderer/actions/test/EditorActions.test.js +++ b/renderer/actions/test/EditorActions.test.js @@ -1,12 +1,5 @@ import { expect } from 'chai'; -import { - openFile, - saveFile, - deleteFile, - createNewFile, - editorUpdate, -} from '../EditorActions'; - +import { openFile, saveFile, deleteFile, createNewFile, editorUpdate } from '../EditorActions'; describe('editor actions creator', () => { it('should create an action to open file', () => { diff --git a/renderer/components/App.tsx b/renderer/components/App.tsx index c8aed043..2bc80dda 100644 --- a/renderer/components/App.tsx +++ b/renderer/components/App.tsx @@ -11,24 +11,18 @@ import { joyrideSteps } from './JoyrideSteps'; import { removeAsyncAlert } from '../actions/AlertActions'; import { updateFieldControl } from '../actions/FieldActions'; import { logging, startLog } from '../utils/utils'; -import { FieldControlConfig } from '../types'; +import { AlertType, FieldControlConfig } from '../types'; type ElectronJSONStorage = typeof electronJSONStorage; const storage = remote.require('electron-json-storage') as ElectronJSONStorage; -interface AlertType { - heading: string; - message: string; - id: number; -} - interface StateProps { connectionStatus: boolean; runtimeStatus: boolean; masterStatus: boolean; isRunningCode: boolean; - asyncAlerts: Array; + asyncAlerts: Array; } interface DispatchProps { @@ -50,7 +44,7 @@ class AppComponent extends React.Component { super(props); this.state = { steps: [], - tourRunning: false, + tourRunning: false }; startLog(); } @@ -90,7 +84,7 @@ class AppComponent extends React.Component { const { asyncAlerts } = nextProps; // If the alerts list has changed, display the latest one. if (asyncAlerts !== this.props.asyncAlerts) { - const latestAlert = asyncAlerts[asyncAlerts.length - 1] as AlertType; + const latestAlert = asyncAlerts[asyncAlerts.length - 1]; if (latestAlert !== undefined) { this.updateAlert(latestAlert); } @@ -126,12 +120,12 @@ class AppComponent extends React.Component { }; updateAlert = (latestAlert: AlertType) => { - smalltalk.alert(latestAlert.heading, latestAlert.message).then( + smalltalk.alert(latestAlert.heading ?? 'General', latestAlert.message ?? '').then( () => { - this.props.onAlertDone(latestAlert.id); + this.props.onAlertDone(latestAlert?.id ?? 0); }, () => { - this.props.onAlertDone(latestAlert.id); + this.props.onAlertDone(latestAlert?.id ?? 0); } ); }; @@ -150,9 +144,6 @@ class AppComponent extends React.Component { isRunningCode={isRunningCode} /> { - this.joyride = c; - }} steps={this.state.steps} continuous={true} showSkipButton @@ -163,7 +154,7 @@ class AppComponent extends React.Component { close: 'Close', last: 'End Tour', next: 'Next', - skip: 'Skip Tour', + skip: 'Skip Tour' }} />
@@ -185,7 +176,7 @@ const mapStateToProps = (state: ApplicationState) => ({ masterStatus: state.fieldStore.masterStatus, asyncAlerts: state.asyncAlerts, stationNumber: state.fieldStore.stationNumber, - isRunningCode: state.info.isRunningCode, + isRunningCode: state.info.isRunningCode }); const mapDispatchToProps = (dispatch: Dispatch) => ({ @@ -194,7 +185,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ }, onFCUpdate: (param: FieldControlConfig) => { dispatch(updateFieldControl(param)); - }, + } }); export const App = connect(mapStateToProps, mapDispatchToProps)(AppComponent); diff --git a/renderer/components/ConfigBox.tsx b/renderer/components/ConfigBox.tsx index 1d6421e8..e1d280b9 100644 --- a/renderer/components/ConfigBox.tsx +++ b/renderer/components/ConfigBox.tsx @@ -51,7 +51,7 @@ class ConfigBoxComponent extends React.Component { stationNumber: this.props.stationNumber, originalIPAddress: this.props.ipAddress, originalStationNumber: this.props.stationNumber, - originalFCAddress: this.props.fcAddress, + originalFCAddress: this.props.fcAddress }; } @@ -66,7 +66,7 @@ class ConfigBoxComponent extends React.Component { this.props.onIPChange(ipAddress); this.setState({ ipAddress: ipAddress, - originalIPAddress: ipAddress, + originalIPAddress: ipAddress }); } }); @@ -81,7 +81,7 @@ class ConfigBoxComponent extends React.Component { fcAddress: bridgeAddress, originalFCAddress: bridgeAddress, stationNumber: stationNumber, - originalStationNumber: stationNumber, + originalStationNumber: stationNumber }); } }); @@ -100,12 +100,12 @@ class ConfigBoxComponent extends React.Component { const newConfig = { stationNumber: this.state.stationNumber, - bridgeAddress: this.state.fcAddress, + bridgeAddress: this.state.fcAddress }; this.props.onFCUpdate(newConfig); this.setState({ originalStationNumber: this.state.stationNumber, - originalFCAddress: this.state.fcAddress, + originalFCAddress: this.state.fcAddress }); storage.set('fieldControl', newConfig, (err: any) => { if (err) logging.log(err); @@ -119,7 +119,7 @@ class ConfigBoxComponent extends React.Component { this.setState({ ipAddress: e.currentTarget.value }); }; - handleFcChange = (e: React.FormEvent) => { + handleFcChange = (e: React.FormEvent) => { this.setState({ fcAddress: e.currentTarget.value }); }; @@ -131,7 +131,7 @@ class ConfigBoxComponent extends React.Component { this.setState({ ipAddress: this.state.originalIPAddress, stationNumber: this.state.originalStationNumber, - fcAddress: this.state.originalFCAddress, + fcAddress: this.state.originalFCAddress }); this.props.hide(); }; @@ -195,12 +195,12 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ }, onFCUpdate: (config: Config) => { dispatch(updateFieldControl(config)); - }, + } }); const mapStateToProps = (state: ApplicationState) => ({ stationNumber: state.fieldStore.stationNumber, - fcAddress: state.fieldStore.bridgeAddress, + fcAddress: state.fieldStore.bridgeAddress }); export const ConfigBox = connect(mapStateToProps, mapDispatchToProps)(ConfigBoxComponent); diff --git a/renderer/components/ConsoleOutput.tsx b/renderer/components/ConsoleOutput.tsx index 92c86a25..765473ea 100644 --- a/renderer/components/ConsoleOutput.tsx +++ b/renderer/components/ConsoleOutput.tsx @@ -8,7 +8,7 @@ interface StateProps { interface OwnProps { height: number; - output: Array + output: string[]; show: boolean; } @@ -22,17 +22,17 @@ export class ConsoleOutput extends React.Component { componentDidMount = () => { this.scrollToBottom(); - } + }; componentWillReceiveProps = (nextProps: Props) => { if (this.props.output.length === 0 && nextProps.output.length > 0 && !this.props.show) { this.props.toggleConsole(); } - } + }; componentDidUpdate = () => { this.scrollToBottom(); - } + }; scrollToBottom = () => { if (!this.props.disableScroll) { @@ -40,8 +40,7 @@ export class ConsoleOutput extends React.Component { this.outerDiv.scrollTop = this.outerDiv.scrollHeight; } } - } - + }; render() { const { show, output } = this.props; @@ -53,7 +52,7 @@ export class ConsoleOutput extends React.Component { style={{ display: show ? 'block' : 'none', marginBottom: '0', - borderRadius: '0', + borderRadius: '0' }} > @@ -61,7 +60,7 @@ export class ConsoleOutput extends React.Component { style={{ position: 'relative', margin: '0', - height, + height }} >
{ maxHeight: height, overflowY: 'auto', padding: '20px', - width: '99%', + width: '99%' + }} + ref={(el) => { + this.outerDiv = el; }} - ref={(el) => { this.outerDiv = el; }} > - {output.map(line => ( + {output.map((line) => ( {line} ))}
diff --git a/renderer/components/DNav.tsx b/renderer/components/DNav.tsx index 9d2f46ed..7f48463b 100644 --- a/renderer/components/DNav.tsx +++ b/renderer/components/DNav.tsx @@ -39,36 +39,37 @@ class DNavComponent extends React.Component { super(props); this.state = { showUpdateModal: false, - showConfigModal: false, + showConfigModal: false }; } toggleUpdateModal = () => { this.setState({ showUpdateModal: !this.state.showUpdateModal }); - } + }; toggleConfigModal = () => { this.setState({ showConfigModal: !this.state.showConfigModal }); - } + }; createHeader = () => { if (this.props.fieldControlStatus) { - return `Dawn FC v${VERSION} ${(this.props.heart) ? '+' : '-'}`; + return `Dawn FC v${VERSION} ${this.props.heart ? '+' : '-'}`; } return `Dawn v${VERSION}`; - } + }; createMaster = () => { if (this.props.fieldControlStatus) { return this.props.masterStatus; } return false; - } + }; render() { - const { connectionStatus, - runtimeStatus, - masterStatus, + const { + connectionStatus, + runtimeStatus, + masterStatus, isRunningCode, ipAddress, runtimeVersion, @@ -76,9 +77,10 @@ class DNavComponent extends React.Component { blueMasterTeamNumber, goldMasterTeamNumber, fieldControlStatus, - startTour } = this.props; + startTour + } = this.props; const { showConfigModal, showUpdateModal } = this.state; - + return ( { ipAddress={ipAddress} hide={this.toggleUpdateModal} /> - + - - {this.createHeader()} - + {this.createHeader()} - {runtimeStatus ? + {runtimeStatus ? ( - - : '' - } + + + ) : ( + '' + )} { fieldControlStatus={fieldControlStatus} /> - + ({ heart: state.fieldStore.heart, ipAddress: state.info.ipAddress, fieldControlStatus: state.fieldStore.fieldControl, - runtimeVersion: state.peripherals.runtimeVersion, + runtimeVersion: state.peripherals.runtimeVersion }); - export const DNav = connect(mapStateToProps)(DNavComponent); diff --git a/renderer/components/Dashboard.tsx b/renderer/components/Dashboard.tsx index 41627024..c90fb5b7 100644 --- a/renderer/components/Dashboard.tsx +++ b/renderer/components/Dashboard.tsx @@ -16,17 +16,11 @@ export const Dashboard = (props: StateProps) => ( - + - + diff --git a/renderer/components/Editor.tsx b/renderer/components/Editor.tsx index 0331bc9b..3d90e375 100644 --- a/renderer/components/Editor.tsx +++ b/renderer/components/Editor.tsx @@ -10,14 +10,14 @@ import { InputGroup, OverlayTrigger, Tooltip, + FormControlProps } from 'react-bootstrap'; import AceEditor from 'react-ace'; -import { Ace } from 'ace-builds' +import { Ace } from 'ace-builds'; import { remote, clipboard } from 'electron'; import storage from 'electron-json-storage'; import _ from 'lodash'; - // React-ace extensions and modes import 'ace-builds/src-noconflict/ext-language_tools'; import 'ace-builds/src-noconflict/ext-searchbox'; @@ -43,7 +43,7 @@ const currentWindow = remote.getCurrentWindow(); interface StateProps { editorTheme: string; - editorCode: string; + editorCode: string; latestSaveCode: string; filepath: string; fontSize: number; @@ -60,11 +60,11 @@ interface OwnProps { onAlertAdd: (heading: string, message: string) => void; onEditorUpdate: (newVal: string) => void; onSaveFile: (saveAs?: boolean) => void; - onDragFile: (filepath: string) => void; - onOpenFile: () => void; + onDragFile: (filepath: string) => void; + onOpenFile: () => void; onCreateNewFile: () => void; onChangeTheme: (theme: string) => void; - onChangeFontsize: (newFontsize: number) => void; + onChangeFontsize: (newFontsize: number) => void; toggleConsole: () => void; onClearConsole: () => void; onUpdateCodeStatus: (status: number) => void; @@ -81,7 +81,7 @@ interface State { modeDisplay: string; simulate: boolean; fontsize?: number; -}; +} export class Editor extends React.Component { themes: string[]; @@ -115,14 +115,14 @@ export class Editor extends React.Component { 'textmate', 'solarized_dark', 'solarized_light', - 'terminal', + 'terminal' ]; this.state = { consoleHeight: windowInfo.CONSOLESTART, editorHeight: 0, // Filled in later during componentDidMount mode: robotState.TELEOP, modeDisplay: robotState.TELEOPSTR, - simulate: false, + simulate: false }; } @@ -132,7 +132,7 @@ export class Editor extends React.Component { componentDidMount = () => { this.CodeEditor.editor.setOptions({ enableBasicAutocompletion: true, - enableLiveAutocompletion: true, + enableLiveAutocompletion: true }); const autoComplete = { getCompletions(_editor: Ace.Editor, _session: Ace.EditSession, _pos: Ace.Point, _prefix: string, callback: Ace.CompleterCallback) { @@ -176,9 +176,9 @@ export class Editor extends React.Component { { value: 'abs', score: 1000, meta: 'Python3' }, { value: 'len', score: 1000, meta: 'Python3' }, { value: 'round', score: 1000, meta: 'Python3' }, - { value: 'set()', score: 1000, meta: 'Python3' }, + { value: 'set()', score: 1000, meta: 'Python3' } ]); - }, + } }; this.CodeEditor.editor.completers = [autoComplete]; @@ -204,116 +204,107 @@ export class Editor extends React.Component { window.addEventListener('beforeunload', this.beforeUnload); window.addEventListener('resize', this.onWindowResize, { passive: true }); - window.addEventListener('dragover', (e: any) => { - e.preventDefault(); + window.addEventListener('dragover', (event: Event) => { + event.preventDefault(); return false; }); - window.addEventListener('drop', (e: any) => { - e.preventDefault(); - this.props.onDragFile(e.dataTransfer.files[0].path); + window.addEventListener('drop', (dragEvent: DragEvent) => { + dragEvent.preventDefault(); + this.props.onDragFile(dragEvent.dataTransfer?.files[0].path ?? ''); return false; }); - } + }; componentWillUnmount = () => { window.removeEventListener('beforeunload', this.beforeUnload); window.removeEventListener('resize', this.onWindowResize); - } + }; onWindowResize = () => { // Trigger editor to re-render on window resizing. this.setState({ editorHeight: this.getEditorHeight() }); - } + }; getEditorHeight = () => { - const windowNonEditorHeight = windowInfo.NONEDITOR + - (+!!this.props.showConsole * (this.state.consoleHeight + windowInfo.CONSOLEPAD)); + const windowNonEditorHeight = windowInfo.NONEDITOR + +!!this.props.showConsole * (this.state.consoleHeight + windowInfo.CONSOLEPAD); return `${String(window.innerHeight - windowNonEditorHeight)}px`; - } + }; - beforeUnload = (event: any) => { + beforeUnload = (event: Event) => { // If there are unsaved changes and the user tries to close Dawn, // check if they want to save their changes first. if (this.hasUnsavedChanges()) { - dialog.showMessageBox(currentWindow, { - type: 'warning', - buttons: ['Save...', 'Don\'t Save', 'Cancel'], - defaultId: 0, - cancelId: 2, - title: 'You have unsaved changes!', - message: 'Do you want to save the changes made to your program?', - detail: 'Your changes will be lost if you don\'t save them.', - }) - // NOTE: For whatever reason, `event.preventDefault()` does not work within - // beforeunload events, so we use `event.returnValue = false` instead. - .then(clickedId => { - if (clickedId.response === 0) { - // FIXME: Figure out a way to make Save and Close, well, close. - event.returnValue = false; - this.props.onSaveFile(); - } else if (clickedId.response === 2) { - event.returnValue = false; - } - }) - + dialog + .showMessageBox(currentWindow, { + type: 'warning', + buttons: ['Save...', "Don't Save", 'Cancel'], + defaultId: 0, + cancelId: 2, + title: 'You have unsaved changes!', + message: 'Do you want to save the changes made to your program?', + detail: "Your changes will be lost if you don't save them." + }) + // NOTE: For whatever reason, `event.preventDefault()` does not work within + // beforeunload events, so we use `event.returnValue = false` instead. + .then((clickedId) => { + if (clickedId.response === 0) { + // FIXME: Figure out a way to make Save and Close, well, close. + event.returnValue = false; + this.props.onSaveFile(); + } else if (clickedId.response === 2) { + event.returnValue = false; + } + }); } - } + }; toggleConsole = () => { this.props.toggleConsole(); // Resize since the console overlaps with the editor, but enough time for console changes setTimeout(() => this.onWindowResize(), 0.01); - } + }; upload = () => { const { filepath } = this.props; if (filepath === '') { - this.props.onAlertAdd( - 'Not Working on a File', - 'Please save first', - ); + this.props.onAlertAdd('Not Working on a File', 'Please save first'); logging.log('Upload: Not Working on File'); return; } if (this.hasUnsavedChanges()) { - this.props.onAlertAdd( - 'Unsaved File', - 'Please save first', - ); + this.props.onAlertAdd('Unsaved File', 'Please save first'); logging.log('Upload: Not Working on Saved File'); return; } if (Editor.correctText(this.props.editorCode) !== this.props.editorCode) { this.props.onAlertAdd( 'Invalid characters detected', - 'Your code has non-ASCII characters, which won\'t work on the robot. ' + - 'Please remove them and try again.', + "Your code has non-ASCII characters, which won't work on the robot. " + 'Please remove them and try again.' ); logging.log('Upload: Non-ASCII Issue'); return; } this.props.onUploadCode(); - } + }; startRobot = () => { this.props.onUpdateCodeStatus(this.state.mode); this.props.onClearConsole(); - } + }; stopRobot = () => { this.setState({ simulate: false, - modeDisplay: (this.state.mode === robotState.AUTONOMOUS) ? - robotState.AUTOSTR : robotState.TELEOPSTR, + modeDisplay: this.state.mode === robotState.AUTONOMOUS ? robotState.AUTOSTR : robotState.TELEOPSTR }); this.props.onUpdateCodeStatus(robotState.IDLE); - } + }; estop = () => { this.setState({ simulate: false, modeDisplay: robotState.ESTOPSTR }); this.props.onUpdateCodeStatus(robotState.ESTOP); - } + }; simulateCompetition = () => { this.setState({ simulate: true, modeDisplay: robotState.SIMSTR }); @@ -336,62 +327,69 @@ export class Editor extends React.Component { }, timings.SEC); }); - simulation.then(() => - new Promise((resolve, reject) => { - logging.log(`Beginning ${timings.IDLE}s Cooldown`); - this.props.onUpdateCodeStatus(robotState.IDLE); - const timestamp = Date.now(); - const coolInt = setInterval(() => { - const diff = Math.trunc((Date.now() - timestamp) / timings.SEC); - if (diff > timings.IDLE) { - clearInterval(coolInt); - resolve(); - } else if (!this.state.simulate) { - clearInterval(coolInt); - logging.log('Cooldown Quit'); - reject(); - } else { - this.setState({ modeDisplay: `Cooldown: ${timings.IDLE - diff}` }); - } - }, timings.SEC); - })).then(() => { - new Promise((resolve, reject) => { - logging.log(`Beginning ${timings.TELEOP}s ${robotState.TELEOPSTR}`); - this.props.onUpdateCodeStatus(robotState.TELEOP); - const timestamp = Date.now(); - const teleInt = setInterval(() => { - const diff = Math.trunc((Date.now() - timestamp) / timings.SEC); - if (diff > timings.TELEOP) { - clearInterval(teleInt); - resolve(); - } else if (!this.state.simulate) { - clearInterval(teleInt); - logging.log(`${robotState.TELEOPSTR} Quit`); - reject(); - } else { - this.setState({ modeDisplay: `${robotState.TELEOPSTR}: ${timings.TELEOP - diff}` }); + simulation + .then( + () => + new Promise((resolve, reject) => { + logging.log(`Beginning ${timings.IDLE}s Cooldown`); + this.props.onUpdateCodeStatus(robotState.IDLE); + const timestamp = Date.now(); + const coolInt = setInterval(() => { + const diff = Math.trunc((Date.now() - timestamp) / timings.SEC); + if (diff > timings.IDLE) { + clearInterval(coolInt); + resolve(); + } else if (!this.state.simulate) { + clearInterval(coolInt); + logging.log('Cooldown Quit'); + reject(); + } else { + this.setState({ modeDisplay: `Cooldown: ${timings.IDLE - diff}` }); + } + }, timings.SEC); + }) + ) + .then(() => { + new Promise((resolve, reject) => { + logging.log(`Beginning ${timings.TELEOP}s ${robotState.TELEOPSTR}`); + this.props.onUpdateCodeStatus(robotState.TELEOP); + const timestamp = Date.now(); + const teleInt = setInterval(() => { + const diff = Math.trunc((Date.now() - timestamp) / timings.SEC); + if (diff > timings.TELEOP) { + clearInterval(teleInt); + resolve(); + } else if (!this.state.simulate) { + clearInterval(teleInt); + logging.log(`${robotState.TELEOPSTR} Quit`); + reject(); + } else { + this.setState({ modeDisplay: `${robotState.TELEOPSTR}: ${timings.TELEOP - diff}` }); + } + }, timings.SEC); + }).then( + () => { + logging.log('Simulation Finished'); + this.props.onUpdateCodeStatus(robotState.IDLE); + }, + () => { + logging.log('Simulation Aborted'); + this.props.onUpdateCodeStatus(robotState.IDLE); } - }, timings.SEC); - }).then(() => { - logging.log('Simulation Finished'); - this.props.onUpdateCodeStatus(robotState.IDLE); - }, () => { - logging.log('Simulation Aborted'); - this.props.onUpdateCodeStatus(robotState.IDLE); + ); }); - }); - } + }; hasUnsavedChanges = () => { - return (this.props.latestSaveCode !== this.props.editorCode); - } + return this.props.latestSaveCode !== this.props.editorCode; + }; changeTheme = (theme: string) => { this.props.onChangeTheme(theme); storage.set('editorTheme', { theme }, (err: any) => { if (err) logging.log(err); }); - } + }; increaseFontsize = () => { this.setState({ fontsize: this.props.fontSize + 1 }); @@ -399,16 +397,16 @@ export class Editor extends React.Component { storage.set('editorFontSize', { editorFontSize: this.props.fontSize + 1 }, (err: any) => { if (err) logging.log(err); }); - } + }; - handleChangeFontsize = (event: any) => { - this.setState({ fontsize: event.target.value }); - } + handleChangeFontsize = (event: React.ChangeEvent) => { + this.setState({ fontsize: Number(event.target.value) ?? 12 }); + }; - handleSubmitFontsize = (event: any) => { + handleSubmitFontsize = (event: React.FormEvent) => { this.changeFontsizeToFont(Number(this.state.fontsize)); event.preventDefault(); - } + }; changeFontsizeToFont = (fontSize: number) => { if (fontSize > 28) { @@ -422,23 +420,23 @@ export class Editor extends React.Component { storage.set('editorFontSize', { editorFontSize: fontSize }, (err: any) => { if (err) logging.log(err); }); - } + }; raiseConsole = () => { this.setState({ consoleHeight: this.state.consoleHeight + windowInfo.UNIT }, () => { this.onWindowResize(); }); - } + }; lowerConsole = () => { this.setState({ consoleHeight: this.state.consoleHeight - windowInfo.UNIT }, () => { this.onWindowResize(); }); - } + }; copyConsole = () => { clipboard.writeText(this.props.consoleData.join('')); - } + }; decreaseFontsize = () => { this.setState({ fontsize: this.props.fontSize - 1 }); @@ -446,7 +444,7 @@ export class Editor extends React.Component { storage.set('editorFontSize', { editorFontSize: this.props.fontSize - 1 }, (err: any) => { if (err) logging.log(err); }); - } + }; render() { const changeMarker = this.hasUnsavedChanges() ? '*' : ''; @@ -456,36 +454,20 @@ export class Editor extends React.Component { return ( - Editing: {pathToName(this.props.filepath) ? pathToName(this.props.filepath) : '[ New File ]' } {changeMarker} + + Editing: {pathToName(this.props.filepath) ? pathToName(this.props.filepath) : '[ New File ]'} {changeMarker} +
- - New File - Open - Save - Save As + + New File + Open + Save + Save As - + { glyph="download" disabled={!this.props.runtimeStatus} /> - - {' '} + {' '} { bsSize="small" key="dropdown" id="modeDropdown" - disabled={this.state.simulate - || this.props.fieldControlActivity - || !this.props.runtimeStatus} + disabled={this.state.simulate || this.props.fieldControlActivity || !this.props.runtimeStatus} > { > Autonomous - + Simulate Competition - - - {' '} + + {' '} { disabled={false} bsStyle={this.props.consoleUnread ? 'danger' : ''} /> - + { glyph="arrow-down" disabled={this.state.consoleHeight < windowInfo.CONSOLEMIN} /> - - - {' '} + + {' '} { style={{ width: 32, padding: 6 }} /> Text Size}> - - this.changeFontsizeToFont(8)} - >8 - this.changeFontsizeToFont(12)} - >12 - this.changeFontsizeToFont(14)} - >14 - this.changeFontsizeToFont(16)} - >16 - this.changeFontsizeToFont(20)} - >20 - this.changeFontsizeToFont(24)} - >24 - this.changeFontsizeToFont(28)} - >28 + + this.changeFontsizeToFont(8)}> + 8 + + this.changeFontsizeToFont(12)}> + 12 + + this.changeFontsizeToFont(14)}> + 14 + + this.changeFontsizeToFont(16)}> + 16 + + this.changeFontsizeToFont(20)}> + 20 + + this.changeFontsizeToFont(24)}> + 24 + + this.changeFontsizeToFont(28)}> + 28 + - - {' '} + {' '} { glyph="zoom-out" disabled={this.props.fontSize <= 8} /> - + {this.themes.map((theme: string) => ( - + {theme} ))} @@ -682,11 +614,14 @@ export class Editor extends React.Component { theme={this.props.editorTheme} width="100%" fontSize={this.props.fontSize} - ref={(input: AceEditor) => { this.CodeEditor = input; }} + ref={(input: AceEditor) => { + this.CodeEditor = input; + }} name="CodeEditor" height={this.state.editorHeight.toString()} value={this.props.editorCode} onChange={this.props.onEditorUpdate} + // TODO: Fix lint error unbound method onPaste={Editor.onEditorPaste} editorProps={{ $blockScrolling: Infinity }} /> diff --git a/renderer/components/EditorContainer.ts b/renderer/components/EditorContainer.ts index 5669428f..cb2970a2 100644 --- a/renderer/components/EditorContainer.ts +++ b/renderer/components/EditorContainer.ts @@ -1,22 +1,8 @@ import { connect } from 'react-redux'; -import { Editor } from './Editor'; -import { - editorUpdate, - saveFile, - openFile, - dragFile, - createNewFile, - downloadCode, - uploadCode, -} from '../actions/EditorActions'; -import { - changeTheme, - changeFontSize, -} from '../actions/SettingsActions'; -import { - toggleConsole, - clearConsole, -} from '../actions/ConsoleActions'; +import { Editor } from './Editor'; +import { editorUpdate, saveFile, openFile, dragFile, createNewFile, downloadCode, uploadCode } from '../actions/EditorActions'; +import { changeTheme, changeFontSize } from '../actions/SettingsActions'; +import { toggleConsole, clearConsole } from '../actions/ConsoleActions'; import { addAsyncAlert } from '../actions/AlertActions'; import { updateCodeStatus, ipChange } from '../actions/InfoActions'; import { Dispatch } from 'redux'; @@ -34,7 +20,7 @@ const mapStateToProps = (state: ApplicationState) => ({ notificationHold: state.info.notificationHold, fieldControlActivity: state.info.fieldControlActivity, disableScroll: state.console.disableScroll, - consoleUnread: state.console.consoleUnread, + consoleUnread: state.console.consoleUnread }); const mapDispatchToProps = (dispatch: Dispatch) => ({ @@ -79,8 +65,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ }, onUploadCode: () => { dispatch(uploadCode()); - }, + } }); export const EditorContainer = connect(mapStateToProps, mapDispatchToProps)(Editor); - diff --git a/renderer/components/Gamepad.tsx b/renderer/components/Gamepad.tsx index 4cbba0ec..76041670 100644 --- a/renderer/components/Gamepad.tsx +++ b/renderer/components/Gamepad.tsx @@ -1,10 +1,5 @@ import React from 'react'; -import { - Modal, - Button, - ListGroupItem, - Table, -} from 'react-bootstrap'; +import { Modal, Button, ListGroupItem, Table } from 'react-bootstrap'; import _ from 'lodash'; import numeral from 'numeral'; import { GpState } from '../../protos/protos'; @@ -31,15 +26,15 @@ export class Gamepad extends React.Component { closeModal = () => { this.setState({ showModal: false }); - } + }; openModal = () => { this.setState({ showModal: true }); - } + }; roundedValues = () => { const gamepadButtons: string[] = []; - + for (let i = 0; i < 32; i++) { gamepadButtons.push(numeral(this.props.gamepad.buttons | (1 << i)).format('0')); } @@ -48,7 +43,7 @@ export class Gamepad extends React.Component { axes: _.map(this.props.gamepad.axes, (axis: number) => numeral(axis).format('0.00000')), buttons: gamepadButtons }; - } + }; renderHeader = () => { return ( @@ -56,15 +51,14 @@ export class Gamepad extends React.Component {

Gamepad {this.props.index}

); - } + }; render() { - const { gamepad } = this.props; const { showModal } = this.state; if (!gamepad) { - return (
); + return
; } const values = this.roundedValues(); return ( @@ -85,11 +79,15 @@ export class Gamepad extends React.Component { Button - {_.range(NUM_GAMEPAD_BUTTONS).map((gamepadButtonNumber: number) => {gamepadButtonNumber})} + {_.range(NUM_GAMEPAD_BUTTONS).map((gamepadButtonNumber: number) => ( + {gamepadButtonNumber} + ))} Value - {_.range(NUM_GAMEPAD_BUTTONS).map((gamepadButtonNumber: number) => {values.buttons[gamepadButtonNumber]})} + {_.range(NUM_GAMEPAD_BUTTONS).map((gamepadButtonNumber: number) => ( + {values.buttons[gamepadButtonNumber]} + ))} @@ -97,12 +95,15 @@ export class Gamepad extends React.Component { Axis - {_.range(NUM_GAMEPAD_AXES).map((gamepadButtonAxis: number) => {gamepadButtonAxis})} - + {_.range(NUM_GAMEPAD_AXES).map((gamepadButtonAxis: number) => ( + {gamepadButtonAxis} + ))} Value - {_.range(NUM_GAMEPAD_AXES).map((gamepadButtonAxis: number) => {values.buttons[gamepadButtonAxis]})} + {_.range(NUM_GAMEPAD_AXES).map((gamepadButtonAxis: number) => ( + {values.buttons[gamepadButtonAxis]} + ))} @@ -111,4 +112,4 @@ export class Gamepad extends React.Component { ); } -}; +} diff --git a/renderer/components/GamepadList.tsx b/renderer/components/GamepadList.tsx index 2a20b14a..d77ca12e 100644 --- a/renderer/components/GamepadList.tsx +++ b/renderer/components/GamepadList.tsx @@ -14,36 +14,26 @@ type Props = StateProps; const GamepadListComponent = (props: Props) => { let interior; if (_.some(props.gamepads, (gamepad: GpState) => gamepad !== undefined)) { - interior = _.map( - props.gamepads, - (gamepad: GpState, index: string) => , - ); + interior = _.map(props.gamepads, (gamepad: GpState, index: string) => ( + + )); } else { interior = ( -

- There doesn't seem to be any gamepads connected. - Connect a gamepad and press any button on it. -

+

There doesn't seem to be any gamepads connected. Connect a gamepad and press any button on it.

); } return ( - + Gamepads - - {interior} - + {interior} ); }; const mapStateToProps = (state: ApplicationState) => ({ - gamepads: state.gamepads.gamepads, + gamepads: state.gamepads.gamepads }); export const GamepadList = connect(mapStateToProps)(GamepadListComponent); - diff --git a/renderer/components/JoyrideSteps.tsx b/renderer/components/JoyrideSteps.tsx index 787159ef..43555711 100644 --- a/renderer/components/JoyrideSteps.tsx +++ b/renderer/components/JoyrideSteps.tsx @@ -13,72 +13,91 @@ interface JoyrideSteps { event: string; } -export const joyrideSteps: JoyrideSteps[] = [ +export const joyrideSteps: JoyrideSteps[] = [ { title: 'Header and Version', - content: 'This header displays the version of Dawn that you have. We may periodically release updates to Dawn, so always make sure you have the latest version.', + content: + 'This header displays the version of Dawn that you have. We may periodically release updates to Dawn, so always make sure you have the latest version.', target: '#header-title', placement: 'bottom', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Status Indicator', - content: 'This displays your connection status with the robot and (when connected) the robot\'s current battery level. Keep an eye on the battery level and charge the battery whenever it is nearly drained. Allowing the battery level to drop too low could damage your battery permanently.', + content: + "This displays your connection status with the robot and (when connected) the robot's current battery level. Keep an eye on the battery level and charge the battery whenever it is nearly drained. Allowing the battery level to drop too low could damage your battery permanently.", target: '#battery-indicator', placement: 'bottom', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Editor', - content: 'This is the code editor. Create and edit your robot\'s code here. The editor has autocompletion. Press CTRL/CMD-SPACEBAR to see autocomplete suggestions.', + content: + "This is the code editor. Create and edit your robot's code here. The editor has autocompletion. Press CTRL/CMD-SPACEBAR to see autocomplete suggestions.", target: '.ace_editor', placement: 'bottom-start', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'File operations', - content: 'Use these buttons to create, open, save, and upload code files. You can additionally download the robot\'s version of your code.', + content: + "Use these buttons to create, open, save, and upload code files. You can additionally download the robot's version of your code.", target: '#file-operations-buttons', placement: 'bottom', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Code execution', - content: 'Use these buttons to run and stop your code, including a last-ditch Emergency-Stop. In addition to changing state, there is an option to simulate the autonomous and teleop timings of a real match.', + content: + 'Use these buttons to run and stop your code, including a last-ditch Emergency-Stop. In addition to changing state, there is an option to simulate the autonomous and teleop timings of a real match.', target: '#code-execution-buttons', placement: 'bottom', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Output Console', content: 'Use these buttons to see and clear the console, along with changing its size and copying console text.', target: '#console-buttons', placement: 'bottom', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Editor Settings', - content: 'You can change the font size of the editor and change your editor\'s theme using these buttons. Your preferences will be saved automatically.', + content: + "You can change the font size of the editor and change your editor's theme using these buttons. Your preferences will be saved automatically.", target: '#editor-settings-buttons', placement: 'bottom', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Peripherals', - content: 'This panel displays info about your robot\'s peripherals, including motors and sensors. You can click on a peripheral name to change it. The name you assign to a peripheral here is the same name you should use to reference the peripheral in your code.', + content: + "This panel displays info about your robot's peripherals, including motors and sensors. You can click on a peripheral name to change it. The name you assign to a peripheral here is the same name you should use to reference the peripheral in your code.", target: '#peripherals-panel', placement: 'left', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Gamepads', - content: 'This panel displays all the connected gamepads. Once you have a gamepad connected, press the details buttons to see more gamepad details.', + content: + 'This panel displays all the connected gamepads. Once you have a gamepad connected, press the details buttons to see more gamepad details.', target: '#gamepads-panel', placement: 'left', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Updates', - content: 'Occasionally we may release updates to the robot\'s software. When this happens, you will download the update package and click on this button to upload it to the robot. Please do not restart your robot.', + content: + "Occasionally we may release updates to the robot's software. When this happens, you will download the update package and click on this button to upload it to the robot. Please do not restart your robot.", target: '#update-software-button', placement: 'left', - event: 'hover', - }, { + event: 'hover' + }, + { title: 'Robot IP', content: 'This sets the IP address Dawn will use when trying to connect to the robot.', target: '#update-address-button', placement: 'left', - event: 'hover', - }, + event: 'hover' + } ]; diff --git a/renderer/components/Peripheral.tsx b/renderer/components/Peripheral.tsx index 7e3d7afa..c3d65540 100644 --- a/renderer/components/Peripheral.tsx +++ b/renderer/components/Peripheral.tsx @@ -8,17 +8,18 @@ import { Motor } from './peripherals/Motor'; import { Param } from '../../protos/protos'; // Mapping between peripheral types and components -const typesToComponents = {}; -typesToComponents[PeripheralTypes.MOTOR_SCALAR] = Motor; -typesToComponents[PeripheralTypes.SENSOR_BOOLEAN] = BooleanSensor; -typesToComponents[PeripheralTypes.LimitSwitch] = BooleanSensor; -typesToComponents[PeripheralTypes.GameValues] = GameValues; +const typesToComponents: Record = { + [PeripheralTypes.MOTOR_SCALAR]: Motor, + [PeripheralTypes.SENSOR_BOOLEAN]: BooleanSensor, + [PeripheralTypes.LimitSwitch]: BooleanSensor, + [PeripheralTypes.GameValues]: GameValues +}; interface OwnProps { key: string; uid: string; name: string; - type: string; + type: number; params: Param[]; } @@ -33,8 +34,7 @@ export const Peripheral = (props: OwnProps) => { return ( - + ); }; - diff --git a/renderer/components/PeripheralList.tsx b/renderer/components/PeripheralList.tsx index e4cee9a0..2cead577 100644 --- a/renderer/components/PeripheralList.tsx +++ b/renderer/components/PeripheralList.tsx @@ -45,7 +45,6 @@ const handleAccordion = (devices: Peripheral[]) => { peripheralGroups[peripheral.name] = group; }); - return Object.keys(peripheralGroups).map((groupName: string) => { const groupNameCleaned = groupName; //cleanerNames[groupName] as string; @@ -69,7 +68,7 @@ const handleAccordion = (devices: Peripheral[]) => { key={String(peripheral.uid)} uid={String(peripheral.uid)} name={peripheral.name} - type={peripheral.name} + type={peripheral.type} params={peripheral.params} /> ))} @@ -111,6 +110,7 @@ const mapStateToProps = (state: ApplicationState) => ({ peripheralList: Object.assign({}, state.peripherals.peripheralList) }); +// eslint-disable-next-line @typescript-eslint/ban-types const PeripheralListContainer = connect(mapStateToProps, {})(PeripheralListComponent); export default PeripheralListContainer; diff --git a/renderer/components/StatusLabel.tsx b/renderer/components/StatusLabel.tsx index 59cf4f97..3812f18c 100644 --- a/renderer/components/StatusLabel.tsx +++ b/renderer/components/StatusLabel.tsx @@ -24,12 +24,13 @@ type Props = StateProps & OwnProps; const StatusLabelComponent = (props: Props) => { let labelStyle = 'default'; let labelText = 'Disconnected'; - const masterRobotHeader = 'Master Robot: Team '; + const teamIP = props.ipAddress.substring(props.ipAddress.length - 2, props.ipAddress.length); - const shouldDisplayMaster = (teamNumber: number) => parseInt(teamIP, 10) === teamNumber - && props.fieldControlStatus; + const shouldDisplayMaster = (teamNumber: number) => parseInt(teamIP, 10) === teamNumber && props.fieldControlStatus; + let masterRobot = null; let masterRobotStyle = ' '; + if (shouldDisplayMaster(props.blueMasterTeamNumber)) { masterRobot = props.blueMasterTeamNumber; masterRobotStyle = 'primary'; @@ -52,10 +53,9 @@ const StatusLabelComponent = (props: Props) => { } return (
- - {' '} + {' '}
); @@ -63,7 +63,7 @@ const StatusLabelComponent = (props: Props) => { const mapStateToProps = (state: ApplicationState) => ({ batteryLevel: state.peripherals.batteryLevel, - batterySafety: state.peripherals.batterySafety, + batterySafety: state.peripherals.batterySafety }); export const StatusLabel = connect(mapStateToProps)(StatusLabelComponent); diff --git a/renderer/components/TooltipButton.tsx b/renderer/components/TooltipButton.tsx index ca108ffe..271393ed 100644 --- a/renderer/components/TooltipButton.tsx +++ b/renderer/components/TooltipButton.tsx @@ -1,12 +1,7 @@ import React from 'react'; -import { - Button, - Glyphicon, - OverlayTrigger, - Tooltip, -} from 'react-bootstrap'; +import { Button, Glyphicon, OverlayTrigger, Tooltip } from 'react-bootstrap'; -interface StateProp{ +interface StateProp { id: string; text: string; onClick: () => void; @@ -17,9 +12,7 @@ interface StateProp{ } export const TooltipButton = (props: StateProp) => { - const tooltip = ( - {props.text} - ); + const tooltip = {props.text}; return ( +
); @@ -137,12 +137,7 @@ class UpdateBoxContainer extends React.Component { {modalBody} - @@ -154,7 +149,7 @@ class UpdateBoxContainer extends React.Component { const mapDispatchToProps = (dispatch: Dispatch) => ({ onAlertAdd: (heading: string, message: string) => { dispatch(addAsyncAlert(heading, message)); - }, + } }); export const UpdateBox = connect(null, mapDispatchToProps)(UpdateBoxContainer); diff --git a/renderer/components/peripherals/BooleanSensor.tsx b/renderer/components/peripherals/BooleanSensor.tsx index 515afc66..444b3705 100644 --- a/renderer/components/peripherals/BooleanSensor.tsx +++ b/renderer/components/peripherals/BooleanSensor.tsx @@ -2,7 +2,8 @@ import React from 'react'; import _ from 'lodash'; import { PeripheralTypes } from '../../consts'; -import { Param, Device } from '../../../protos/protos'; +import { Param } from '../../../protos/protos'; +import { Peripheral } from '../../types'; /** * Boolean Sensor Component @@ -13,29 +14,22 @@ const formatBoolean = (peripheralType: any, peripheral: Param) => { sensorValue = peripheral.bval; } if (peripheralType === PeripheralTypes.LimitSwitch) { - return (sensorValue) ? 'Closed' : 'Open'; + return sensorValue ? 'Closed' : 'Open'; } - return sensorValue; + return String(sensorValue); }; -export const BooleanSensor = ({ - uid, - type, - params, -}: Device) => ( +export const BooleanSensor = ({ uid, type, params }: Peripheral) => (

{uid}

- { - _.map(params, obj => ( -
-

- {`${obj.name}: ${formatBoolean(type, obj)}`} -

-
- )) - } + {_.map(params, (obj) => ( +
+

+ {`${obj.name}: ${formatBoolean(type, obj)}`} +

+
+ ))}
); - diff --git a/renderer/components/peripherals/GameValues.tsx b/renderer/components/peripherals/GameValues.tsx index dc22f02d..021f4e8c 100644 --- a/renderer/components/peripherals/GameValues.tsx +++ b/renderer/components/peripherals/GameValues.tsx @@ -1,30 +1,26 @@ /* eslint-disable camelcase */ import React from 'react'; import _ from 'lodash'; -import { Device } from '../../../protos/protos'; +import { Peripheral } from '../../types'; /** * Generic Peripheral for General Case */ -export const GameValues = ({ - name, params, -}: Device) => ( +export const GameValues = ({ name, params }: Peripheral) => (

{name}

- { - _.map(params, obj => ( -
-

- {obj.ival} -

-
- )) - } + {_.map(params, (obj) => ( +
+

+ {obj.ival} +

+
+ ))}
); GameValues.defaultProps = { - device_name: 'Unknown Device', + device_name: 'Unknown Device' }; diff --git a/renderer/components/peripherals/GenericPeripheral.tsx b/renderer/components/peripherals/GenericPeripheral.tsx index 1163cc01..c2e015dc 100644 --- a/renderer/components/peripherals/GenericPeripheral.tsx +++ b/renderer/components/peripherals/GenericPeripheral.tsx @@ -2,27 +2,22 @@ import React from 'react'; import _ from 'lodash'; import numeral from 'numeral'; -import { Device } from '../../../protos/protos'; +import { Peripheral } from '../../types'; /** * Generic Peripheral for General Case */ -export const GenericPeripheral = ({ - uid, params, -}: Device) => ( +export const GenericPeripheral = ({ uid, params }: Peripheral) => (

{uid}

- { - _.map(params, obj => ( -
-

- {`${obj.name}: ${numeral(obj.ival || obj.fval).format('+0.00')}`} -

-
- )) - } + {_.map(params, (obj) => ( +
+

+ {`${obj.name}: ${numeral(obj.ival || obj.fval).format('+0.00')}`} +

+
+ ))}
); - diff --git a/renderer/components/peripherals/Motor.tsx b/renderer/components/peripherals/Motor.tsx index dce7a4da..a74932c8 100644 --- a/renderer/components/peripherals/Motor.tsx +++ b/renderer/components/peripherals/Motor.tsx @@ -3,28 +3,27 @@ import React from 'react'; import _ from 'lodash'; import numeral from 'numeral'; import { ProgressBar } from 'react-bootstrap'; -import { Device } from '../../../protos/protos'; +import { Peripheral } from '../../types'; /** * Motor Component */ -export const Motor = ({ uid, params }: Device) => ( +export const Motor = ({ uid, params }: Peripheral) => (

{uid}
Motor

- { - _.map(params, obj => ( // TODO: Figure out if a ProgressBar is useful -
-

- {`${obj.name}: ${numeral(obj.fval).format('+0.00')}`} - -

- -
- )) - } + {_.map(params, ( + obj // TODO: Figure out if a ProgressBar is useful + ) => ( +
+

+ {`${obj.name}: ${numeral(obj.fval).format('+0.00')}`} +

+ +
+ ))}
); diff --git a/renderer/consts/actions.ts b/renderer/consts/actions.ts index 09142820..d3f8ab4e 100644 --- a/renderer/consts/actions.ts +++ b/renderer/consts/actions.ts @@ -1,18 +1,18 @@ export enum AlertActionsTypes { ADD_ASYNC_ALERT = 'ADD_ASYNC_ALERT', - REMOVE_ASYNC_ALERT = 'REMOVE_ASYNC_ALERT', + REMOVE_ASYNC_ALERT = 'REMOVE_ASYNC_ALERT' } export enum ConsoleActionsTypes { UPDATE_CONSOLE = 'UPDATE_CONSOLE', CLEAR_CONSOLE = 'CLEAR_CONSOLE', TOGGLE_CONSOLE = 'TOGGLE_CONSOLE', - TOGGLE_SCROLL = 'TOGGLE_SCROLL', + TOGGLE_SCROLL = 'TOGGLE_SCROLL' } export enum PeripheralActionsTypes { UPDATE_PERIPHERALS = 'UPDATE_PERIPHERALS', - PERIPHERAL_RENAME = 'PERIPHERAL_RENAME', + PERIPHERAL_RENAME = 'PERIPHERAL_RENAME' } export enum EditorActionsTypes { @@ -25,16 +25,16 @@ export enum EditorActionsTypes { DELETE_FILE = 'DELETE_FILE', CREATE_NEW_FILE = 'CREATE_NEW_FILE', DOWNLOAD_CODE = 'DOWNLOAD_CODE', - UPLOAD_CODE = 'UPLOAD_CODE', + UPLOAD_CODE = 'UPLOAD_CODE' } export enum GamepadsActionsTypes { - UPDATE_GAMEPADS = 'UPDATE_GAMEPADS', + UPDATE_GAMEPADS = 'UPDATE_GAMEPADS' } export enum SettingsActionsTypes { CHANGE_FONT_SIZE = 'CHANGE_FONTSIZE', - CHANGE_THEME = 'CHANGE_THEME', + CHANGE_THEME = 'CHANGE_THEME' } export enum InfoActionsTypes { @@ -44,7 +44,7 @@ export enum InfoActionsTypes { RUNTIME_DISCONNECT = 'RUNTIME_DISCONNECT', CODE_STATUS = 'CODE_STATUS', IP_CHANGE = 'IP_CHANGE', - NOTIFICATION_CHANGE = 'NOTIFICATION_CHANGE', + NOTIFICATION_CHANGE = 'NOTIFICATION_CHANGE' } export enum FieldActionsTypes { @@ -54,5 +54,5 @@ export enum FieldActionsTypes { UPDATE_MATCH = 'UPDATE_MATCH', UPDATE_ROBOT = 'UPDATE_ROBOT', FIELD_CONTROL = 'FIELD_CONTROL', - UPDATE_FC_CONFIG = 'UPDATE_FC_CONFIG', + UPDATE_FC_CONFIG = 'UPDATE_FC_CONFIG' } diff --git a/renderer/consts/index.ts b/renderer/consts/index.ts index 5888dc91..1872f2a6 100644 --- a/renderer/consts/index.ts +++ b/renderer/consts/index.ts @@ -6,7 +6,7 @@ export { GamepadsActionsTypes, SettingsActionsTypes, InfoActionsTypes, - FieldActionsTypes, + FieldActionsTypes } from './actions'; export { PeripheralTypes } from './peripheral-types'; export { VERSION } from './version'; diff --git a/renderer/consts/peripheral-types.ts b/renderer/consts/peripheral-types.ts index 6ed75d23..a4638a32 100644 --- a/renderer/consts/peripheral-types.ts +++ b/renderer/consts/peripheral-types.ts @@ -19,5 +19,5 @@ export const PeripheralTypes = keyMirror({ GameValues: null, master: null, PolarBear: null, - KoalaBear: null, + KoalaBear: null }); diff --git a/renderer/reducers/alerts.ts b/renderer/reducers/alerts.ts index 5e3b1544..8e596063 100644 --- a/renderer/reducers/alerts.ts +++ b/renderer/reducers/alerts.ts @@ -3,15 +3,11 @@ */ import * as consts from '../consts'; -import { AddAsyncAlertAction, RemoveAsyncAlertAction } from '../types'; +import { AddAsyncAlertAction, AlertType, RemoveAsyncAlertAction } from '../types'; type Actions = AddAsyncAlertAction | RemoveAsyncAlertAction; -type AsyncAlertsState = Array<{ - id?: number; - heading?: string; - message?: string; -}>; +type AsyncAlertsState = Array; const initialState: AsyncAlertsState = []; @@ -23,8 +19,8 @@ export const asyncAlerts = (state: AsyncAlertsState = initialState, action: Acti { id: action.id, heading: action.heading, - message: action.message, - }, + message: action.message + } ]; case consts.AlertActionsTypes.REMOVE_ASYNC_ALERT: return state.filter((el: { id?: number }) => el.id !== action.id); diff --git a/renderer/reducers/console.ts b/renderer/reducers/console.ts index 24713518..a1db34d5 100644 --- a/renderer/reducers/console.ts +++ b/renderer/reducers/console.ts @@ -17,7 +17,7 @@ const initialState = { showConsole: false, consoleData: [], disableScroll: false, - consoleUnread: false, + consoleUnread: false }; export const console = (state: ConsoleState = initialState, action: Actions) => { @@ -26,23 +26,23 @@ export const console = (state: ConsoleState = initialState, action: Actions) => return { ...state, consoleData: [...state.consoleData, ...action.consoleOutput], - consoleUnread: !state.showConsole, + consoleUnread: !state.showConsole }; case consts.ConsoleActionsTypes.CLEAR_CONSOLE: return { ...state, - consoleData: [], + consoleData: [] }; case consts.ConsoleActionsTypes.TOGGLE_CONSOLE: return { ...state, showConsole: !state.showConsole, - consoleUnread: false, + consoleUnread: false }; case consts.ConsoleActionsTypes.TOGGLE_SCROLL: return { ...state, - disableScroll: !state.disableScroll, + disableScroll: !state.disableScroll }; default: return state; diff --git a/renderer/reducers/editor.ts b/renderer/reducers/editor.ts index ae41ff91..0afa31c8 100644 --- a/renderer/reducers/editor.ts +++ b/renderer/reducers/editor.ts @@ -12,7 +12,7 @@ import { DeleteFileAction, CreateNewFileAction, DownloadCodeAction, - UploadCodeAction, + UploadCodeAction } from '../types'; type Actions = @@ -36,7 +36,7 @@ interface EditorState { const defaultEditorState = { filepath: '', latestSaveCode: '', - editorCode: '', + editorCode: '' }; export const editor = (state: EditorState = defaultEditorState, action: Actions) => { @@ -44,20 +44,20 @@ export const editor = (state: EditorState = defaultEditorState, action: Actions) case consts.EditorActionsTypes.UPDATE_EDITOR: return { ...state, - editorCode: action.code, + editorCode: action.code }; case consts.EditorActionsTypes.OPEN_FILE_SUCCEEDED: return { ...state, editorCode: action.code, filepath: action.filepath, - latestSaveCode: action.code, + latestSaveCode: action.code }; case consts.EditorActionsTypes.SAVE_FILE_SUCCEEDED: return { ...state, filepath: action.filepath, - latestSaveCode: action.code, + latestSaveCode: action.code }; default: return state; diff --git a/renderer/reducers/fieldStore.ts b/renderer/reducers/fieldStore.ts index 9986e96d..07ce19b3 100644 --- a/renderer/reducers/fieldStore.ts +++ b/renderer/reducers/fieldStore.ts @@ -6,7 +6,7 @@ import { UpdateMatchAction, UpdateRobotAction, ToggleFieldControlAction, - UpdateFieldControlAction, + UpdateFieldControlAction } from '../types'; type Actions = @@ -58,24 +58,24 @@ export const fieldStore = (state: FieldState = initialFieldState, action: Action return { ...state, stationNumber: action.stationNumber, - bridgeAddress: action.bridgeAddress, + bridgeAddress: action.bridgeAddress }; case consts.FieldActionsTypes.FIELD_CONTROL: return { ...state, - fieldControl: action.fieldControl, + fieldControl: action.fieldControl }; case consts.FieldActionsTypes.UPDATE_HEART: return { ...state, - heart: !state.heart, + heart: !state.heart }; case consts.FieldActionsTypes.UPDATE_MASTER: return { ...state, masterStatus: true, blueMasterTeamNumber: action.blueMasterTeamNumber, - goldMasterTeamNumber: action.goldMasterTeamNumber, + goldMasterTeamNumber: action.goldMasterTeamNumber }; case consts.FieldActionsTypes.UPDATE_MATCH: return { @@ -84,7 +84,7 @@ export const fieldStore = (state: FieldState = initialFieldState, action: Action mTeamNumbers: action.teamNumbers, mTeamNames: action.teamNames, rTeamNumber: action.teamNumbers[state.stationNumber], - rTeamName: action.teamNames[state.stationNumber], + rTeamName: action.teamNames[state.stationNumber] }; default: return state; diff --git a/renderer/reducers/gamepads.ts b/renderer/reducers/gamepads.ts index fd749b83..257d77c3 100644 --- a/renderer/reducers/gamepads.ts +++ b/renderer/reducers/gamepads.ts @@ -11,7 +11,7 @@ export const gamepads = (state: GamePadsState = {}, action: UpdateGamepadsAction case consts.GamepadsActionsTypes.UPDATE_GAMEPADS: return { ...state, - gamepads: action.gamepads, + gamepads: action.gamepads }; default: return state; diff --git a/renderer/reducers/info.ts b/renderer/reducers/info.ts index e7a2fe8e..468c2f87 100644 --- a/renderer/reducers/info.ts +++ b/renderer/reducers/info.ts @@ -9,7 +9,7 @@ import { UpdateCodeStatusAction, IpChangeAction, UpdateRobotAction, - NotificationChangeAction, + NotificationChangeAction } from '../types'; type Actions = @@ -45,7 +45,7 @@ const initialInfoState = { masterStatus: false, notificationHold: 0, fieldControlDirective: robotState.TELEOP, - fieldControlActivity: false, + fieldControlActivity: false }; export const info = (state: InfoState = initialInfoState, action: Actions): InfoState => { @@ -53,50 +53,50 @@ export const info = (state: InfoState = initialInfoState, action: Actions): Info case consts.InfoActionsTypes.PER_MESSAGE: return { ...state, - connectionStatus: true, + connectionStatus: true }; case consts.InfoActionsTypes.NOTIFICATION_CHANGE: return { ...state, - notificationHold: action.notificationHold, + notificationHold: action.notificationHold }; case consts.InfoActionsTypes.RUNTIME_CONNECT: return { ...state, - runtimeStatus: true, + runtimeStatus: true }; case consts.InfoActionsTypes.RUNTIME_DISCONNECT: return { ...state, runtimeStatus: false, connectionStatus: false, - studentCodeStatus: robotState.IDLE, + studentCodeStatus: robotState.IDLE }; case consts.InfoActionsTypes.MASTER_ROBOT: return { ...state, - masterStatus: true, + masterStatus: true }; case consts.InfoActionsTypes.CODE_STATUS: return { ...state, - studentCodeStatus: action.studentCodeStatus, + studentCodeStatus: action.studentCodeStatus }; case consts.InfoActionsTypes.IP_CHANGE: ipcRenderer.send('ipAddress', action.ipAddress); return { ...state, - ipAddress: action.ipAddress, + ipAddress: action.ipAddress }; case consts.FieldActionsTypes.UPDATE_ROBOT: { - const stateChange = (action.autonomous) ? robotState.AUTONOMOUS : robotState.TELEOP; - const codeStatus = (!action.enabled) ? robotState.IDLE : stateChange; + const stateChange = action.autonomous ? robotState.AUTONOMOUS : robotState.TELEOP; + const codeStatus = !action.enabled ? robotState.IDLE : stateChange; return { ...state, fieldControlDirective: stateChange, fieldControlActivity: action.enabled, // eslint-disable-next-line no-nested-ternary - studentCodeStatus: codeStatus, + studentCodeStatus: codeStatus }; } default: diff --git a/renderer/reducers/peripherals.ts b/renderer/reducers/peripherals.ts index 20826cb8..f4ddcb67 100644 --- a/renderer/reducers/peripherals.ts +++ b/renderer/reducers/peripherals.ts @@ -15,12 +15,12 @@ const initialPeripheralState: PeripheralState = { peripheralList: {}, batterySafety: false, batteryLevel: 0, - runtimeVersion: '1.0.0', + runtimeVersion: '1.0.0' }; // Taken from runtime_util.c in Runtime repo -const IS_UNSAFE: number = 0; -const V_BATT: number = 5; +const IS_UNSAFE = 0; +const V_BATT = 5; // TODO: Handle runtimeVersion since no longer sent export const peripherals = (state: PeripheralState = initialPeripheralState, action: Actions) => { @@ -34,16 +34,19 @@ export const peripherals = (state: PeripheralState = initialPeripheralState, act if (peripheral.name === consts.PeripheralTypes.BatteryBuzzer) { const batteryParams = peripheral.params; if (batteryParams[IS_UNSAFE] && batteryParams[IS_UNSAFE].bval) { - nextState.batterySafety = batteryParams[IS_UNSAFE].bval!; + nextState.batterySafety = batteryParams[IS_UNSAFE].bval; } if (batteryParams[V_BATT] && batteryParams[V_BATT].fval) { - nextState.batteryLevel = batteryParams[V_BATT].fval!; + nextState.batteryLevel = batteryParams[V_BATT].fval; } } else if (peripheral.uid === -1) { // const version = peripheral.params; // nextState.runtimeVersion = `${version['major']}.${version['minor']}.${version['patch']}`; } else { - const key = typeof peripheral.uid === 'number' ? peripheral.uid.toString() : (peripheral.uid.high || '').toString() + peripheral.uid.low.toString(); + const key = + typeof peripheral.uid === 'number' + ? peripheral.uid.toString() + : (peripheral.uid.high || '').toString() + peripheral.uid.low.toString(); keys.push(key); if (key in nextPeripherals) { peripheral.name = nextPeripherals[key].name; // ensures that the device keeps the name, if it was a custom name diff --git a/renderer/reducers/rootReducer.ts b/renderer/reducers/rootReducer.ts index 8024c1c7..c614a93b 100644 --- a/renderer/reducers/rootReducer.ts +++ b/renderer/reducers/rootReducer.ts @@ -23,5 +23,5 @@ export const rootReducer = combineReducers({ info, gamepads, settings, - timerStore, + timerStore }); diff --git a/renderer/reducers/settings.ts b/renderer/reducers/settings.ts index 20d395b8..b2c6bc6c 100644 --- a/renderer/reducers/settings.ts +++ b/renderer/reducers/settings.ts @@ -10,7 +10,7 @@ interface SettingState { const initialState = { fontSize: 14, - editorTheme: 'tomorrow', + editorTheme: 'tomorrow' }; export const settings = (state: SettingState = initialState, action: Actions) => { @@ -18,12 +18,12 @@ export const settings = (state: SettingState = initialState, action: Actions) => case consts.SettingsActionsTypes.CHANGE_FONT_SIZE: return { ...state, - fontSize: action.newFontSize, + fontSize: action.newFontSize }; case consts.SettingsActionsTypes.CHANGE_THEME: return { ...state, - editorTheme: action.theme, + editorTheme: action.theme }; default: return state; diff --git a/renderer/reducers/timerStore.ts b/renderer/reducers/timerStore.ts index f1f79692..f5ef5c55 100644 --- a/renderer/reducers/timerStore.ts +++ b/renderer/reducers/timerStore.ts @@ -14,7 +14,7 @@ const initialTimerState = { timeLeft: 0, computedTime: 0, // TODO: Questionable if this should even be in the store totalTime: 0, - stage: '', + stage: '' }; export const timerStore = (state: TimerState = initialTimerState, action: UpdateTimerAction) => { @@ -26,7 +26,7 @@ export const timerStore = (state: TimerState = initialTimerState, action: Update timeLeft: action.timeLeft, computedTime: action.timeLeft, stage: action.stage, - totalTime: action.totalTime, + totalTime: action.totalTime }; default: return state; diff --git a/renderer/store.ts b/renderer/store.ts index 94be8d90..61dfce05 100644 --- a/renderer/store.ts +++ b/renderer/store.ts @@ -5,11 +5,8 @@ import { rootReducer } from './reducers/rootReducer'; import rootSaga from './utils/sagas'; const sagaMiddleware = createSagaMiddleware(); -const composeEnhancers = window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'] as typeof compose || compose; +const composeEnhancers = (window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'] as typeof compose) || compose; -export const store = createStore( - rootReducer, - composeEnhancers(applyMiddleware(sagaMiddleware)), -); +export const store = createStore(rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware))); sagaMiddleware.run(rootSaga); diff --git a/renderer/types/actions/gamepads-actions.ts b/renderer/types/actions/gamepads-actions.ts index 7fc37f87..30dcb20e 100644 --- a/renderer/types/actions/gamepads-actions.ts +++ b/renderer/types/actions/gamepads-actions.ts @@ -1,5 +1,5 @@ import * as consts from '../../consts'; -import { GpState } from "../../../protos/protos"; +import { GpState } from '../../../protos/protos'; export interface UpdateGamepadsAction { type: consts.GamepadsActionsTypes.UPDATE_GAMEPADS; diff --git a/renderer/types/actions/index.ts b/renderer/types/actions/index.ts index e558162d..30d53dc2 100644 --- a/renderer/types/actions/index.ts +++ b/renderer/types/actions/index.ts @@ -12,7 +12,7 @@ export { DeleteFileAction, CreateNewFileAction, DownloadCodeAction, - UploadCodeAction, + UploadCodeAction } from './editor-actions'; export { GamepadsActions, UpdateGamepadsAction } from './gamepads-actions'; export { SettingsActions, ChangeFontSizeAction, ChangeThemeAction } from './settings-actions'; @@ -24,7 +24,7 @@ export { UpdateMatchAction, UpdateRobotAction, ToggleFieldControlAction, - UpdateFieldControlAction, + UpdateFieldControlAction } from './field-actions'; export { InfoActions, @@ -34,5 +34,5 @@ export { RuntimeDisconnectAction, UpdateCodeStatusAction, IpChangeAction, - NotificationChangeAction, + NotificationChangeAction } from './info-actions'; diff --git a/renderer/types/alert-type.ts b/renderer/types/alert-type.ts new file mode 100644 index 00000000..f7872fc8 --- /dev/null +++ b/renderer/types/alert-type.ts @@ -0,0 +1,5 @@ +export interface AlertType { + heading?: string; + message?: string; + id?: number; +} diff --git a/renderer/types/field-control-config.ts b/renderer/types/field-control-config.ts index 504ff28c..ae2403d9 100644 --- a/renderer/types/field-control-config.ts +++ b/renderer/types/field-control-config.ts @@ -1,4 +1,4 @@ export interface FieldControlConfig { - stationNumber: number; - bridgeAddress: string; - } \ No newline at end of file + stationNumber: number; + bridgeAddress: string; +} diff --git a/renderer/types/index.ts b/renderer/types/index.ts index ce0982f7..b83e7a6f 100644 --- a/renderer/types/index.ts +++ b/renderer/types/index.ts @@ -1,3 +1,4 @@ export * from './actions'; +export { AlertType } from './alert-type'; export { FieldControlConfig } from './field-control-config'; export { Peripheral, PeripheralList } from './peripheral-list'; diff --git a/renderer/types/modules.d.ts b/renderer/types/modules.d.ts index 426006be..b2924769 100644 --- a/renderer/types/modules.d.ts +++ b/renderer/types/modules.d.ts @@ -1 +1,3 @@ -declare module 'smalltalk'; \ No newline at end of file +declare module 'smalltalk' { + export function alert(heading: string, message: string): Promise; +} diff --git a/renderer/types/peripheral-list.ts b/renderer/types/peripheral-list.ts index a631593e..84dceef0 100644 --- a/renderer/types/peripheral-list.ts +++ b/renderer/types/peripheral-list.ts @@ -1,6 +1,6 @@ -import { Param } from "../../protos/protos"; +import { Param } from '../../protos/protos'; -/** This `Peripheral` type is separate from the Device proto. +/** This `Peripheral` type is separate from the Device proto. * The main difference is the uid is a string to account for readability of numbers and 64-bit Longs. */ export interface Peripheral { diff --git a/renderer/utils/sagas.ts b/renderer/utils/sagas.ts index 48fa6756..c2be048a 100644 --- a/renderer/utils/sagas.ts +++ b/renderer/utils/sagas.ts @@ -1,22 +1,26 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ + /** * Redux sagas are how we handle complicated asynchronous stuff with redux. - * See http://yelouafi.github.io/redux-saga/index.html for docs. + * See https://redux-saga.js.org/docs/api/ for docs. * Sagas use ES6 generator functions, which have the '*' in their declaration. */ +import * as consts from '../consts'; import fs, { readFile, writeFile } from 'fs'; import _ from 'lodash'; import { eventChannel } from 'redux-saga'; -import { all, call, cps, delay, fork, put, race, select, take, takeEvery } from 'redux-saga/effects'; -import { Client } from 'ssh2'; +import { all, call, cps, delay, fork, put, race, select, take, TakeEffect, takeEvery } from 'redux-saga/effects'; +import { Client, ClientChannel, ClientErrorExtensions, SFTPWrapper } from 'ssh2'; import { ipcRenderer, OpenDialogReturnValue, SaveDialogReturnValue, MessageBoxReturnValue, remote } from 'electron'; import { addAsyncAlert } from '../actions/AlertActions'; import { openFileSucceeded, saveFileSucceeded } from '../actions/EditorActions'; import { toggleFieldControl } from '../actions/FieldActions'; import { updateGamepads } from '../actions/GamepadsActions'; import { runtimeConnect, runtimeDisconnect } from '../actions/InfoActions'; -import { TIMEOUT, defaults, logging } from '../utils/utils'; +import { TIMEOUT_MSEC, defaults, logging } from '../utils/utils'; import { GpState } from '../../protos/protos'; +import { DragFileAction, OpenFileAction, SaveFileAction } from '../types'; let timestamp = Date.now(); @@ -30,19 +34,22 @@ let timestamp = Date.now(); */ function openFileDialog() { return new Promise((resolve, reject) => { - remote.dialog.showOpenDialog({ - filters: [{ name: 'python', extensions: ['py'] }], - }).then((openDialogReturnValue: OpenDialogReturnValue) => { - const { filePaths } = openDialogReturnValue; - // If filepaths is undefined, the user did not specify a file. - if (_.isEmpty(filePaths)) { - reject(); - } else { - resolve(filePaths[0]); - } - }).catch((error) => { - reject(error); - }); + remote.dialog + .showOpenDialog({ + filters: [{ name: 'python', extensions: ['py'] }] + }) + .then((openDialogReturnValue: OpenDialogReturnValue) => { + const { filePaths } = openDialogReturnValue; + // If filepaths is undefined, the user did not specify a file. + if (_.isEmpty(filePaths)) { + reject(); + } else { + resolve(filePaths[0]); + } + }) + .catch((error) => { + reject(error); + }); }); } @@ -54,22 +61,24 @@ function openFileDialog() { */ function saveFileDialog() { return new Promise((resolve, reject) => { - remote.dialog.showSaveDialog({ - filters: [{ name: 'python', extensions: ['py'] }], - }).then((saveDialogReturnValue: SaveDialogReturnValue) => { - const { filePath } = saveDialogReturnValue; - // If filepath is undefined, the user did not specify a file. - if (filePath === undefined) { - reject(); - return; - } + remote.dialog + .showSaveDialog({ + filters: [{ name: 'python', extensions: ['py'] }] + }) + .then((saveDialogReturnValue: SaveDialogReturnValue) => { + const { filePath } = saveDialogReturnValue; + // If filepath is undefined, the user did not specify a file. + if (filePath === undefined) { + reject(); + return; + } - // Automatically append .py extension if they don't have it - if (!filePath.endsWith('.py')) { - resolve(`${filePath}.py`); - } - resolve(filePath); - }); + // Automatically append .py extension if they don't have it + if (!filePath.endsWith('.py')) { + resolve(`${filePath}.py`); + } + resolve(filePath); + }); }); } @@ -81,21 +90,23 @@ function saveFileDialog() { */ function unsavedDialog(action: string) { return new Promise((resolve, reject) => { - remote.dialog.showMessageBox({ - type: 'warning', - buttons: [`Save and ${action}`, `Discard and ${action}`, 'Cancel action'], - title: 'You have unsaved changes!', - message: `You are trying to ${action} a new file, but you have unsaved changes to -your current one. What do you want to do?`, - }).then((messageBoxReturnValue: MessageBoxReturnValue) => { - const { response } = messageBoxReturnValue; - // 'res' is an integer corrseponding to index in button list above. - if (response === 0 || response === 1 || response === 2) { - resolve(response); - } else { - reject(); - } - }) + remote.dialog + .showMessageBox({ + type: 'warning', + buttons: [`Save and ${action}`, `Discard and ${action}`, 'Cancel action'], + title: 'You have unsaved changes!', + message: `You are trying to ${action} a new file, but you have unsaved changes to +your current one. What do you want to do?` + }) + .then((messageBoxReturnValue: MessageBoxReturnValue) => { + const { response } = messageBoxReturnValue; + // 'res' is an integer corrseponding to index in button list above. + if (response === 0 || response === 1 || response === 2) { + resolve(response); + } else { + reject(); + } + }); }); } @@ -108,16 +119,17 @@ function* writeCodeToFile(filepath: string, code: string): Generator ({ +const editorState = (state: ApplicationState) => ({ filepath: state.editor.filepath, - code: state.editor.editorCode, + code: state.editor.editorCode }); -function* saveFile(action: any) { - const result = yield select(editorState); +function* saveFile(action: SaveFileAction) { + const result: ReturnType = yield select(editorState); let { filepath } = result; const { code } = result; - // If the action is a "save as" OR there is no filepath (ie, a new file) + + // If the action is a "save as" OR there is no filepath (i.e. a new file) // then we open the save file dialog so the user can specify a filename before saving. if (action.saveAs === true || !filepath) { try { @@ -131,29 +143,35 @@ function* saveFile(action: any) { } } -const editorSavedState = (state: any) => ({ +const editorSavedState = (state: ApplicationState) => ({ savedCode: state.editor.latestSaveCode, - code: state.editor.editorCode, + code: state.editor.editorCode }); -function* openFile(action: any) { - const type = (action.type === 'OPEN_FILE') ? 'open' : 'create'; - const result = yield select(editorSavedState); - let res = 1; +function* openFile(action: OpenFileAction) { + const type = action.type === consts.EditorActionsTypes.OPEN_FILE ? 'open' : 'create'; + const result: ReturnType = yield select(editorSavedState); + + /** buttonIndex refers to the corresponding index (0, 1, 2) of the buttons in the Unsaved Dialog.*/ + let buttonIndex = 1; + if (result.code !== result.savedCode) { - res = yield call(unsavedDialog, type); - if (res === 0) { + buttonIndex = yield call(unsavedDialog, type); + + if (buttonIndex === 0) { yield* saveFile({ - type: 'SAVE_FILE', - saveAs: false, + type: consts.EditorActionsTypes.SAVE_FILE, + saveAs: false }); } } - if (res === 0 || res === 1) { + + // TODO: Add a comment explaining what's happening here. + if (buttonIndex === 0 || buttonIndex === 1) { if (type === 'open') { try { const filepath: string = yield call(openFileDialog); - const data = yield cps([fs, readFile], filepath); + const data: string = yield cps([fs, readFile], filepath); yield put(openFileSucceeded(data, filepath)); } catch (e) { logging.log('No filename specified, no file opened.'); @@ -166,23 +184,24 @@ function* openFile(action: any) { } } -function* dragFile(action: any) { - const result = yield select(editorSavedState); - let res = 1; // Refers to unsavedDialog choices +function* dragFile(action: DragFileAction) { + const result: ReturnType = yield select(editorSavedState); + let buttonIndex = 1; // Refers to unsavedDialog choices + if (result.code !== result.savedCode) { - res = yield call(unsavedDialog, 'open'); - if (res === 0) { + buttonIndex = yield call(unsavedDialog, 'open'); + if (buttonIndex === 0) { yield* saveFile({ - type: 'SAVE_FILE', - saveAs: false, + type: consts.EditorActionsTypes.SAVE_FILE, + saveAs: false }); } } - if (res === 0 || res === 1) { + if (buttonIndex === 0 || buttonIndex === 1) { try { const { filepath } = action; - const data = yield cps([fs, readFile], filepath); + const data: string = yield cps([fs, readFile], filepath); yield put(openFileSucceeded(data, filepath)); } catch (e) { logging.log('Failure to Drag File In'); @@ -203,13 +222,13 @@ function* runtimeHeartbeat() { while (true) { // Start a race between a delay and receiving an UPDATE_STATUS action from // runtime. Only the winner will have a value. - const result = yield race({ - update: take('PER_MESSAGE'), - timeout: delay(TIMEOUT) - }); + const { update }: { update: TakeEffect } = yield race({ + update: take(consts.InfoActionsTypes.PER_MESSAGE), + timeout: delay(TIMEOUT_MSEC) + }); // If update wins, we assume we are connected, otherwise disconnected. - if (result.update) { + if (update) { yield put(runtimeConnect()); } else { yield put(runtimeDisconnect()); @@ -219,9 +238,9 @@ function* runtimeHeartbeat() { const _timestamps: Array = [0, 0, 0, 0]; -function _needToUpdate(newGamepads: (Gamepad | null)[]): boolean { +function _needToUpdate(newGamepads: Array): boolean { return _.some(newGamepads, (gamepad, index) => { - if (gamepad != null && (gamepad.timestamp > (_timestamps[index] ?? 0))) { + if (gamepad != null && gamepad.timestamp > (_timestamps[index] ?? 0)) { _timestamps[index] = gamepad.timestamp; return true; } else if (gamepad == null && _timestamps[index] != null) { @@ -232,23 +251,23 @@ function _needToUpdate(newGamepads: (Gamepad | null)[]): boolean { }); } -function formatGamepads(newGamepads: (Gamepad | null)[]): GpState[] { - let formattedGamepads: GpState[] = []; +function formatGamepads(newGamepads: Array): GpState[] { + const formattedGamepads: GpState[] = []; // Currently there is a bug on windows where navigator.getGamepads() // returns a second, 'ghost' gamepad even when only one is connected. // The filter on 'mapping' filters out the ghost gamepad. _.forEach(_.filter(newGamepads, { mapping: 'standard' }), (gamepad: Gamepad | null, indexGamepad: number) => { if (gamepad) { - let bitmap: number = 0; + let bitmap = 0; gamepad.buttons.forEach((button, index) => { if (button.pressed) { - bitmap |= (1 << index); + bitmap |= 1 << index; } }); formattedGamepads[indexGamepad] = new GpState({ connected: gamepad.connected, axes: gamepad.axes.slice(), - buttons: bitmap, + buttons: bitmap }); } }); @@ -286,7 +305,7 @@ function* runtimeGamepads() { */ function runtimeReceiver() { return eventChannel((emitter) => { - const listener = (_event: any, action: any) => { + const listener = (_event: Electron.IpcRendererEvent, action: any) => { emitter(action); }; // Suscribe listener to dispatches from main process. @@ -304,7 +323,7 @@ function runtimeReceiver() { */ function* runtimeSaga() { try { - const chan = yield call(runtimeReceiver); + const chan: ReturnType = yield call(runtimeReceiver); while (true) { const action = yield take(chan); @@ -312,69 +331,70 @@ function* runtimeSaga() { yield put(action); } } catch (e) { - logging.log(e.stack); + logging.log(e); } } -const gamepadsState = (state: any) => state.gamepads.gamepads; +const getGamepadsState = (state: ApplicationState) => state.gamepads.gamepads; /** * Send the store to the main process whenever it changes. */ function* updateMainProcess() { - const stateSlice = yield select(gamepadsState); // Get gamepads from Redux state store + const stateSlice: ReturnType = yield select(getGamepadsState); // Get gamepads from Redux state store ipcRenderer.send('stateUpdate', stateSlice); } +const getSSHConfig = (state: ApplicationState) => ({ + runtimeStatus: state.info.runtimeStatus, + ipAddress: state.info.ipAddress, + filepath: state.editor.filepath +}); + function* restartRuntime() { const conn = new Client(); - const stateSlice = yield select((state: any) => ({ - runtimeStatus: state.info.runtimeStatus, - ipAddress: state.info.ipAddress, - })); + const stateSlice: ReturnType = yield select(getSSHConfig); + if (stateSlice.runtimeStatus && stateSlice.ipAddress !== defaults.IPADDRESS) { - const network = yield call(() => new Promise((resolve) => { - conn.on('ready', () => { - conn.exec( - 'sudo systemctl restart runtime.service', - { pty: true }, (uperr: any, stream: any) => { - if (uperr) { - resolve(1); - } - stream.write(`${defaults.PASSWORD}\n`); - stream.on('exit', (code: any) => { - logging.log(`Runtime Restart: Returned ${code}`); - conn.end(); - resolve(0); + const network = yield call( + () => + new Promise((resolve) => { + conn + .on('ready', () => { + conn.exec('sudo systemctl restart runtime.service', { pty: true }, (uperr: Error | undefined, stream: ClientChannel) => { + if (uperr) { + resolve(1); + } + stream.write(`${defaults.PASSWORD}\n`); + stream.on('exit', (code: number | null) => { + logging.log(`Runtime Restart: Returned ${code ?? -1}`); + conn.end(); + resolve(0); + }); + }); + }) + .connect({ + debug: (inpt: any) => { + logging.log(inpt); + }, + host: stateSlice.ipAddress, + port: defaults.PORT, + username: defaults.USERNAME, + password: defaults.PASSWORD }); - }, - ); - }).connect({ - debug: (inpt: any) => { - logging.log(inpt); - }, - host: stateSlice.ipAddress, - port: defaults.PORT, - username: defaults.USERNAME, - password: defaults.PASSWORD, - }); - })); + }) + ); if (network === 1) { - yield addAsyncAlert( - 'Runtime Restart Error', - 'Dawn was unable to run restart commands. Please check your robot connectivity.', - ); + yield addAsyncAlert('Runtime Restart Error', 'Dawn was unable to run restart commands. Please check your robot connectivity.'); } } } function* downloadStudentCode() { const conn = new Client(); - const stateSlice = yield select((state: any) => ({ - runtimeStatus: state.info.runtimeStatus, - ipAddress: state.info.ipAddress, - })); - const path = `${require('electron').remote.app.getPath('desktop')}/Dawn`; // eslint-disable-line global-require + const stateSlice: ReturnType = yield select(getSSHConfig); + const path = `${remote.app.getPath('desktop')}/Dawn`; + try { fs.statSync(path); } catch (fileErr) { @@ -382,75 +402,62 @@ function* downloadStudentCode() { } if (stateSlice.runtimeStatus) { logging.log(`Downloading to ${path}`); - const errors = yield call(() => new Promise((resolve) => { - conn.on('error', (err: any) => { - logging.log(err); - resolve(3); - }); - - conn.on('ready', () => { - conn.sftp((err: any, sftp: any) => { - if (err) { - logging.log(err); - resolve(1); - } - sftp.fastGet( - defaults.STUDENTCODELOC, `${path}/robotCode.py`, - (err2: any) => { - if (err2) { - logging.log(err2); - resolve(2); - } - resolve(0); - }, - ); - }); - }).connect({ - debug: (inpt: any) => { - logging.log(inpt); - }, - host: stateSlice.ipAddress, - port: defaults.PORT, - username: defaults.USERNAME, - password: defaults.PASSWORD, - }); - })); + const errors = yield call( + () => + new Promise((resolve) => { + conn.on('error', (err: Error & ClientErrorExtensions) => { + logging.log(err.description ?? err.message); + resolve(3); + }); + + conn + .on('ready', () => { + conn.sftp((err: Error | undefined, sftp: SFTPWrapper) => { + if (err) { + logging.log(err.message); + resolve(1); + } + sftp.fastGet(defaults.STUDENTCODELOC, `${path}/robotCode.py`, (err2: any) => { + if (err2) { + logging.log(err2); + resolve(2); + } + resolve(0); + }); + }); + }) + .connect({ + debug: (inpt: any) => { + logging.log(inpt); + }, + host: stateSlice.ipAddress, + port: defaults.PORT, + username: defaults.USERNAME, + password: defaults.PASSWORD + }); + }) + ); switch (errors) { case 0: { const data = yield cps(fs.readFile, `${path}/robotCode.py`); yield put(openFileSucceeded(data, `${path}/robotCode.py`)); - yield put(addAsyncAlert( - 'Download Success', - 'File Downloaded Successfully', - )); + yield put(addAsyncAlert('Download Success', 'File Downloaded Successfully')); break; } case 1: { - yield put(addAsyncAlert( - 'Download Issue', - 'SFTP session could not be initiated', - )); + yield put(addAsyncAlert('Download Issue', 'SFTP session could not be initiated')); break; } case 2: { - yield put(addAsyncAlert( - 'Download Issue', - 'File failed to be downloaded', - )); + yield put(addAsyncAlert('Download Issue', 'File failed to be downloaded')); break; } case 3: { - yield put(addAsyncAlert( - 'Download Issue', - 'Robot could not be connected.', - )); + yield put(addAsyncAlert('Download Issue', 'Robot could not be connected.')); break; } default: { - yield put(addAsyncAlert( - 'Download Issue', - 'Unknown Error', - )); + yield put(addAsyncAlert('Download Issue', 'Unknown Error')); break; } } @@ -462,81 +469,65 @@ function* downloadStudentCode() { function* uploadStudentCode() { const conn = new Client(); - const stateSlice = yield select((state: any) => ({ - runtimeStatus: state.info.runtimeStatus, - ipAddress: state.info.ipAddress, - filepath: state.editor.filepath, - })); + const stateSlice: ReturnType = yield select(getSSHConfig); + if (stateSlice.runtimeStatus) { logging.log(`Uploading ${stateSlice.filepath}`); - const errors = yield call(() => new Promise((resolve) => { - conn.on('error', (err: any) => { - logging.log(err); - resolve(3); - }); - - conn.on('ready', () => { - conn.sftp((err: any, sftp: any) => { - if (err) { + const errors = yield call( + () => + new Promise((resolve) => { + conn.on('error', (err: any) => { logging.log(err); - resolve(1); - } - sftp.fastPut( - stateSlice.filepath, defaults.STUDENTCODELOC, - (err2: any) => { - if (err2) { - logging.log(err2); - resolve(2); - } - resolve(0); - }, - ); - }); - }).connect({ - debug: (input: any) => { - logging.log(input); - }, - host: stateSlice.ipAddress, - port: defaults.PORT, - username: defaults.USERNAME, - password: defaults.PASSWORD, - }); - })); + resolve(3); + }); + + conn + .on('ready', () => { + conn.sftp((err: Error | undefined, sftp: SFTPWrapper) => { + if (err) { + logging.log(err.message); + resolve(1); + } + sftp.fastPut(stateSlice.filepath, defaults.STUDENTCODELOC, (err2: any) => { + if (err2) { + logging.log(err2); + resolve(2); + } + resolve(0); + }); + }); + }) + .connect({ + debug: (input: string) => { + logging.log(input); + }, + host: stateSlice.ipAddress, + port: defaults.PORT, + username: defaults.USERNAME, + password: defaults.PASSWORD + }); + }) + ); switch (errors) { case 0: { - yield put(addAsyncAlert( - 'Upload Success', - 'File Uploaded Successfully', - )); + yield put(addAsyncAlert('Upload Success', 'File Uploaded Successfully')); break; } case 1: { - yield put(addAsyncAlert( - 'Upload Issue', - 'SFTP session could not be initiated', - )); + yield put(addAsyncAlert('Upload Issue', 'SFTP session could not be initiated')); break; } case 2: { - yield put(addAsyncAlert( - 'Upload Issue', - 'File failed to be transmitted', - )); + yield put(addAsyncAlert('Upload Issue', 'File failed to be transmitted')); break; } case 3: { - yield put(addAsyncAlert( - 'Upload Issue', - 'Robot could not be connected', - )); + yield put(addAsyncAlert('Upload Issue', 'Robot could not be connected')); break; } default: { - yield put(addAsyncAlert( - 'Upload Issue', - 'Unknown Error', - )); + yield put(addAsyncAlert('Upload Issue', 'Unknown Error')); break; } } @@ -546,10 +537,11 @@ function* uploadStudentCode() { } } +const getFieldControlStatus = (state: ApplicationState) => ({ fieldControlStatus: state.fieldStore.fieldControl }); + function* handleFieldControl() { - const stateSlice = yield select((state: any) => ({ - fieldControlStatus: state.fieldStore.fieldControl, - })); + const stateSlice: ReturnType = yield select(getFieldControlStatus); + if (stateSlice.fieldControlStatus) { yield put(toggleFieldControl(false)); ipcRenderer.send('FC_TEARDOWN'); @@ -568,9 +560,10 @@ function timestampBounceback() { * Sends run mode status upon each main process update. */ function* exportRunMode() { - const stateSlice = yield select((state: any) => ({ - mode: state.info.studentCodeStatus, + const stateSlice = yield select((state: ApplicationState) => ({ + mode: state.info.studentCodeStatus })); + ipcRenderer.send('runModeUpdate', stateSlice); } @@ -592,7 +585,7 @@ export default function* rootSaga() { takeEvery('EXPORT_RUN_MODE', exportRunMode), fork(runtimeHeartbeat), fork(runtimeGamepads), - fork(runtimeSaga), + fork(runtimeSaga) ]); } @@ -606,8 +599,8 @@ export { saveFileDialog, saveFile, runtimeHeartbeat, - gamepadsState, + getGamepadsState, updateMainProcess, runtimeReceiver, - runtimeSaga, + runtimeSaga }; // for tests diff --git a/renderer/utils/test/sagas.test.js b/renderer/utils/test/sagas.test.js index 10497447..dd40b9b4 100644 --- a/renderer/utils/test/sagas.test.js +++ b/renderer/utils/test/sagas.test.js @@ -15,7 +15,7 @@ import { saveFileDialog, saveFile, runtimeHeartbeat, - gamepadsState, + getGamepadsState, updateMainProcess, runtimeReceiver, runtimeSaga, @@ -31,10 +31,12 @@ describe('filesystem sagas', () => { const type = 'open'; const expect = fromGenerator(assert, openFile(action)); expect.next().select(editorSavedState); - expect.next({ - savedCode: 'this was last code saved', - code: 'this is new modifications after last save', - }).call(unsavedDialog, type); + expect + .next({ + savedCode: 'this was last code saved', + code: 'this is new modifications after last save', + }) + .call(unsavedDialog, type); expect.next(1).call(openFileDialog); expect.next('mock-path').cps(fs.readFile, 'mock-path', 'utf8'); expect.next('mock-data').put(openFileSucceeded('mock-data', 'mock-path')); @@ -48,10 +50,12 @@ describe('filesystem sagas', () => { const type = 'create'; const expect = fromGenerator(assert, openFile(action)); expect.next().select(editorSavedState); - expect.next({ - savedCode: 'this was last code saved', - code: 'this is new modifications after last save', - }).call(unsavedDialog, type); + expect + .next({ + savedCode: 'this was last code saved', + code: 'this is new modifications after last save', + }) + .call(unsavedDialog, type); expect.next(1).put(openFileSucceeded('', null)); expect.next().returns(); }); @@ -71,10 +75,12 @@ describe('filesystem sagas', () => { const expect = fromGenerator(assert, saveFile(action)); expect.next().select(editorState); // follows to writeFile - expect.next({ - filepath: 'mock-path', - code: 'mock-code', - }).cps(fs.writeFile, 'mock-path', 'mock-code'); + expect + .next({ + filepath: 'mock-path', + code: 'mock-code', + }) + .cps(fs.writeFile, 'mock-path', 'mock-code'); }); it('should yield effects for saving file as (saveAs true)', () => { @@ -84,10 +90,12 @@ describe('filesystem sagas', () => { }; const expect = fromGenerator(assert, saveFile(action)); expect.next().select(editorState); - expect.next({ - filepath: 'mock-path', - code: 'mock-code', - }).call(saveFileDialog); + expect + .next({ + filepath: 'mock-path', + code: 'mock-code', + }) + .call(saveFileDialog); // follows to writeFile expect.next('mock-new-path').cps(fs.writeFile, 'mock-new-path', 'mock-code'); }); @@ -99,10 +107,12 @@ describe('filesystem sagas', () => { }; const expect = fromGenerator(assert, saveFile(action)); expect.next().select(editorState); - expect.next({ - filepath: null, - code: 'mock-code', - }).call(saveFileDialog); + expect + .next({ + filepath: null, + code: 'mock-code', + }) + .call(saveFileDialog); // follows to writeFile expect.next('mock-path').cps(fs.writeFile, 'mock-path', 'mock-code'); }); @@ -115,11 +125,13 @@ describe('runtime sagas', () => { update: take('PER_MESSAGE'), timeout: call(delay, TIMEOUT), }); - expect.next({ - update: { - type: 'PER_MESSAGE', - }, - }).put(runtimeConnect()); + expect + .next({ + update: { + type: 'PER_MESSAGE', + }, + }) + .put(runtimeConnect()); }); it('should yield effects for runtime heartbeat, disconnected', () => { @@ -128,14 +140,16 @@ describe('runtime sagas', () => { update: take('PER_MESSAGE'), timeout: call(delay, TIMEOUT), }); - expect.next({ - timeout: TIMEOUT, - }).put(runtimeDisconnect()); + expect + .next({ + timeout: TIMEOUT, + }) + .put(runtimeDisconnect()); }); it('should update main process of store changes', () => { const expect = fromGenerator(assert, updateMainProcess()); - expect.next().select(gamepadsState); + expect.next().select(getGamepadsState); }); it('should take data from runtimeReceiver and dispatch to store', () => { diff --git a/renderer/utils/utils.ts b/renderer/utils/utils.ts index d503ae43..eaec2ffa 100644 --- a/renderer/utils/utils.ts +++ b/renderer/utils/utils.ts @@ -1,7 +1,7 @@ import { app, remote } from 'electron'; import fs from 'fs'; -export const TIMEOUT = 5000; +export const TIMEOUT_MSEC = 5000; export const pathToName = (filepath: string) => { if (filepath !== null && filepath !== '') { @@ -27,7 +27,7 @@ export const getValidationState = (testIPAddress: string) => { export const uploadStatus = { RECEIVED: 0, SENT: 1, - ERROR: 2, + ERROR: 2 }; export const robotState = { @@ -38,7 +38,7 @@ export const robotState = { TELEOP: 2, TELEOPSTR: 'Tele-Operated', ESTOP: 3, - ESTOPSTR: 'ESTOP', + ESTOPSTR: 'ESTOP' }; // TODO: Synchronize this and the above state @@ -54,7 +54,7 @@ export const runtimeState = { AUTONOMOUS: 4, 4: 'Autonomous', ESTOP: 5, - 5: 'E-Stop', + 5: 'E-Stop' }; export const defaults = { @@ -62,14 +62,14 @@ export const defaults = { USERNAME: 'pi', PASSWORD: 'raspberry', IPADDRESS: '192.168.0.0', - STUDENTCODELOC: '/home/pi/runtime/executor/studentcode.py', + STUDENTCODELOC: '/home/pi/runtime/executor/studentcode.py' }; export const timings = { AUTO: 30, IDLE: 5, TELEOP: 120, - SEC: 1000, + SEC: 1000 }; export const windowInfo = { @@ -78,7 +78,7 @@ export const windowInfo = { CONSOLEPAD: 40, CONSOLESTART: 250, CONSOLEMAX: 350, - CONSOLEMIN: 100, + CONSOLEMIN: 100 }; export class Logger { @@ -104,11 +104,11 @@ export class Logger { log = (output: string) => { console.log(output); - this._write(output, `\n[${(new Date()).toString()}]`); - } + this._write(output, `\n[${new Date().toString()}]`); + }; debug = (output: string) => { - this._write(output, `\n[${(new Date()).toString()} DEBUG]`); - } + this._write(output, `\n[${new Date().toString()} DEBUG]`); + }; _write = (output: string, prefix: string) => { output = String(output); @@ -118,7 +118,7 @@ export class Logger { } else { // this.log_file.write('*'); } - } + }; } export let logging: Logger; // eslint-disable-line import/no-mutable-exports diff --git a/yarn.lock b/yarn.lock index 0dbf2d9c..f0f0f691 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,14 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/runtime-corejs2@^7.0.0": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.12.5.tgz#382ec38f0826365e96118e28b81249c1c61bace3" + integrity sha512-kt5YpZ7F5A05LOgQuaMXXmcxakK/qttf5C/E1BJPA3Kf5PanbjPzDoXN+PIslUnjUxpuKblCsXyP0QfMiqyKqA== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.1.2": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" @@ -340,6 +348,13 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/react@^16.9.11": + version "16.14.1" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.1.tgz#da2ecb638385614a5573e16e4aa7daf936dbead5" + integrity sha512-32mxrbX62m5b+lMTSzucFKNIr8Eq4T6T3rDVxYzKqyRwyfnPcwZppWW0YXUlPNPUE+r6phBtHXYRgr8ad/Zl9A== + dependencies: + "@types/prop-types" "*" + "@types/react@^16.9.43": version "16.9.43" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" @@ -1802,7 +1817,7 @@ babel-register@^6.26.0, babel-register@^6.9.0: mkdirp "^0.5.1" source-map-support "^0.4.15" -babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -2703,6 +2718,11 @@ core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895" integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A== +core-js@^2.6.5: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + core-js@^3.6.5: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" @@ -3101,7 +3121,7 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-helpers@^3.2.0, dom-helpers@^3.2.1, dom-helpers@^3.3.1: +dom-helpers@^3.2.0, dom-helpers@^3.2.1, dom-helpers@^3.3.1, dom-helpers@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== @@ -3547,6 +3567,11 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-react-hooks@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" + integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== + eslint-plugin-react@7.5.1: version "7.5.1" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz#52e56e8d80c810de158859ef07b880d2f56ee30b" @@ -5024,7 +5049,7 @@ into-stream@^3.1.0: from2 "^2.1.1" p-is-promise "^1.1.0" -invariant@^2.1.0, invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -5570,7 +5595,7 @@ junk@^3.1.0: resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== -keycode@^2.1.2: +keycode@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04" integrity sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ= @@ -7206,7 +7231,7 @@ prop-types@15.6.0: loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -7385,22 +7410,22 @@ react-ace@^9.1.3: lodash.isequal "^4.5.0" prop-types "^15.7.2" -react-bootstrap@0.32.0: - version "0.32.0" - resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-0.32.0.tgz#7f656be7b0f88e4bdda819135956bad10d3f167e" - integrity sha512-AbWq1qjDpuYZzXSF0N6oXwwlWa1MWNEhqH/d5I51Q4AN/zn8oTBqx7HgIICR0Jk6xGy76LzJQGr+31VP3ehfVw== +react-bootstrap@0.33.1: + version "0.33.1" + resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-0.33.1.tgz#e072592aa143b9792526281272eca754bc9a4940" + integrity sha512-qWTRravSds87P8WC82tETy2yIso8qDqlIm0czsrduCaYAFtHuyLu0XDbUlfLXeRzqgwm5sRk2wRaTNoiVkk/YQ== dependencies: - babel-runtime "^6.11.6" + "@babel/runtime-corejs2" "^7.0.0" classnames "^2.2.5" dom-helpers "^3.2.0" - invariant "^2.2.1" - keycode "^2.1.2" - prop-types "^15.5.10" + invariant "^2.2.4" + keycode "^2.2.0" + prop-types "^15.6.1" prop-types-extra "^1.0.1" - react-overlays "^0.8.0" + react-overlays "^0.9.0" react-prop-types "^0.4.0" react-transition-group "^2.0.0" - uncontrollable "^4.1.0" + uncontrollable "^7.0.2" warning "^3.0.0" react-dom@^16.13.1: @@ -7461,16 +7486,16 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-overlays@^0.8.0: - version "0.8.3" - resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.8.3.tgz#fad65eea5b24301cca192a169f5dddb0b20d3ac5" - integrity sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA== +react-overlays@^0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.9.2.tgz#51ab1c62ded5af4d279bd3b943999531bbd648da" + integrity sha512-wOi+WqO0acnUAMCbTTW06/GRkYjHdlvIoyX4bYkLvxKrLgl2kX9WzFVyBdwukl2jvN7I7oX7ZXAz7MNOWYdgCA== dependencies: classnames "^2.2.5" dom-helpers "^3.2.1" prop-types "^15.5.10" prop-types-extra "^1.0.1" - react-transition-group "^2.2.0" + react-transition-group "^2.2.1" warning "^3.0.0" react-prop-types@^0.4.0: @@ -7496,7 +7521,7 @@ react-redux@^7.2.1: prop-types "^15.7.2" react-is "^16.9.0" -react-transition-group@^2.0.0, react-transition-group@^2.2.0: +react-transition-group@^2.0.0: version "2.8.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.8.0.tgz#d6d8f635d81a0955b67348be5d017cff77d6c75f" integrity sha512-So23a1MPn8CGoW5WNU4l0tLiVkOFmeXSS1K4Roe+dxxqqHvI/2XBmj76jx+u96LHnQddWG7LX8QovPAainSmWQ== @@ -7506,6 +7531,16 @@ react-transition-group@^2.0.0, react-transition-group@^2.2.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" +react-transition-group@^2.2.1: + version "2.9.0" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" + integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== + dependencies: + dom-helpers "^3.4.0" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react-lifecycles-compat "^3.0.4" + react@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -9109,12 +9144,15 @@ ultron@~1.1.0: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== -uncontrollable@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-4.1.0.tgz#e0358291252e1865222d90939b19f2f49f81c1a9" - integrity sha1-4DWCkSUuGGUiLZCTmxny9J+Bwak= +uncontrollable@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.1.1.tgz#f67fed3ef93637126571809746323a9db815d556" + integrity sha512-EcPYhot3uWTS3w00R32R2+vS8Vr53tttrvMj/yA1uYRhf8hbTG2GyugGqWDY0qIskxn0uTTojVd6wPYW9ZEf8Q== dependencies: - invariant "^2.1.0" + "@babel/runtime" "^7.6.3" + "@types/react" "^16.9.11" + invariant "^2.2.4" + react-lifecycles-compat "^3.0.4" underscore@~1.6.0: version "1.6.0"