1 Commits

Author SHA1 Message Date
Róbert Kiss
38c60d9cc0 fix: keyboard description z-index 2019-08-03 11:29:30 +02:00
102 changed files with 12923 additions and 10636 deletions

2
.nvmrc
View File

@@ -1 +1 @@
12.0.0 10.11.0

View File

@@ -13,9 +13,7 @@ Firmware: 8.5.**4** [[release](https://github.com/UltimateHackingKeyboard/firmwa
- Implement the Kinetis bootloader protocol natively instead of relying on blhost. - Implement the Kinetis bootloader protocol natively instead of relying on blhost.
- Fix device recovery mode. - Fix device recovery mode.
- Correctly display whether the UHK is detected. - Correctly display whether the UHK is detected.
- Animate keyboard splitting, merging, and the presence of the left half.
- Don't disable input in the key action popover after adding a layer switch action, deleting it, and trying to edit it on its layer. - Don't disable input in the key action popover after adding a layer switch action, deleting it, and trying to edit it on its layer.
- Provide reasonable default mouse settings for Macs.
- Don't change tab immediately upon closing the key action popover. - Don't change tab immediately upon closing the key action popover.
- Fix UI glitch that occurrs when hitting Tab after updating keymap description. - Fix UI glitch that occurrs when hitting Tab after updating keymap description.
- Make the Agent icon slightly smaller to be consistent with most application icons. - Make the Agent icon slightly smaller to be consistent with most application icons.

View File

@@ -6,5 +6,3 @@ Before submitting a new issue, make sure to do the following:
3. Use Agent to update to the latest firmware: 3. Use Agent to update to the latest firmware:
https://github.com/UltimateHackingKeyboard/firmware/releases/latest https://github.com/UltimateHackingKeyboard/firmware/releases/latest
4. Try to reproduce the issue, and only report it if it still persists. 4. Try to reproduce the issue, and only report it if it still persists.
`npm audit` related issues will be closed due to https://github.com/UltimateHackingKeyboard/agent/blob/master/NPM_UPDATES.md

View File

@@ -1,8 +0,0 @@
We get requests from time to time to update our NPM dependencies because they contain vulnerabilities according to `npm audit`. Such issues will be closed without further consideration due to the following reasons:
1. Usually, the affected packages are not runtime dependencies of Agent, but devDependencies which are only needed for developing Agent.
2. Often times, 3rd party packages are affected by vulnerabilities which we cannot fix.
3. We can't just blindly update all of the packages because that'd likely break Agent as it has happened in the past. Each of the updates must be carefully tested, and we don't have the manpower to do it on a daily basis.
4. Sometimes `npm audit` signals false vulnerabilities.
We routinely update our dependencies on a best effort basis.

View File

@@ -12,7 +12,7 @@ Agent is the configuration application of the [Ultimate Hacking Keyboard](https:
### Step 1: Build Dependencies ### Step 1: Build Dependencies
You'll need Node.js 12. Use your OS package manager to install it. [Check the NodeJS site for more info.](https://nodejs.org/en/download/package-manager/ "Installing Node.js via package manager") Mac OS users can simply `brew install node` to get both. Should you need multiple Node.js versions on the same computer, use Node Version Manager for [Mac/Linux](https://github.com/creationix/nvm) or for [Windows](https://github.com/coreybutler/nvm-windows) You'll need Node.js LTS. Use your OS package manager to install it. [Check the NodeJS site for more info.](https://nodejs.org/en/download/package-manager/ "Installing Node.js via package manager") Mac OS users can simply `brew install node` to get both. Should you need multiple Node.js versions on the same computer, use Node Version Manager for [Mac/Linux](https://github.com/creationix/nvm) or for [Windows](https://github.com/coreybutler/nvm-windows)
You'll also need `libusb`. You'll also need `libusb`.
On debian-based linux distros, `apt-get install libusb-dev libudev-dev g++` is sufficient. On debian-based linux distros, `apt-get install libusb-dev libudev-dev g++` is sufficient.

View File

@@ -7,7 +7,7 @@ environment:
secure: 3IebpEKmC39codi1wT6dXx8mql4/mCL1JzZ7lir7GQ5MWRnCxlED2OXbiKHHigDV secure: 3IebpEKmC39codi1wT6dXx8mql4/mCL1JzZ7lir7GQ5MWRnCxlED2OXbiKHHigDV
CSC_LINK: c:\projects\uhk-agent\scripts\certs\windows-cert.p12 CSC_LINK: c:\projects\uhk-agent\scripts\certs\windows-cert.p12
matrix: matrix:
- nodejs_version: "12.0.0" - nodejs_version: "10.11.0"
cache: cache:
- node_modules -> package.json - node_modules -> package.json

11843
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,9 +4,9 @@
"author": "Ultimate Gadget Laboratories", "author": "Ultimate Gadget Laboratories",
"main": "electron/dist/electron-main.js", "main": "electron/dist/electron-main.js",
"version": "1.2.13", "version": "1.2.13",
"firmwareVersion": "8.6.0", "firmwareVersion": "8.5.4",
"deviceProtocolVersion": "4.5.0", "deviceProtocolVersion": "4.4.0",
"userConfigVersion": "4.1.1", "userConfigVersion": "4.0.1",
"hardwareConfigVersion": "1.0.0", "hardwareConfigVersion": "1.0.0",
"description": "Agent is the configuration application of the Ultimate Hacking Keyboard.", "description": "Agent is the configuration application of the Ultimate Hacking Keyboard.",
"repository": { "repository": {
@@ -15,11 +15,11 @@
}, },
"license": "GPL-3.0", "license": "GPL-3.0",
"engines": { "engines": {
"node": ">=12.0.0 <13.0.0", "node": ">=10.2.1 <11.0.0",
"npm": ">=6.9.0 <7.0.0" "npm": ">=6.4.0 <7.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/decompress": "4.2.3", "@types/decompress": "4.2.0",
"@types/electron-devtools-installer": "2.0.2", "@types/electron-devtools-installer": "2.0.2",
"@types/electron-settings": "3.0.0", "@types/electron-settings": "3.0.0",
"@types/file-saver": "0.0.1", "@types/file-saver": "0.0.1",
@@ -27,42 +27,47 @@
"@types/jasmine": "3.3.12", "@types/jasmine": "3.3.12",
"@types/jasminewd2": "2.0.3", "@types/jasminewd2": "2.0.3",
"@types/jquery": "3.3.29", "@types/jquery": "3.3.29",
"@types/jsonfile": "5.0.0", "@types/jsonfile": "4.0.1",
"@types/lodash": "4.14.136", "@types/lodash": "4.14.136",
"@types/node": "8.0.53", "@types/node": "8.0.53",
"@types/node-hid": "0.7.2", "@types/node-hid": "0.7.0",
"@types/request": "2.0.8", "@types/request": "2.0.8",
"@types/semver": "5.5.0", "@types/semver": "5.5.0",
"@types/tmp": "0.0.33", "@types/tmp": "0.0.33",
"autoprefixer": "6.5.3",
"buffer": "5.0.6", "buffer": "5.0.6",
"check-node-version": "4.0.1", "check-node-version": "^3.2.0",
"copy-webpack-plugin": "5.0.0", "copy-webpack-plugin": "5.0.0",
"copyfiles": "2.1.1", "copyfiles": "^2.0.0",
"core-js": "2.4.1", "core-js": "2.4.1",
"cross-env": "5.0.5", "cross-env": "5.0.5",
"decompress": "4.2.0", "decompress": "4.2.0",
"decompress-tarbz2": "4.1.1", "decompress-tarbz2": "4.1.1",
"devtron": "1.4.0", "devtron": "1.4.0",
"electron": "5.0.9", "electron": "4.2.8",
"electron-builder": "20.44.4", "electron-builder": "20.34.0",
"electron-debug": "1.5.0", "electron-debug": "1.5.0",
"electron-devtools-installer": "2.2.3", "electron-devtools-installer": "2.2.3",
"electron-log": "2.2.16", "electron-log": "2.2.16",
"electron-rebuild": "1.8.6", "electron-rebuild": "1.8.5",
"electron-settings": "3.1.4", "electron-settings": "3.1.4",
"electron-updater": "4.1.2", "electron-updater": "2.21.4",
"exports-loader": "0.6.3",
"file-loader": "0.10.0",
"fs-extra": "8.1.0", "fs-extra": "8.1.0",
"gh-pages": "2.0.1", "gh-pages": "2.0.1",
"html-webpack-plugin": "3.2.0",
"jasmine": "3.4.0", "jasmine": "3.4.0",
"jasmine-core": "3.4.0", "jasmine-core": "3.4.0",
"jasmine-node": "3.0.0", "jasmine-node": "3.0.0",
"jasmine-ts": "0.3.0", "jasmine-ts": "0.3.0",
"jsonfile": "5.0.0", "jsonfile": "4.0.0",
"lerna": "3.16.4", "lerna": "3.16.4",
"lodash": "4.17.15", "lodash": "4.17.15",
"node-hid": "0.7.9", "node-hid": "0.7.8",
"npm-run-all": "4.1.5", "npm-run-all": "4.0.2",
"nrf-intel-hex": "1.3.0", "nrf-intel-hex": "1.3.0",
"postcss-url": "8.0.0",
"pre-commit": "1.2.2", "pre-commit": "1.2.2",
"request": "2.88.0", "request": "2.88.0",
"rimraf": "2.6.1", "rimraf": "2.6.1",
@@ -91,13 +96,11 @@
"server:electron": "lerna exec --scope uhk-web npm run server:renderer", "server:electron": "lerna exec --scope uhk-web npm run server:renderer",
"electron": "lerna exec --scope uhk-agent npm start", "electron": "lerna exec --scope uhk-agent npm start",
"electron:spe": "lerna exec --scope uhk-agent npm run electron:spe", "electron:spe": "lerna exec --scope uhk-agent npm run electron:spe",
"electron:kboot": "lerna exec --scope uhk-agent npm run electron:kboot",
"pack": "node ./scripts/release.js", "pack": "node ./scripts/release.js",
"sprites": "node ./scripts/generate-svg-sprites", "sprites": "node ./scripts/generate-svg-sprites",
"release": "node ./scripts/release.js", "release": "node ./scripts/release.js",
"clean": "lerna exec rimraf ./node_modules ./dist && rimraf ./node_modules ./dist ./tmp", "clean": "lerna exec rimraf ./node_modules ./dist && rimraf ./node_modules ./dist ./tmp",
"predeploy-gh-pages": "lerna run build:web --scope=uhk-web", "predeploy-gh-pages": "lerna run build:web --scope=uhk-web",
"deploy-gh-pages": "gh-pages -d packages/uhk-web/dist", "deploy-gh-pages": "gh-pages -d packages/uhk-web/dist"
"convert-user-config-to-bin": "node -r ts-node/register ./packages/usb/user-config-json-to-bin.ts"
} }
} }

View File

@@ -24,16 +24,13 @@
} }
}, },
"bindings": { "bindings": {
"version": "1.5.0", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew=="
"requires": {
"file-uri-to-path": "1.0.0"
}
}, },
"bl": { "bl": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
"requires": { "requires": {
"readable-stream": "^2.3.5", "readable-stream": "^2.3.5",
@@ -72,9 +69,9 @@
} }
}, },
"chownr": { "chownr": {
"version": "1.1.2", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
@@ -140,11 +137,6 @@
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
}, },
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"fs-constants": { "fs-constants": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -181,9 +173,9 @@
"integrity": "sha512-dDlJhYk8BAmH1HDncTjCt6xOm2+kT+MxGhRKB+mUoF8nocDzPAgZPEWTRI9QgkGvbDkbJgCqyxweGlIV0yhbUQ==" "integrity": "sha512-dDlJhYk8BAmH1HDncTjCt6xOm2+kT+MxGhRKB+mUoF8nocDzPAgZPEWTRI9QgkGvbDkbJgCqyxweGlIV0yhbUQ=="
}, },
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@@ -210,12 +202,12 @@
}, },
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
@@ -223,7 +215,7 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
} }
} }
@@ -234,9 +226,9 @@
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}, },
"nan": { "nan": {
"version": "2.14.0", "version": "2.12.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw=="
}, },
"napi-build-utils": { "napi-build-utils": {
"version": "1.0.1", "version": "1.0.1",
@@ -244,21 +236,21 @@
"integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==" "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA=="
}, },
"node-abi": { "node-abi": {
"version": "2.11.0", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.11.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.1.tgz",
"integrity": "sha512-kuy/aEg75u40v378WRllQ4ZexaXJiCvB68D2scDXclp/I4cRq6togpbOoKhmN07tns9Zldu51NNERo0wehfX9g==", "integrity": "sha512-oDbFc7vCFx0RWWCweTer3hFm1u+e60N5FtGnmRV6QqvgATGFH/XRR6vqWIeBVosCYCqt6YdIr2L0exLZuEdVcQ==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
} }
}, },
"node-hid": { "node-hid": {
"version": "0.7.9", "version": "0.7.4",
"resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.9.tgz", "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.4.tgz",
"integrity": "sha512-vJnonTqmq3frCyTumJqG4g2IZcny3ynkfmbfDfQ90P3ZhRzcWYS/Um1ux6HFmAxmkaQnrZqIYHcGpL7kdqY8jA==", "integrity": "sha512-gvgNDPoszObn7avIDYMUvVv1T0xQB4/CZFJWckra/LXAc0qHYho4M1LCnCKlLIocL2R5/3qGv0J4AjRMdwgjxg==",
"requires": { "requires": {
"bindings": "^1.5.0", "bindings": "^1.3.0",
"nan": "^2.13.2", "nan": "^2.10.0",
"prebuild-install": "^5.3.0" "prebuild-install": "^5.2.1"
} }
}, },
"noop-logger": { "noop-logger": {
@@ -297,13 +289,13 @@
}, },
"os-homedir": { "os-homedir": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
}, },
"prebuild-install": { "prebuild-install": {
"version": "5.3.0", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.0.tgz", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.2.2.tgz",
"integrity": "sha512-aaLVANlj4HgZweKttFNUVNRxDukytuIuxeK2boIMHjagNJCiVKWFsKF4tCE3ql3GbrD2tExPQ7/pwtEJcHNZeg==", "integrity": "sha512-4e8VJnP3zJdZv/uP0eNWmr2r9urp4NECw7Mt1OSAi3rcLrbBRxGiAkfUFtre2MhQ5wfREAjRV+K1gubvs/GPsA==",
"requires": { "requires": {
"detect-libc": "^1.0.3", "detect-libc": "^1.0.3",
"expand-template": "^2.0.3", "expand-template": "^2.0.3",
@@ -311,7 +303,7 @@
"minimist": "^1.2.0", "minimist": "^1.2.0",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"napi-build-utils": "^1.0.1", "napi-build-utils": "^1.0.1",
"node-abi": "^2.7.0", "node-abi": "^2.2.0",
"noop-logger": "^0.1.1", "noop-logger": "^0.1.1",
"npmlog": "^4.0.1", "npmlog": "^4.0.1",
"os-homedir": "^1.0.1", "os-homedir": "^1.0.1",
@@ -324,9 +316,9 @@
} }
}, },
"process-nextick-args": { "process-nextick-args": {
"version": "2.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
}, },
"pump": { "pump": {
"version": "2.0.1", "version": "2.0.1",
@@ -350,7 +342,7 @@
}, },
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": { "requires": {
"core-util-is": "~1.0.0", "core-util-is": "~1.0.0",
@@ -368,9 +360,9 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}, },
"semver": { "semver": {
"version": "5.7.1", "version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
@@ -399,7 +391,7 @@
}, },
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
@@ -409,7 +401,7 @@
}, },
"string_decoder": { "string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": { "requires": {
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
@@ -417,7 +409,7 @@
}, },
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
@@ -524,9 +516,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
} }
} }
} }

View File

@@ -9,11 +9,15 @@
"url": "git@github.com:UltimateHackingKeyboard/agent.git" "url": "git@github.com:UltimateHackingKeyboard/agent.git"
}, },
"license": "GPL-3.0", "license": "GPL-3.0",
"engines": {
"node": ">=8.12.0 <9.0.0",
"npm": ">=6.4.1 <7.0.0"
},
"dependencies": { "dependencies": {
"debug": "^4.1.1", "debug": "^4.1.1",
"byte-data": "^16.0.3", "byte-data": "^16.0.3",
"tslib": "^1.10.0", "tslib": "^1.10.0",
"node-hid": ">= 0.7.9" "node-hid": ">= 0.7.3"
}, },
"peer-dependencies": {}, "peer-dependencies": {},
"scripts": { "scripts": {

View File

@@ -12,19 +12,15 @@ export class KBoot {
} }
open(): void { open(): void {
logger('Open peripheral');
this.peripheral.open(); this.peripheral.open();
} }
close(): void { close(): void {
logger('Close peripheral');
this.peripheral.close(); this.peripheral.close();
} }
// ================= Read properties ================== // ================= Read properties ==================
async getProperty(property: Properties, memoryId = MemoryIds.Internal): Promise<CommandResponse> { async getProperty(property: Properties, memoryId = MemoryIds.Internal): Promise<CommandResponse> {
logger('Start read memory %o', { property, memoryId });
const command: CommandOption = { const command: CommandOption = {
command: Commands.GetProperty, command: Commands.GetProperty,
params: [ params: [
@@ -36,17 +32,14 @@ export class KBoot {
const response = await this.peripheral.sendCommand(command); const response = await this.peripheral.sendCommand(command);
if (response.tag !== ResponseTags.Property) { if (response.tag !== ResponseTags.Property) {
logger('Response tag is not property response: %d', property);
throw new Error('Response tag is not property response'); throw new Error('Response tag is not property response');
} }
if (response.code === ResponseCodes.UnknownProperty) { if (response.code === ResponseCodes.UnknownProperty) {
logger('Unknown property %d', response.code);
throw new Error('Unknown property!'); throw new Error('Unknown property!');
} }
if (response.code !== ResponseCodes.Success) { if (response.code !== ResponseCodes.Success) {
logger('Unknown error %d', response.code);
throw new Error(`Unknown error. Error code:${response.code}`); throw new Error(`Unknown error. Error code:${response.code}`);
} }
@@ -54,8 +47,6 @@ export class KBoot {
} }
async getBootloaderVersion(): Promise<BootloaderVersion> { async getBootloaderVersion(): Promise<BootloaderVersion> {
logger('Start to read Bootloader Version');
const response = await this.getProperty(Properties.BootloaderVersion); const response = await this.getProperty(Properties.BootloaderVersion);
const version: BootloaderVersion = { const version: BootloaderVersion = {
@@ -73,9 +64,7 @@ export class KBoot {
// ================= End read properties ================== // ================= End read properties ==================
async flashSecurityDisable(key: number[]): Promise<void> { async flashSecurityDisable(key: number[]): Promise<void> {
logger('Start flash security disable %o', { key });
if (key.length !== 8) { if (key.length !== 8) {
logger('Error: Flash security key must be 8 byte. %o', key);
throw new Error('Flash security key must be 8 byte'); throw new Error('Flash security key must be 8 byte');
} }
@@ -87,18 +76,15 @@ export class KBoot {
const response = await this.peripheral.sendCommand(command); const response = await this.peripheral.sendCommand(command);
if (response.tag !== ResponseTags.Generic) { if (response.tag !== ResponseTags.Generic) {
logger('Response tag is not generic response: %d', response.tag);
throw new Error('Response tag is not generic response'); throw new Error('Response tag is not generic response');
} }
if (response.code !== ResponseCodes.Success) { if (response.code !== ResponseCodes.Success) {
logger('Can not disable flash security: %d', response.code);
throw new Error(`Can not disable flash security`); throw new Error(`Can not disable flash security`);
} }
} }
async flashEraseRegion(startAddress: number, count: number): Promise<void> { async flashEraseRegion(startAddress: number, count: number): Promise<void> {
logger('Start flash erase region');
const command: CommandOption = { const command: CommandOption = {
command: Commands.FlashEraseRegion, command: Commands.FlashEraseRegion,
params: [ params: [
@@ -110,18 +96,15 @@ export class KBoot {
const response = await this.peripheral.sendCommand(command); const response = await this.peripheral.sendCommand(command);
if (response.tag !== ResponseTags.Generic) { if (response.tag !== ResponseTags.Generic) {
logger('Response tag is not generic response: %d', response.tag);
throw new Error('Response tag is not generic response'); throw new Error('Response tag is not generic response');
} }
if (response.code !== ResponseCodes.Success) { if (response.code !== ResponseCodes.Success) {
logger('Can not flash erase region: %d', response.code); throw new Error(`Can not disable flash security`);
throw new Error(`Can not flash erase region`);
} }
} }
async flashEraseAllUnsecure(): Promise<void> { async flashEraseAllUnsecure(): Promise<void> {
logger('Start flash erase all unsecure');
const command: CommandOption = { const command: CommandOption = {
command: Commands.FlashEraseAllUnsecure, command: Commands.FlashEraseAllUnsecure,
params: [] params: []
@@ -130,23 +113,19 @@ export class KBoot {
const response = await this.peripheral.sendCommand(command); const response = await this.peripheral.sendCommand(command);
if (response.tag !== ResponseTags.Generic) { if (response.tag !== ResponseTags.Generic) {
logger('Response tag is not generic response: %d', response.tag);
throw new Error('Response tag is not generic response'); throw new Error('Response tag is not generic response');
} }
if (response.code !== ResponseCodes.Success) { if (response.code !== ResponseCodes.Success) {
logger('Can not flash erase all unsecure: %d', response.code); throw new Error(`Can not disable flash security`);
throw new Error(`Can not flash erase all unsecure`);
} }
} }
async readMemory(startAddress: number, count: number): Promise<any> { async readMemory(startAddress: number, count: number): Promise<any> {
logger('Start read memory %o', { startAddress, count });
return this.peripheral.readMemory(startAddress, count); return this.peripheral.readMemory(startAddress, count);
} }
async writeMemory(options: DataOption): Promise<void> { async writeMemory(options: DataOption): Promise<void> {
logger('Start write memory %o', { options });
return this.peripheral.writeMemory(options); return this.peripheral.writeMemory(options);
} }
@@ -154,7 +133,6 @@ export class KBoot {
* Reset the bootloader * Reset the bootloader
*/ */
async reset(): Promise<void> { async reset(): Promise<void> {
logger('Start reset the bootloader');
const command: CommandOption = { const command: CommandOption = {
command: Commands.Reset, command: Commands.Reset,
params: [] params: []
@@ -176,12 +154,10 @@ export class KBoot {
} }
if (response.tag !== ResponseTags.Generic) { if (response.tag !== ResponseTags.Generic) {
logger('Response tag is not generic response: %d', response.tag);
throw new Error('Response tag is not generic response'); throw new Error('Response tag is not generic response');
} }
if (response.code !== ResponseCodes.Success) { if (response.code !== ResponseCodes.Success) {
logger('Unknown error %d', response.code);
throw new Error(`Unknown error. Error code:${response.code}`); throw new Error(`Unknown error. Error code:${response.code}`);
} }
} }
@@ -192,9 +168,8 @@ export class KBoot {
* @param [speed=64] - Speed of the I2C * @param [speed=64] - Speed of the I2C
*/ */
async configureI2c(address: number, speed = 64): Promise<void> { async configureI2c(address: number, speed = 64): Promise<void> {
logger('Start configure I2C', { address, speed });
if (address > 127) { if (address > 127) {
logger('Only 7-bit i2c address is supported');
throw new Error('Only 7-bit i2c address is supported'); throw new Error('Only 7-bit i2c address is supported');
} }
@@ -209,12 +184,10 @@ export class KBoot {
const response = await this.peripheral.sendCommand(command); const response = await this.peripheral.sendCommand(command);
if (response.tag !== ResponseTags.Generic) { if (response.tag !== ResponseTags.Generic) {
logger('Response tag is not generic response: %d', response.tag);
throw new Error('Response tag is not generic response'); throw new Error('Response tag is not generic response');
} }
if (response.code !== ResponseCodes.Success) { if (response.code !== ResponseCodes.Success) {
logger('Unknown error %d', response.code);
throw new Error(`Unknown error. Error code:${response.code}`); throw new Error(`Unknown error. Error code:${response.code}`);
} }
} }

View File

@@ -55,8 +55,6 @@ export class UsbPeripheral implements Peripheral {
close(): void { close(): void {
if (this._device) { if (this._device) {
this._device.close(); this._device.close();
this._device.removeAllListeners('data');
this._device.removeAllListeners('error');
this._device = undefined; this._device = undefined;
} }
} }
@@ -224,7 +222,6 @@ export class UsbPeripheral implements Peripheral {
} }
private _readFromBuffer(bufferName: string, byte: number, timeout: number): Promise<Buffer> { private _readFromBuffer(bufferName: string, byte: number, timeout: number): Promise<Buffer> {
logger('start read from buffer %o', { bufferName, byte, timeout });
return new Promise<Buffer>(async (resolve, reject) => { return new Promise<Buffer>(async (resolve, reject) => {
const startTime = new Date(); const startTime = new Date();
while (startTime.getTime() + timeout > new Date().getTime()) { while (startTime.getTime() + timeout > new Date().getTime()) {
@@ -269,7 +266,6 @@ export class UsbPeripheral implements Peripheral {
} }
private async _getNextCommandResponse(): Promise<CommandResponse> { private async _getNextCommandResponse(): Promise<CommandResponse> {
logger('Start read next command response');
const response = await this._readFromCommandStream(); const response = await this._readFromCommandStream();
const commandResponse = decodeCommandResponse(response); const commandResponse = decodeCommandResponse(response);
logger('next command response: %o', commandResponse); logger('next command response: %o', commandResponse);

View File

@@ -32,9 +32,9 @@
} }
}, },
"base64-js": { "base64-js": {
"version": "1.3.1", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
}, },
"bindings": { "bindings": {
"version": "1.5.0", "version": "1.5.0",
@@ -54,42 +54,24 @@
} }
}, },
"buffer": { "buffer": {
"version": "5.4.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.0.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz",
"integrity": "sha512-Xpgy0IwHK2N01ncykXTy6FpCWuM+CJSHoPVBLyNqyrWxsedpLvwsYUhf0ME3WRFNUhos0dMamz9cOS/xRDtU5g==", "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=",
"requires": { "requires": {
"base64-js": "^1.0.2", "base64-js": "0.0.8",
"ieee754": "^1.1.4" "ieee754": "^1.1.4",
"isarray": "^1.0.0"
} }
}, },
"buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"requires": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
},
"buffer-crc32": { "buffer-crc32": {
"version": "0.2.13", "version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
}, },
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
},
"chownr": { "chownr": {
"version": "1.1.2", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
@@ -249,9 +231,9 @@
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
}, },
"fd-slicer": { "fd-slicer": {
"version": "1.1.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
"requires": { "requires": {
"pend": "~1.2.0" "pend": "~1.2.0"
} }
@@ -285,11 +267,6 @@
} }
} }
}, },
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"gauge": { "gauge": {
"version": "2.7.4", "version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -320,9 +297,9 @@
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
}, },
"graceful-fs": { "graceful-fs": {
"version": "4.2.1", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==" "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
}, },
"graceful-readlink": { "graceful-readlink": {
"version": "1.0.1", "version": "1.0.1",
@@ -335,14 +312,14 @@
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
}, },
"ieee754": { "ieee754": {
"version": "1.1.13", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg=="
}, },
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@@ -373,9 +350,9 @@
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
}, },
"make-dir": { "make-dir": {
"version": "1.3.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz",
"integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==",
"requires": { "requires": {
"pify": "^3.0.0" "pify": "^3.0.0"
}, },
@@ -423,17 +400,17 @@
"integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==" "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA=="
}, },
"node-abi": { "node-abi": {
"version": "2.11.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.11.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.8.0.tgz",
"integrity": "sha512-kuy/aEg75u40v378WRllQ4ZexaXJiCvB68D2scDXclp/I4cRq6togpbOoKhmN07tns9Zldu51NNERo0wehfX9g==", "integrity": "sha512-1/aa2clS0pue0HjckL62CsbhWWU35HARvBDXcJtYKbYR7LnIutmpxmXbuDMV9kEviD2lP/wACOgWmmwljghHyQ==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
} }
}, },
"node-hid": { "node-hid": {
"version": "0.7.9", "version": "0.7.8",
"resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.9.tgz", "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.8.tgz",
"integrity": "sha512-vJnonTqmq3frCyTumJqG4g2IZcny3ynkfmbfDfQ90P3ZhRzcWYS/Um1ux6HFmAxmkaQnrZqIYHcGpL7kdqY8jA==", "integrity": "sha512-79Z9hw/pqIDp0kxvb353ivGgslo4i0hYQTcCqfRFxIJSO2gF9VtPla5uQY/9jTcDlON5O5YaqxbdH+8bs+m+1Q==",
"requires": { "requires": {
"bindings": "^1.5.0", "bindings": "^1.5.0",
"nan": "^2.13.2", "nan": "^2.13.2",
@@ -531,9 +508,9 @@
} }
}, },
"process-nextick-args": { "process-nextick-args": {
"version": "2.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
}, },
"pump": { "pump": {
"version": "2.0.1", "version": "2.0.1",
@@ -567,19 +544,12 @@
"safe-buffer": "~5.1.1", "safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1", "string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1" "util-deprecate": "~1.0.1"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
} }
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.2.0", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
}, },
"seek-bzip": { "seek-bzip": {
"version": "1.0.5", "version": "1.0.5",
@@ -590,9 +560,9 @@
} }
}, },
"semver": { "semver": {
"version": "5.7.1", "version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
@@ -635,13 +605,6 @@
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": { "requires": {
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
} }
}, },
"strip-ansi": { "strip-ansi": {
@@ -693,16 +656,13 @@
} }
}, },
"tar-stream": { "tar-stream": {
"version": "1.6.2", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz",
"integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==",
"requires": { "requires": {
"bl": "^1.0.0", "bl": "^1.0.0",
"buffer-alloc": "^1.2.0",
"end-of-stream": "^1.0.0", "end-of-stream": "^1.0.0",
"fs-constants": "^1.0.0", "readable-stream": "^2.0.0",
"readable-stream": "^2.3.0",
"to-buffer": "^1.1.1",
"xtend": "^4.0.0" "xtend": "^4.0.0"
} }
}, },
@@ -738,11 +698,6 @@
"os-tmpdir": "~1.0.2" "os-tmpdir": "~1.0.2"
} }
}, },
"to-buffer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
},
"tslib": { "tslib": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
@@ -762,12 +717,12 @@
"integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0="
}, },
"unbzip2-stream": { "unbzip2-stream": {
"version": "1.3.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
"integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
"requires": { "requires": {
"buffer": "^5.2.1", "buffer": "^3.0.1",
"through": "^2.3.8" "through": "^2.3.6"
} }
}, },
"util-deprecate": { "util-deprecate": {
@@ -794,17 +749,17 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}, },
"yauzl": { "yauzl": {
"version": "2.10.0", "version": "2.9.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz",
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=",
"requires": { "requires": {
"buffer-crc32": "~0.2.3", "buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0" "fd-slicer": "~1.0.1"
} }
} }
} }

View File

@@ -17,7 +17,7 @@
"command-line-args": "4.0.7", "command-line-args": "4.0.7",
"decompress": "4.2.0", "decompress": "4.2.0",
"decompress-bzip2": "4.0.0", "decompress-bzip2": "4.0.0",
"node-hid": "0.7.9", "node-hid": "0.7.8",
"sudo-prompt": "7.0.0", "sudo-prompt": "7.0.0",
"tmp": "0.0.33", "tmp": "0.0.33",
"tslib": "1.10.0", "tslib": "1.10.0",
@@ -29,7 +29,6 @@
"scripts": { "scripts": {
"start": "cross-env DEBUG=kboot* electron ./dist/electron-main.js", "start": "cross-env DEBUG=kboot* electron ./dist/electron-main.js",
"electron:spe": "electron ./dist/electron-main.js --spe", "electron:spe": "electron ./dist/electron-main.js --spe",
"electron:kboot": "cross-env DEBUG=kboot* electron ./dist/electron-main.js --useKboot",
"build": "webpack && npm run install:build-deps && npm run build:usb && npm run download-firmware && npm run copy-to-tmp-folder", "build": "webpack && npm run install:build-deps && npm run build:usb && npm run download-firmware && npm run copy-to-tmp-folder",
"build:usb": "electron-rebuild -w node-hid -p -m ./dist", "build:usb": "electron-rebuild -w node-hid -p -m ./dist",
"lint": "tslint --project tsconfig.json", "lint": "tslint --project tsconfig.json",

View File

@@ -11,7 +11,6 @@ import * as commandLineArgs from 'command-line-args';
import { UhkHidDevice, UhkOperations } from 'uhk-usb'; import { UhkHidDevice, UhkOperations } from 'uhk-usb';
// import { ElectronDataStorageRepositoryService } from './services/electron-datastorage-repository.service'; // import { ElectronDataStorageRepositoryService } from './services/electron-datastorage-repository.service';
import { CommandLineArgs, LogRegExps } from 'uhk-common'; import { CommandLineArgs, LogRegExps } from 'uhk-common';
import { UhkBlhost } from 'uhk-usb';
import { DeviceService } from './services/device.service'; import { DeviceService } from './services/device.service';
import { logger } from './services/logger.service'; import { logger } from './services/logger.service';
import { AppUpdateService } from './services/app-update.service'; import { AppUpdateService } from './services/app-update.service';
@@ -23,8 +22,7 @@ import { loadWindowState, saveWindowState } from './util/window';
const optionDefinitions = [ const optionDefinitions = [
{name: 'addons', type: Boolean}, {name: 'addons', type: Boolean},
{name: 'spe', type: Boolean}, // simulate privilege escalation error {name: 'spe', type: Boolean} // simulate privilege escalation error
{name: 'useKboot', type: Boolean} // If it is true use kboot package instead of blhost for firmware upgrade
]; ];
const options: CommandLineArgs = commandLineArgs(optionDefinitions); const options: CommandLineArgs = commandLineArgs(optionDefinitions);
@@ -38,7 +36,6 @@ let win: Electron.BrowserWindow;
autoUpdater.logger = logger; autoUpdater.logger = logger;
let deviceService: DeviceService; let deviceService: DeviceService;
let uhkBlhost: UhkBlhost;
let uhkHidDeviceService: UhkHidDevice; let uhkHidDeviceService: UhkHidDevice;
let uhkOperations: UhkOperations; let uhkOperations: UhkOperations;
let appUpdateService: AppUpdateService; let appUpdateService: AppUpdateService;
@@ -103,9 +100,8 @@ function createWindow() {
setMenu(win); setMenu(win);
uhkHidDeviceService = new UhkHidDevice(logger, options, packagesDir); uhkHidDeviceService = new UhkHidDevice(logger, options, packagesDir);
uhkBlhost = new UhkBlhost(logger, packagesDir); uhkOperations = new UhkOperations(logger, uhkHidDeviceService, packagesDir);
uhkOperations = new UhkOperations(logger, uhkBlhost, uhkHidDeviceService, packagesDir); deviceService = new DeviceService(logger, win, uhkHidDeviceService, uhkOperations, packagesDir);
deviceService = new DeviceService(logger, win, uhkHidDeviceService, uhkOperations, packagesDir, options);
appUpdateService = new AppUpdateService(logger, win, app); appUpdateService = new AppUpdateService(logger, win, app);
appService = new AppService(logger, win, deviceService, options, uhkHidDeviceService); appService = new AppService(logger, win, deviceService, options, uhkHidDeviceService);
sudoService = new SudoService(logger, options); sudoService = new SudoService(logger, options);

View File

@@ -1,4 +1,4 @@
import { app, BrowserWindow, Menu, MenuItemConstructorOptions, systemPreferences } from 'electron'; import { app, BrowserWindow, Menu, systemPreferences } from 'electron';
import * as isDev from 'electron-is-dev'; import * as isDev from 'electron-is-dev';
export const setMenu = (win: BrowserWindow): void => { export const setMenu = (win: BrowserWindow): void => {
@@ -8,7 +8,7 @@ export const setMenu = (win: BrowserWindow): void => {
return; return;
} }
const template: MenuItemConstructorOptions[] = [ const template = [
{ {
label: app.getName(), label: app.getName(),
submenu: [ submenu: [

View File

@@ -14,6 +14,6 @@
"npm": ">=5.1.0 <6.0.0" "npm": ">=5.1.0 <6.0.0"
}, },
"dependencies": { "dependencies": {
"node-hid": "0.7.9" "node-hid": "0.7.8"
} }
} }

View File

@@ -1,7 +1,6 @@
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { import {
CommandLineArgs,
ConfigurationReply, ConfigurationReply,
DeviceConnectionState, DeviceConnectionState,
FirmwareUpgradeIpcResponse, FirmwareUpgradeIpcResponse,
@@ -42,8 +41,7 @@ export class DeviceService {
private win: Electron.BrowserWindow, private win: Electron.BrowserWindow,
private device: UhkHidDevice, private device: UhkHidDevice,
private operations: UhkOperations, private operations: UhkOperations,
private rootDir: string, private rootDir: string) {
private options: CommandLineArgs) {
this.startPollUhkDevice(); this.startPollUhkDevice();
this.uhkDevicePoller() this.uhkDevicePoller()
.catch(error => { .catch(error => {
@@ -184,25 +182,15 @@ export class DeviceService {
const packageJson = await getPackageJsonFromPathAsync(firmwarePathData.packageJsonPath); const packageJson = await getPackageJsonFromPathAsync(firmwarePathData.packageJsonPath);
this.logService.debug('New firmware version:', packageJson.firmwareVersion); this.logService.debug('New firmware version:', packageJson.firmwareVersion);
if (this.options.useKboot) { await this.operations.updateRightFirmware(firmwarePathData.rightFirmwarePath);
await this.operations.updateRightFirmwareWithKboot(firmwarePathData.rightFirmwarePath); await this.operations.updateLeftModule(firmwarePathData.leftFirmwarePath);
await this.operations.updateLeftModuleWithKboot(firmwarePathData.leftFirmwarePath);
} else {
await this.operations.updateRightFirmwareWithBlhost(firmwarePathData.rightFirmwarePath);
await this.operations.updateLeftModuleWithBlhost(firmwarePathData.leftFirmwarePath);
}
} else { } else {
const packageJsonPath = path.join(this.rootDir, 'packages/firmware/package.json'); const packageJsonPath = path.join(this.rootDir, 'packages/firmware/package.json');
const packageJson = await getPackageJsonFromPathAsync(packageJsonPath); const packageJson = await getPackageJsonFromPathAsync(packageJsonPath);
this.logService.debug('New firmware version:', packageJson.firmwareVersion); this.logService.debug('New firmware version:', packageJson.firmwareVersion);
if (this.options.useKboot) { await this.operations.updateRightFirmware();
await this.operations.updateRightFirmwareWithKboot(); await this.operations.updateLeftModule();
await this.operations.updateLeftModuleWithKboot();
} else {
await this.operations.updateRightFirmwareWithBlhost();
await this.operations.updateLeftModuleWithBlhost();
}
} }
response.success = true; response.success = true;
@@ -232,11 +220,7 @@ export class DeviceService {
try { try {
await this.stopPollUhkDevice(); await this.stopPollUhkDevice();
if (this.options.useKboot) { await this.operations.updateRightFirmware();
await this.operations.updateRightFirmwareWithKboot();
} else {
await this.operations.updateRightFirmwareWithBlhost();
}
response.modules = await this.getHardwareModules(false); response.modules = await this.getHardwareModules(false);
response.success = true; response.success = true;
@@ -286,8 +270,8 @@ export class DeviceService {
while (true) { while (true) {
if (this._pollerAllowed) { if (this._pollerAllowed) {
this._uhkDevicePolling = true; this._uhkDevicePolling = true;
try {
const state = await this.device.getDeviceConnectionStateAsync(); const state = await this.device.getDeviceConnectionStateAsync();
if (!isEqual(state, savedState)) { if (!isEqual(state, savedState)) {
@@ -295,12 +279,10 @@ export class DeviceService {
this.win.webContents.send(IpcEvents.device.deviceConnectionStateChanged, state); this.win.webContents.send(IpcEvents.device.deviceConnectionStateChanged, state);
this.logService.info('[DeviceService] Device connection state changed to:', state); this.logService.info('[DeviceService] Device connection state changed to:', state);
} }
} catch (err) {
this.logService.error('[DeviceService] Device connection state query error', err);
}
}
this._uhkDevicePolling = false; this._uhkDevicePolling = false;
}
await snooze(250); await snooze(250);
} }
} }

View File

@@ -15,12 +15,7 @@ export enum MouseActionParam {
scrollLeft, scrollLeft,
scrollRight, scrollRight,
accelerate, accelerate,
decelerate, decelerate
button4,
button5,
button6,
button7,
button8
} }
export class MouseAction extends KeyAction { export class MouseAction extends KeyAction {

View File

@@ -7,8 +7,4 @@ export interface CommandLineArgs {
* simulate privilege escalation error * simulate privilege escalation error
*/ */
spe?: boolean; spe?: boolean;
/**
* If it is true use kboot package instead of blhost for firmware upgrade
*/
useKboot?: boolean;
} }

View File

@@ -1,4 +1,4 @@
export interface LeftModuleInfo { export interface HardwareModuleInfo {
firmwareVersion?: string; firmwareVersion?: string;
moduleProtocolVersion?: string; moduleProtocolVersion?: string;
} }

View File

@@ -1,7 +1,6 @@
import { LeftModuleInfo } from './left-module-info'; import { HardwareModuleInfo } from './hardware-module-info';
import { RightModuleInfo } from './right-module-info';
export interface HardwareModules { export interface HardwareModules {
leftModuleInfo?: LeftModuleInfo; leftModuleInfo?: HardwareModuleInfo;
rightModuleInfo?: RightModuleInfo; rightModuleInfo?: HardwareModuleInfo;
} }

View File

@@ -6,9 +6,8 @@ export * from './app-start-info';
export * from './configuration-reply'; export * from './configuration-reply';
export * from './version-information'; export * from './version-information';
export * from './device-connection-state'; export * from './device-connection-state';
export * from './left-module-info';
export * from './hardware-modules'; export * from './hardware-modules';
export * from './right-module-info'; export * from './hardware-module-info';
export * from './save-user-configuration-data'; export * from './save-user-configuration-data';
export * from './udev-rules-info'; export * from './udev-rules-info';
export * from './update-firmware-data'; export * from './update-firmware-data';

View File

@@ -1,7 +0,0 @@
export interface RightModuleInfo {
deviceProtocolVersion?: string;
hardwareConfigVersion?: string;
firmwareVersion?: string;
moduleProtocolVersion?: string;
userConfigVersion?: string;
}

View File

@@ -60,9 +60,9 @@
"integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
}, },
"chownr": { "chownr": {
"version": "1.1.2", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
@@ -151,9 +151,9 @@
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
}, },
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@@ -209,17 +209,17 @@
"integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==" "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA=="
}, },
"node-abi": { "node-abi": {
"version": "2.11.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.11.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.8.0.tgz",
"integrity": "sha512-kuy/aEg75u40v378WRllQ4ZexaXJiCvB68D2scDXclp/I4cRq6togpbOoKhmN07tns9Zldu51NNERo0wehfX9g==", "integrity": "sha512-1/aa2clS0pue0HjckL62CsbhWWU35HARvBDXcJtYKbYR7LnIutmpxmXbuDMV9kEviD2lP/wACOgWmmwljghHyQ==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
} }
}, },
"node-hid": { "node-hid": {
"version": "0.7.9", "version": "0.7.8",
"resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.9.tgz", "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.8.tgz",
"integrity": "sha512-vJnonTqmq3frCyTumJqG4g2IZcny3ynkfmbfDfQ90P3ZhRzcWYS/Um1ux6HFmAxmkaQnrZqIYHcGpL7kdqY8jA==", "integrity": "sha512-79Z9hw/pqIDp0kxvb353ivGgslo4i0hYQTcCqfRFxIJSO2gF9VtPla5uQY/9jTcDlON5O5YaqxbdH+8bs+m+1Q==",
"requires": { "requires": {
"bindings": "^1.5.0", "bindings": "^1.5.0",
"nan": "^2.13.2", "nan": "^2.13.2",
@@ -294,9 +294,9 @@
} }
}, },
"process-nextick-args": { "process-nextick-args": {
"version": "2.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
}, },
"pump": { "pump": {
"version": "2.0.1", "version": "2.0.1",
@@ -338,9 +338,9 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}, },
"semver": { "semver": {
"version": "5.7.1", "version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
@@ -476,9 +476,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
} }
} }
} }

View File

@@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"kboot": "0.0.0", "kboot": "0.0.0",
"node-hid": "0.7.9", "node-hid": "0.7.8",
"nrf-intel-hex": "1.3.0", "nrf-intel-hex": "1.3.0",
"tslib": "1.10.0", "tslib": "1.10.0",
"uhk-common": "1.0.0" "uhk-common": "1.0.0"

View File

@@ -71,9 +71,9 @@ export enum EnumerationNameToProductId {
} }
export enum ModuleSlotToI2cAddress { export enum ModuleSlotToI2cAddress {
leftHalf = '0x10', leftHalf = 0x10,
leftModule = '0x20', leftModule = 0x20,
rightModule = '0x30' rightModule = 0x30
} }
export enum ModuleSlotToId { export enum ModuleSlotToId {

View File

@@ -1,5 +1,4 @@
export * from './constants'; export * from './constants';
export * from './uhk-blhost';
export * from './uhk-hid-device'; export * from './uhk-hid-device';
export * from './uhk-operations'; export * from './uhk-operations';
export * from './util'; export * from './util';

View File

@@ -1,89 +0,0 @@
import * as path from 'path';
import { spawn } from 'child_process';
import { LogService } from 'uhk-common';
import { retry } from './util';
export class UhkBlhost {
private blhostPath: string;
constructor(private logService: LogService,
private rootDir: string) {
}
public async runBlhostCommand(params: Array<string>): Promise<void> {
const self = this;
return new Promise<void>((resolve, reject) => {
const blhostPath = this.getBlhostPath();
self.logService.debug(`[blhost] RUN: ${blhostPath} ${params.join(' ')}`);
const childProcess = spawn(`"${blhostPath}"`, params, {shell: true});
let finished = false;
childProcess.stdout.on('data', data => {
self.logService.debug(`[blhost] STDOUT: ${data}`);
});
childProcess.stderr.on('data', data => {
self.logService.error(`[blhost] STDERR: ${data}`);
});
childProcess.on('close', code => {
self.logService.debug(`[blhost] CLOSE_CODE: ${code}`);
finish(code);
});
childProcess.on('exit', code => {
self.logService.debug(`[blhost] EXIT_CODE: ${code}`);
finish(code);
});
childProcess.on('error', err => {
self.logService.debug(`[blhost] ERROR: ${err}`);
});
function finish(code) {
if (finished) {
return;
}
finished = true;
self.logService.debug(`[blhost] FINISHED: ${code}`);
if (code !== 0) {
return reject(new Error(`blhost error code:${code}`));
}
resolve();
}
});
}
public async runBlhostCommandRetry(params: Array<string>, maxTry = 100): Promise<void> {
return await retry(async () => await this.runBlhostCommand(params), maxTry, this.logService);
}
private getBlhostPath(): string {
if (this.blhostPath) {
return this.blhostPath;
}
let blhostPath;
switch (process.platform) {
case 'linux':
blhostPath = 'linux/x86_64/blhost';
break;
case 'darwin':
blhostPath = 'mac/blhost';
break;
case 'win32':
blhostPath = 'win/blhost.exe';
break;
default:
throw new Error(`Could not find blhost path. Unknown platform:${process.platform}`);
}
this.blhostPath = path.join(this.rootDir, `packages/blhost/${blhostPath}`);
return this.blhostPath;
}
}

View File

@@ -208,7 +208,7 @@ export class UhkHidDevice {
while (new Date().getTime() - startTime.getTime() < 20000) { while (new Date().getTime() - startTime.getTime() < 20000) {
const devs = devices(); const devs = devices();
this.logService.debug('[UhkHidDevice] reenumeration devices', devs); this.logService.silly('[UhkHidDevice] reenumeration devices', devs);
const inBootloaderMode = devs.some((x: Device) => const inBootloaderMode = devs.some((x: Device) =>
x.vendorId === Constants.VENDOR_ID && x.vendorId === Constants.VENDOR_ID &&
@@ -219,7 +219,7 @@ export class UhkHidDevice {
return; return;
} }
this.logService.debug(`[UhkHidDevice] Could not find reenumerated device: ${reenumMode}. Waiting...`); this.logService.silly(`[UhkHidDevice] Could not find reenumerated device: ${reenumMode}. Waiting...`);
await snooze(100); await snooze(100);
if (!jumped) { if (!jumped) {
@@ -232,7 +232,7 @@ export class UhkHidDevice {
device.close(); device.close();
jumped = true; jumped = true;
} else { } else {
this.logService.debug(`[UhkHidDevice] USB[T]: Enumerate device is not ready yet}`); this.logService.silly(`[UhkHidDevice] USB[T]: Enumerate device is not ready yet}`);
} }
} }
} }
@@ -249,7 +249,7 @@ export class UhkHidDevice {
if (command === KbootCommands.idle) { if (command === KbootCommands.idle) {
transfer = Buffer.from([UsbCommand.SendKbootCommandToModule, command]); transfer = Buffer.from([UsbCommand.SendKbootCommandToModule, command]);
} else { } else {
transfer = Buffer.from([UsbCommand.SendKbootCommandToModule, command, Number.parseInt(module, 16)]); transfer = Buffer.from([UsbCommand.SendKbootCommandToModule, command, module]);
} }
await retry(async () => await this.write(transfer), maxTry, this.logService); await retry(async () => await this.write(transfer), maxTry, this.logService);
} }

View File

@@ -1,4 +1,4 @@
import { LeftModuleInfo, LogService, RightModuleInfo, UhkBuffer } from 'uhk-common'; import { HardwareModuleInfo, LogService, UhkBuffer } from 'uhk-common';
import { DataOption, KBoot, Properties, UsbPeripheral } from 'kboot'; import { DataOption, KBoot, Properties, UsbPeripheral } from 'kboot';
import { import {
@@ -13,7 +13,6 @@ import {
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import * as os from 'os'; import * as os from 'os';
import { UhkBlhost } from './uhk-blhost';
import { UhkHidDevice } from './uhk-hid-device'; import { UhkHidDevice } from './uhk-hid-device';
import { readBootloaderFirmwareFromHexFileAsync, snooze, waitForDevice } from './util'; import { readBootloaderFirmwareFromHexFileAsync, snooze, waitForDevice } from './util';
import { ConfigBufferId, convertBufferToIntArray, DevicePropertyIds, getTransferBuffers, UsbCommand } from '../index'; import { ConfigBufferId, convertBufferToIntArray, DevicePropertyIds, getTransferBuffers, UsbCommand } from '../index';
@@ -21,67 +20,11 @@ import { LoadConfigurationsResult } from './models/load-configurations-result';
export class UhkOperations { export class UhkOperations {
constructor(private logService: LogService, constructor(private logService: LogService,
private blhost: UhkBlhost,
private device: UhkHidDevice, private device: UhkHidDevice,
private rootDir: string) { private rootDir: string) {
} }
public async updateRightFirmwareWithBlhost(firmwarePath = this.getFirmwarePath()) { public async updateRightFirmware(firmwarePath = this.getFirmwarePath()) {
this.logService.debug(`[UhkOperations] Operating system: ${os.type()} ${os.release()} ${os.arch()}`);
this.logService.debug('[UhkOperations] Start flashing right firmware');
const prefix = [`--usb 0x1d50,0x${EnumerationNameToProductId.bootloader.toString(16)}`];
await this.device.reenumerate(EnumerationModes.Bootloader);
this.device.close();
await this.blhost.runBlhostCommand([...prefix, 'flash-security-disable', '0403020108070605']);
await this.blhost.runBlhostCommand([...prefix, 'flash-erase-region', '0xc000', '475136']);
await this.blhost.runBlhostCommand([...prefix, 'flash-image', `"${firmwarePath}"`]);
await this.blhost.runBlhostCommand([...prefix, 'reset']);
this.logService.debug('[UhkOperations] Right firmware successfully flashed');
}
public async updateLeftModuleWithBlhost(firmwarePath = this.getLeftModuleFirmwarePath()) {
this.logService.debug('[UhkOperations] Start flashing left module firmware');
const prefix = [`--usb 0x1d50,0x${EnumerationNameToProductId.buspal.toString(16)}`];
const buspalPrefix = [...prefix, `--buspal i2c,${ModuleSlotToI2cAddress.leftHalf}`];
await this.device.reenumerate(EnumerationModes.NormalKeyboard);
this.device.close();
await snooze(1000);
await this.device.sendKbootCommandToModule(ModuleSlotToI2cAddress.leftHalf, KbootCommands.ping, 100);
await snooze(1000);
await this.device.jumpToBootloaderModule(ModuleSlotToId.leftHalf);
this.device.close();
const leftModuleBricked = await this.waitForKbootIdle();
if (!leftModuleBricked) {
const msg = '[UhkOperations] Couldn\'t connect to the left keyboard half.';
this.logService.error(msg);
throw new Error(msg);
}
await this.device.reenumerate(EnumerationModes.Buspal);
this.device.close();
await this.blhost.runBlhostCommandRetry([...buspalPrefix, 'get-property', '1']);
await this.blhost.runBlhostCommand([...buspalPrefix, 'flash-erase-all-unsecure']);
await this.blhost.runBlhostCommand([...buspalPrefix, 'write-memory', '0x0', `"${firmwarePath}"`]);
await this.blhost.runBlhostCommand([...prefix, 'reset']);
await snooze(1000);
await this.device.reenumerate(EnumerationModes.NormalKeyboard);
this.device.close();
await snooze(1000);
await this.device.sendKbootCommandToModule(ModuleSlotToI2cAddress.leftHalf, KbootCommands.reset, 100);
this.device.close();
await snooze(1000);
await this.device.sendKbootCommandToModule(ModuleSlotToI2cAddress.leftHalf, KbootCommands.idle);
this.device.close();
this.logService.debug('[UhkOperations] Left firmware successfully flashed');
this.logService.debug('[UhkOperations] Both left and right firmwares successfully flashed');
}
public async updateRightFirmwareWithKboot(firmwarePath = this.getFirmwarePath()) {
this.logService.debug(`[UhkOperations] Operating system: ${os.type()} ${os.release()} ${os.arch()}`); this.logService.debug(`[UhkOperations] Operating system: ${os.type()} ${os.release()} ${os.arch()}`);
this.logService.debug('[UhkOperations] Start flashing right firmware'); this.logService.debug('[UhkOperations] Start flashing right firmware');
@@ -115,10 +58,9 @@ export class UhkOperations {
this.logService.debug('[UhkOperations] Right firmware successfully flashed'); this.logService.debug('[UhkOperations] Right firmware successfully flashed');
} }
public async updateLeftModuleWithKboot(firmwarePath = this.getLeftModuleFirmwarePath()) { public async updateLeftModule(firmwarePath = this.getLeftModuleFirmwarePath()) {
this.logService.debug('[UhkOperations] Start flashing left module firmware'); this.logService.debug('[UhkOperations] Start flashing left module firmware');
const i2cAddressOfLeftModule = Number.parseInt(ModuleSlotToI2cAddress.leftHalf, 16);
await this.device.reenumerate(EnumerationModes.NormalKeyboard); await this.device.reenumerate(EnumerationModes.NormalKeyboard);
this.device.close(); this.device.close();
await snooze(1000); await snooze(1000);
@@ -144,31 +86,28 @@ export class UhkOperations {
while (true) { while (true) {
try { try {
this.logService.debug('[UhkOperations] Try to connect to the LEFT keyboard'); this.logService.debug('[UhkOperations] Try to connect to the LEFT keyboard');
await kboot.configureI2c(i2cAddressOfLeftModule); await kboot.configureI2c(ModuleSlotToI2cAddress.leftHalf);
await kboot.getProperty(Properties.BootloaderVersion); await kboot.getProperty(Properties.BootloaderVersion);
break; break;
} catch { } catch {
if (tryCount > 100) { if (tryCount > 100) {
throw new Error('Can not connect to the LEFT keyboard'); throw new Error('Can not connect to the LEFT keyboard');
} }
await snooze(2000); } finally {
kboot.close();
} }
await snooze(100);
tryCount++; tryCount++;
} }
// https://github.com/node-hid/node-hid/issues/230
this.logService.debug('[UhkOperations] Wait 1 sec to prevent node-hid race condition');
await snooze(1000);
this.logService.debug('[UhkOperations] Flash erase all on LEFT keyboard'); this.logService.debug('[UhkOperations] Flash erase all on LEFT keyboard');
await kboot.configureI2c(i2cAddressOfLeftModule); await kboot.configureI2c(ModuleSlotToI2cAddress.leftHalf);
await kboot.flashEraseAllUnsecure(); await kboot.flashEraseAllUnsecure();
this.logService.debug('[UhkOperations] Read LEFT firmware from file'); this.logService.debug('[UhkOperations] Read LEFT firmware from file');
const configData = fs.readFileSync(firmwarePath); const configData = fs.readFileSync(firmwarePath);
this.logService.debug('[UhkOperations] Write memory'); this.logService.debug('[UhkOperations] Write memory');
await kboot.configureI2c(i2cAddressOfLeftModule); await kboot.configureI2c(ModuleSlotToI2cAddress.leftHalf);
await kboot.writeMemory({ startAddress: 0, data: configData }); await kboot.writeMemory({ startAddress: 0, data: configData });
this.logService.debug('[UhkOperations] Reset LEFT keyboard'); this.logService.debug('[UhkOperations] Reset LEFT keyboard');
@@ -309,7 +248,7 @@ export class UhkOperations {
return false; return false;
} }
public async getLeftModuleVersionInfo(): Promise<LeftModuleInfo> { public async getLeftModuleVersionInfo(): Promise<HardwareModuleInfo> {
try { try {
this.logService.debug('[DeviceOperation] USB[T]: Read left module version information'); this.logService.debug('[DeviceOperation] USB[T]: Read left module version information');
@@ -338,7 +277,7 @@ export class UhkOperations {
}; };
} }
public async getRightModuleVersionInfo(): Promise<RightModuleInfo> { public async getRightModuleVersionInfo(): Promise<HardwareModuleInfo> {
this.logService.debug('[DeviceOperation] USB[T]: Read right module version information'); this.logService.debug('[DeviceOperation] USB[T]: Read right module version information');
const command = Buffer.from([UsbCommand.GetProperty, DevicePropertyIds.ProtocolVersions]); const command = Buffer.from([UsbCommand.GetProperty, DevicePropertyIds.ProtocolVersions]);
@@ -348,11 +287,7 @@ export class UhkOperations {
uhkBuffer.readUInt8(); uhkBuffer.readUInt8();
return { return {
firmwareVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`, firmwareVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`
deviceProtocolVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`,
moduleProtocolVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`,
userConfigVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`,
hardwareConfigVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`
}; };
} }

View File

@@ -126,9 +126,7 @@ export const getFileContentAsync = async (filePath: string): Promise<Array<strin
export const readBootloaderFirmwareFromHexFileAsync = async (hexFilePath: string): Promise<Map<any, any>> => { export const readBootloaderFirmwareFromHexFileAsync = async (hexFilePath: string): Promise<Map<any, any>> => {
const fileContent = await readFile(hexFilePath, { encoding: 'utf8' }); const fileContent = await readFile(hexFilePath, { encoding: 'utf8' });
const fromHex = MemoryMap.fromHex ? MemoryMap.fromHex : MemoryMap.default.fromHex; const memoryMap = MemoryMap.fromHex(fileContent);
const memoryMap = fromHex(fileContent);
return memoryMap; return memoryMap;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -19,28 +19,29 @@
}, },
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@angular/animations": "8.2.6", "@angular/animations": "7.2.15",
"@angular-builders/custom-webpack": "8.2.0", "@angular-builders/custom-webpack": "7.3.1",
"@angular/cli": "8.3.4", "@angular/cli": "7.3.9",
"@angular/common": "8.2.6", "@angular/common": "7.2.15",
"@angular/compiler": "8.2.6", "@angular/compiler": "7.2.15",
"@angular/compiler-cli": "8.2.6", "@angular/compiler-cli": "7.2.15",
"@angular/core": "8.2.6", "@angular/core": "7.2.15",
"@angular-devkit/build-angular": "0.803.4", "@angular-devkit/build-angular": "0.13.9",
"@angular-devkit/build-optimizer": "0.803.4", "@angular-devkit/build-optimizer": "0.13.9",
"@angular-devkit/core": "8.3.4", "@angular-devkit/core": "7.3.9",
"@angular/forms": "8.2.6", "@angular/forms": "7.2.15",
"@angular/language-service": "8.2.6", "@angular/http": "7.2.15",
"@angular/platform-browser": "8.2.6", "@angular/language-service": "7.2.15",
"@angular/platform-browser-dynamic": "8.2.6", "@angular/platform-browser": "7.2.15",
"@angular/router": "8.2.6", "@angular/platform-browser-dynamic": "7.2.15",
"@ngtools/webpack": "8.3.4", "@angular/router": "7.2.15",
"@ngrx/effects": "8.2.0", "@ngtools/webpack": "7.3.9",
"@ngrx/router-store": "8.2.0", "@ngrx/effects": "7.4.0",
"@ngrx/store": "8.2.0", "@ngrx/router-store": "7.4.0",
"@ngrx/store-devtools": "8.2.0", "@ngrx/store": "7.4.0",
"@ngrx/store-devtools": "7.4.0",
"@ngrx/store-log-monitor": "3.0.2", "@ngrx/store-log-monitor": "3.0.2",
"angular-confirmation-popover": "4.2.1", "angular-confirmation-popover": "4.2.0",
"angular-notifier": "4.1.1", "angular-notifier": "4.1.1",
"bootstrap": "3.4.1", "bootstrap": "3.4.1",
"codelyzer": "4.5.0", "codelyzer": "4.5.0",
@@ -55,18 +56,19 @@
"karma-jasmine": "1.1.2", "karma-jasmine": "1.1.2",
"karma-jasmine-html-reporter": "1.3.1", "karma-jasmine-html-reporter": "1.3.1",
"ng2-dragula": "2.1.1", "ng2-dragula": "2.1.1",
"ng2-nouislider": "1.8.2", "ng2-nouislider": "1.7.13",
"ngx-clipboard": "12.2.0", "ngx-clipboard": "10.0.0",
"ngx-select-ex": "3.7.0", "ngx-select-ex": "3.6.8",
"ngrx-store-freeze": "0.2.4", "ngrx-store-freeze": "0.1.9",
"nouislider": "14.0.2", "nouislider": "13.1.1",
"protractor": "5.4.0", "protractor": "5.4.0",
"rxjs": "6.5.2", "reselect": "3.0.1",
"rxjs": "6.4.0",
"semver": "5.6.0", "semver": "5.6.0",
"ts-keycode-enum": "^1.0.6", "ts-keycode-enum": "^1.0.6",
"uhk-common": "1.0.0", "uhk-common": "1.0.0",
"xml-loader": "1.2.1", "xml-loader": "1.2.1",
"zone.js": "0.10.0" "zone.js": "0.8.26"
}, },
"dependencies": { "dependencies": {
"classlist.js": "1.1.20150312", "classlist.js": "1.1.20150312",

View File

@@ -16,7 +16,6 @@ import {
} from './store'; } from './store';
import { ProgressButtonState } from './store/reducers/progress-button-state'; import { ProgressButtonState } from './store/reducers/progress-button-state';
import { UpdateInfo } from './models/update-info'; import { UpdateInfo } from './models/update-info';
import { KeyUpAction, KeyDownAction } from './store/actions/app';
@Component({ @Component({
selector: 'main-app', selector: 'main-app',
@@ -96,13 +95,6 @@ export class MainAppComponent implements OnDestroy {
this.enableUsbStackTest(); this.enableUsbStackTest();
event.preventDefault(); event.preventDefault();
} }
this.store.dispatch(new KeyDownAction(event));
}
@HostListener('document:keyup', ['$event'])
onKeyUp(event: KeyboardEvent) {
this.store.dispatch(new KeyUpAction(event));
} }
updateApp() { updateApp() {

View File

@@ -1,7 +1,7 @@
import { Component, Input, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; import { Component, Input, ViewChild, ElementRef, OnInit } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '../../../../store'; import { AppState } from '../../../../store/index';
import { UHKContributor } from '../../../../models/uhk-contributor'; import { UHKContributor } from '../../../../models/uhk-contributor';
@@ -10,9 +10,9 @@ import { UHKContributor } from '../../../../models/uhk-contributor';
templateUrl: './contributor-badge.component.html', templateUrl: './contributor-badge.component.html',
styleUrls: ['./contributor-badge.component.scss'] styleUrls: ['./contributor-badge.component.scss']
}) })
export class ContributorBadgeComponent implements AfterViewInit { export class ContributorBadgeComponent implements OnInit {
@Input() contributor: UHKContributor; @Input() contributor: UHKContributor;
@ViewChild('badge', { static: false }) badge: ElementRef; @ViewChild('badge') badge: ElementRef;
get name(): string { get name(): string {
return this.contributor.login; return this.contributor.login;
@@ -29,7 +29,7 @@ export class ContributorBadgeComponent implements AfterViewInit {
constructor(private store: Store<AppState>) { constructor(private store: Store<AppState>) {
} }
ngAfterViewInit(): void { ngOnInit(): void {
(this.badge.nativeElement as HTMLImageElement).src = URL.createObjectURL(this.contributor.avatar); (this.badge.nativeElement as HTMLImageElement).src = URL.createObjectURL(this.contributor.avatar);
} }
} }

View File

@@ -20,7 +20,6 @@
<li>Right click on a key: Capture key</li> <li>Right click on a key: Capture key</li>
<li>Hold Shift while clicking on a key: Remap on all keymaps</li> <li>Hold Shift while clicking on a key: Remap on all keymaps</li>
<li>Hold Alt while clicking on a key: Remap on all layers</li> <li>Hold Alt while clicking on a key: Remap on all layers</li>
<li>Hold Alt to see macro reference counts in the side menu</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -30,7 +30,7 @@ export class AutoGrowInputComponent implements ControlValueAccessor {
@Input() maxParentWidthPercent = 1; @Input() maxParentWidthPercent = 1;
@Input() css: string; @Input() css: string;
@ViewChild('inputControl', { static: true }) inputControl: ElementRef; @ViewChild('inputControl') inputControl: ElementRef;
disabled: boolean; disabled: boolean;

View File

@@ -21,7 +21,7 @@
<li> <li>
<button class="btn btn-danger" <button class="btn btn-danger"
mwlConfirmationPopover mwlConfirmationPopover
popoverTitle="Are you sure?" title="Are you sure?"
placement="bottom" placement="bottom"
confirmText="Yes" confirmText="Yes"
cancelText="No" cancelText="No"

View File

@@ -27,7 +27,7 @@
label="Choose firmware file and flash it"></file-upload> label="Choose firmware file and flash it"></file-upload>
</p> </p>
<div *ngIf="firmwareUpgradeFailed" <div *ngIf="firmwareUpgradeFailed$ | async"
class="alert alert-danger" class="alert alert-danger"
role="alert"> role="alert">
<p>Firmware update failed. Disconnect every USB device from your computer (including USB hubs, KVM switches, USB dongles, and everything else), then connect only your UHK and retry.</p> <p>Firmware update failed. Disconnect every USB device from your computer (including USB hubs, KVM switches, USB dongles, and everything else), then connect only your UHK and retry.</p>
@@ -35,7 +35,7 @@
<p>If you've tried the above and the update still keeps failing, please <a class="link-github" [href]="firmwareGithubIssueUrl" externalUrl>create a GitHub issue</a>, and attach the update log.</p> <p>If you've tried the above and the update still keeps failing, please <a class="link-github" [href]="firmwareGithubIssueUrl" externalUrl>create a GitHub issue</a>, and attach the update log.</p>
</div> </div>
<div *ngIf="firmwareUpgradeSuccess" <div *ngIf="firmwareUpgradeSuccess$ | async"
class="alert alert-success" class="alert alert-success"
role="alert"> role="alert">
<p>Firmware update succeeded.</p> <p>Firmware update succeeded.</p>

View File

@@ -1,4 +1,4 @@
import { Component, OnDestroy, ViewChild } from '@angular/core'; import { Component, OnDestroy } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { Constants, HardwareModules, VersionInformation } from 'uhk-common'; import { Constants, HardwareModules, VersionInformation } from 'uhk-common';
@@ -17,7 +17,6 @@ import {
import { UpdateFirmwareAction, UpdateFirmwareWithAction } from '../../../store/actions/device'; import { UpdateFirmwareAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
import { XtermLog } from '../../../models/xterm-log'; import { XtermLog } from '../../../models/xterm-log';
import { UploadFileData } from '../../../models/upload-file-data'; import { UploadFileData } from '../../../models/upload-file-data';
import { XtermComponent } from '../../xterm/xterm.component';
@Component({ @Component({
selector: 'device-firmware', selector: 'device-firmware',
@@ -31,41 +30,30 @@ export class DeviceFirmwareComponent implements OnDestroy {
flashFirmwareButtonDisbabled$: Observable<boolean>; flashFirmwareButtonDisbabled$: Observable<boolean>;
xtermLog$: Observable<Array<XtermLog>>; xtermLog$: Observable<Array<XtermLog>>;
getAgentVersionInfo$: Observable<VersionInformation>; getAgentVersionInfo$: Observable<VersionInformation>;
hardwareModulesSubscription: Subscription;
hardwareModules: HardwareModules; hardwareModules: HardwareModules;
runningOnNotSupportedWindows$: Observable<boolean>; runningOnNotSupportedWindows$: Observable<boolean>;
firmwareUpgradeAllowed$: Observable<boolean>; firmwareUpgradeAllowed$: Observable<boolean>;
firmwareUpgradeFailed$: Observable<boolean>;
firmwareUpgradeSuccess$: Observable<boolean>;
firmwareGithubIssueUrl: string; firmwareGithubIssueUrl: string;
firmwareUpgradeFailed: boolean;
firmwareUpgradeSuccess: boolean;
@ViewChild(XtermComponent, { static: false })
xtermRef: XtermComponent;
private subscription = new Subscription();
constructor(private store: Store<AppState>) { constructor(private store: Store<AppState>) {
this.flashFirmwareButtonDisbabled$ = store.select(flashFirmwareButtonDisbabled); this.flashFirmwareButtonDisbabled$ = store.select(flashFirmwareButtonDisbabled);
this.xtermLog$ = store.select(xtermLog); this.xtermLog$ = store.select(xtermLog);
this.getAgentVersionInfo$ = store.select(getAgentVersionInfo); this.getAgentVersionInfo$ = store.select(getAgentVersionInfo);
this.subscription.add(store.select(getHardwareModules).subscribe(data => { this.hardwareModulesSubscription = store.select(getHardwareModules).subscribe(data => {
this.hardwareModules = data; this.hardwareModules = data;
})); });
this.runningOnNotSupportedWindows$ = store.select(runningOnNotSupportedWindows); this.runningOnNotSupportedWindows$ = store.select(runningOnNotSupportedWindows);
this.firmwareUpgradeAllowed$ = store.select(firmwareUpgradeAllowed); this.firmwareUpgradeAllowed$ = store.select(firmwareUpgradeAllowed);
this.subscription.add(store.select(firmwareUpgradeFailed).subscribe(data => { this.firmwareUpgradeFailed$ = store.select(firmwareUpgradeFailed);
this.firmwareUpgradeFailed = data; this.firmwareUpgradeSuccess$ = store.select(firmwareUpgradeSuccess);
this.scrollToTheEndOfTheLogs();
}));
this.subscription.add(store.select(firmwareUpgradeSuccess).subscribe(data => {
this.firmwareUpgradeSuccess = data;
this.scrollToTheEndOfTheLogs();
}));
this.firmwareGithubIssueUrl = Constants.FIRMWARE_GITHUB_ISSUE_URL; this.firmwareGithubIssueUrl = Constants.FIRMWARE_GITHUB_ISSUE_URL;
} }
ngOnDestroy(): void { ngOnDestroy(): void {
this.subscription.unsubscribe(); this.hardwareModulesSubscription.unsubscribe();
} }
onUpdateFirmware(): void { onUpdateFirmware(): void {
@@ -75,10 +63,4 @@ export class DeviceFirmwareComponent implements OnDestroy {
changeFile(data: UploadFileData): void { changeFile(data: UploadFileData): void {
this.store.dispatch(new UpdateFirmwareWithAction(data.data)); this.store.dispatch(new UpdateFirmwareWithAction(data.data));
} }
private scrollToTheEndOfTheLogs(): void {
if (this.xtermRef) {
this.xtermRef.scrollToTheEnd();
}
}
} }

View File

@@ -4,7 +4,7 @@
</h1> </h1>
<button class="btn btn-danger mouse-speed-reset-button" <button class="btn btn-danger mouse-speed-reset-button"
mwlConfirmationPopover mwlConfirmationPopover
popoverTitle="Are you sure?" title="Are you sure?"
placement="bottom" placement="bottom"
confirmText="Yes" confirmText="Yes"
cancelText="No" cancelText="No"
@@ -12,7 +12,7 @@
</button> </button>
<button class="btn btn-danger mouse-speed-reset-button" <button class="btn btn-danger mouse-speed-reset-button"
mwlConfirmationPopover mwlConfirmationPopover
popoverTitle="Are you sure?" title="Are you sure?"
placement="bottom" placement="bottom"
confirmText="Yes" confirmText="Yes"
cancelText="No" cancelText="No"

View File

@@ -39,8 +39,8 @@ export class KeymapHeaderComponent implements OnChanges {
@Input() deletable: boolean; @Input() deletable: boolean;
@Output() downloadClick = new EventEmitter<void>(); @Output() downloadClick = new EventEmitter<void>();
@ViewChild('name', { static: true }) keymapName: ElementRef; @ViewChild('name') keymapName: ElementRef;
@ViewChild('abbr', { static: true }) keymapAbbr: ElementRef; @ViewChild('abbr') keymapAbbr: ElementRef;
starTitle: string; starTitle: string;
trashTitle: string = DEFAULT_TRASH_TITLE; trashTitle: string = DEFAULT_TRASH_TITLE;

View File

@@ -31,8 +31,7 @@ export class MacroActionEditorComponent implements OnInit {
@Output() save = new EventEmitter<MacroAction>(); @Output() save = new EventEmitter<MacroAction>();
@Output() cancel = new EventEmitter<void>(); @Output() cancel = new EventEmitter<void>();
// tslint:disable-next-line:max-line-length @ViewChild('tab') selectedTab: MacroTextTabComponent | MacroKeyTabComponent | MacroMouseTabComponent | MacroDelayTabComponent;
@ViewChild('tab', { static: false }) selectedTab: MacroTextTabComponent | MacroKeyTabComponent | MacroMouseTabComponent | MacroDelayTabComponent;
editableMacroAction: MacroAction; editableMacroAction: MacroAction;
activeTab: TabName; activeTab: TabName;

View File

@@ -1,8 +1,10 @@
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
ElementRef,
Input, Input,
OnInit OnInit,
ViewChild
} from '@angular/core'; } from '@angular/core';
import { DelayMacroAction } from 'uhk-common'; import { DelayMacroAction } from 'uhk-common';
@@ -19,6 +21,7 @@ const INITIAL_DELAY = 0.5; // In seconds
}) })
export class MacroDelayTabComponent extends MacroBaseComponent implements OnInit { export class MacroDelayTabComponent extends MacroBaseComponent implements OnInit {
@Input() macroAction: DelayMacroAction; @Input() macroAction: DelayMacroAction;
@ViewChild('macroDelayInput') input: ElementRef;
presets: number[] = [0.1, 0.5, 1, 5, 10]; presets: number[] = [0.1, 0.5, 1, 5, 10];

View File

@@ -21,7 +21,8 @@ enum TabName {
}) })
export class MacroKeyTabComponent extends MacroBaseComponent implements OnInit { export class MacroKeyTabComponent extends MacroBaseComponent implements OnInit {
@Input() macroAction: KeyMacroAction; @Input() macroAction: KeyMacroAction;
@ViewChild('keypressTab', { static: true }) keypressTab: KeypressTabComponent; @ViewChild('tab') selectedTab: Tab;
@ViewChild('keypressTab') keypressTab: KeypressTabComponent;
/* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */ /* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */
TabName = TabName; TabName = TabName;

View File

@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { import {
MacroMouseSubAction, MacroMouseSubAction,
@@ -7,6 +7,7 @@ import {
MoveMouseMacroAction, MoveMouseMacroAction,
ScrollMouseMacroAction ScrollMouseMacroAction
} from 'uhk-common'; } from 'uhk-common';
import { Tab } from '../../../../popover/tab';
import { MacroBaseComponent } from '../macro-base.component'; import { MacroBaseComponent } from '../macro-base.component';
type MouseMacroAction = MouseButtonMacroAction | MoveMouseMacroAction | ScrollMouseMacroAction; type MouseMacroAction = MouseButtonMacroAction | MoveMouseMacroAction | ScrollMouseMacroAction;
@@ -30,6 +31,7 @@ enum TabName {
}) })
export class MacroMouseTabComponent extends MacroBaseComponent implements OnInit { export class MacroMouseTabComponent extends MacroBaseComponent implements OnInit {
@Input() macroAction: MouseMacroAction; @Input() macroAction: MouseMacroAction;
@ViewChild('tab') selectedTab: Tab;
/* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */ /* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */
MouseButtons = MouseButtons; MouseButtons = MouseButtons;

View File

@@ -20,7 +20,7 @@ const NON_ASCII_REGEXP = /[^\x00-\x7F]/g;
}) })
export class MacroTextTabComponent extends MacroBaseComponent implements OnInit, AfterViewInit { export class MacroTextTabComponent extends MacroBaseComponent implements OnInit, AfterViewInit {
@Input() macroAction: TextMacroAction; @Input() macroAction: TextMacroAction;
@ViewChild('macroTextInput', { static: false } ) input: ElementRef; @ViewChild('macroTextInput') input: ElementRef;
constructor() { super(); } constructor() { super(); }

View File

@@ -26,7 +26,7 @@ import * as util from '../../../util';
export class MacroHeaderComponent implements AfterViewInit, OnChanges { export class MacroHeaderComponent implements AfterViewInit, OnChanges {
@Input() macro: Macro; @Input() macro: Macro;
@Input() isNew: boolean; @Input() isNew: boolean;
@ViewChild('macroName', { static: true }) macroName: ElementRef; @ViewChild('macroName') macroName: ElementRef;
constructor(private store: Store<AppState>, private renderer: Renderer2) { } constructor(private store: Store<AppState>, private renderer: Renderer2) { }

View File

@@ -46,6 +46,7 @@ export class MacroListComponent {
newMacro: Macro = undefined; newMacro: Macro = undefined;
showNew: boolean = false; showNew: boolean = false;
private activeEdit: number = undefined; private activeEdit: number = undefined;
private dragIndex: number;
constructor( constructor(
private mapper: MapperService, private mapper: MapperService,
@@ -58,18 +59,16 @@ export class MacroListComponent {
} }
}); });
dragulaService.drop('macroActions').subscribe(value => { dragulaService.drag('macroActions').subscribe((value: any) => {
if (value.el) { this.dragIndex = +value[1].getAttribute('data-index');
let newIndex = this.macroItems.length - 1; });
if (value.sibling) {
newIndex = (+value.sibling.getAttribute('data-index') - 1);
}
dragulaService.drop('macroActions').subscribe((value: any) => {
if (value[4]) {
this.reorder.emit({ this.reorder.emit({
macroId: this.macro.id, macroId: this.macro.id,
oldIndex: +value.el.getAttribute('data-index'), oldIndex: this.dragIndex,
newIndex newIndex: +value[4].getAttribute('data-index')
}); });
} }
}); });

View File

@@ -38,7 +38,6 @@
></layer-tab> ></layer-tab>
<mouse-tab #tab *ngSwitchCase="tabName.Mouse" class="popover-content" <mouse-tab #tab *ngSwitchCase="tabName.Mouse" class="popover-content"
[defaultKeyAction]="defaultKeyAction" [defaultKeyAction]="defaultKeyAction"
[extraMouseButtonsSupported]="extraMouseButtonsSupported$ | async"
(validAction)="setKeyActionValidState($event)" (validAction)="setKeyActionValidState($event)"
></mouse-tab> ></mouse-tab>
<macro-tab #tab *ngSwitchCase="tabName.Macro" class="popover-content" <macro-tab #tab *ngSwitchCase="tabName.Macro" class="popover-content"

View File

@@ -30,7 +30,7 @@ import {
import { Tab } from './tab'; import { Tab } from './tab';
import { AppState, extraMouseButtonsSupported, getKeymaps, macroPlaybackSupported } from '../../store'; import { AppState, getKeymaps, macroPlaybackSupported } from '../../store';
import { KeyActionRemap } from '../../models/key-action-remap'; import { KeyActionRemap } from '../../models/key-action-remap';
import { RemapInfo } from '../../models/remap-info'; import { RemapInfo } from '../../models/remap-info';
@@ -98,8 +98,8 @@ export class PopoverComponent implements OnChanges {
@Output() cancel = new EventEmitter<any>(); @Output() cancel = new EventEmitter<any>();
@Output() remap = new EventEmitter<KeyActionRemap>(); @Output() remap = new EventEmitter<KeyActionRemap>();
@ViewChild('tab', { static: false }) selectedTab: Tab; @ViewChild('tab') selectedTab: Tab;
@ViewChild('popover', { static: false }) popoverHost: ElementRef; @ViewChild('popover') popoverHost: ElementRef;
tabName = TabName; tabName = TabName;
keyActionValid: boolean; keyActionValid: boolean;
@@ -145,7 +145,6 @@ export class PopoverComponent implements OnChanges {
} }
]; ];
macroPlaybackSupported$: Observable<boolean>; macroPlaybackSupported$: Observable<boolean>;
extraMouseButtonsSupported$: Observable<boolean>;
private readonly currentKeymap$ = new BehaviorSubject<Keymap>(undefined); private readonly currentKeymap$ = new BehaviorSubject<Keymap>(undefined);
@@ -159,7 +158,6 @@ export class PopoverComponent implements OnChanges {
keymaps.filter((keymap: Keymap) => currentKeymap.abbreviation !== keymap.abbreviation)) keymaps.filter((keymap: Keymap) => currentKeymap.abbreviation !== keymap.abbreviation))
); );
this.macroPlaybackSupported$ = store.select(macroPlaybackSupported); this.macroPlaybackSupported$ = store.select(macroPlaybackSupported);
this.extraMouseButtonsSupported$ = store.select(extraMouseButtonsSupported);
} }
ngOnChanges(change: SimpleChanges) { ngOnChanges(change: SimpleChanges) {

View File

@@ -80,27 +80,6 @@
[class.btn-primary]="mouseActionParam === MouseActionParam.rightClick" [class.btn-primary]="mouseActionParam === MouseActionParam.rightClick"
(click)="setMouseActionParam(MouseActionParam.rightClick)">Right</button> (click)="setMouseActionParam(MouseActionParam.rightClick)">Right</button>
</div> </div>
<div class="additional-keys" *ngIf="extraMouseButtonsSupported">
<div class="btn-group col-xs-12" role="group">
<button type="button" class="btn btn-default col-xs-4"
[class.btn-primary]="mouseActionParam === MouseActionParam.button4"
(click)="setMouseActionParam(MouseActionParam.button4)">Button 4</button>
<button type="button" class="btn btn-default col-xs-4"
[class.btn-primary]="mouseActionParam === MouseActionParam.button5"
(click)="setMouseActionParam(MouseActionParam.button5)">Button 5</button>
<button type="button" class="btn btn-default col-xs-4"
[class.btn-primary]="mouseActionParam === MouseActionParam.button6"
(click)="setMouseActionParam(MouseActionParam.button6)">Button 6</button>
</div>
<div class="btn-group col-xs-12" role="group">
<button type="button" class="btn btn-default col-xs-6"
[class.btn-primary]="mouseActionParam === MouseActionParam.button7"
(click)="setMouseActionParam(MouseActionParam.button7)">Button 7</button>
<button type="button" class="btn btn-default col-xs-6"
[class.btn-primary]="mouseActionParam === MouseActionParam.button8"
(click)="setMouseActionParam(MouseActionParam.button8)">Button 8</button>
</div>
</div>
</div> </div>
<div *ngSwitchCase="3" class="mouse__config mouse__config--speed text-center"> <div *ngSwitchCase="3" class="mouse__config mouse__config--speed text-center">
<div class="help-text--mouse-speed text-left"> <div class="help-text--mouse-speed text-left">

View File

@@ -54,32 +54,6 @@
} }
} }
.mouse__config--click {
.additional-keys {
display: inline-block;
margin-top: 1rem;
.btn-group:first-child {
.btn {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
.btn-group:last-child {
.btn {
border-top: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
&:last-child {
right: 1px;
}
}
}
}
}
.mouse__config--speed { .mouse__config--speed {
.btn-default { .btn-default {
font-size: 25px; font-size: 25px;

View File

@@ -11,7 +11,6 @@ import { Tab } from '../tab';
}) })
export class MouseTabComponent extends Tab implements OnChanges { export class MouseTabComponent extends Tab implements OnChanges {
@Input() defaultKeyAction: KeyAction; @Input() defaultKeyAction: KeyAction;
@Input() extraMouseButtonsSupported: boolean;
/* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */ /* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */
MouseActionParam = MouseActionParam; MouseActionParam = MouseActionParam;
@@ -63,11 +62,6 @@ export class MouseTabComponent extends Tab implements OnChanges {
case MouseActionParam.leftClick: case MouseActionParam.leftClick:
case MouseActionParam.middleClick: case MouseActionParam.middleClick:
case MouseActionParam.rightClick: case MouseActionParam.rightClick:
case MouseActionParam.button4:
case MouseActionParam.button5:
case MouseActionParam.button6:
case MouseActionParam.button7:
case MouseActionParam.button8:
this.selectedPageIndex = 2; this.selectedPageIndex = 2;
break; break;
case MouseActionParam.decelerate: case MouseActionParam.decelerate:

View File

@@ -91,12 +91,6 @@
<div class="sidebar__level-2" [routerLinkActive]="['active']"> <div class="sidebar__level-2" [routerLinkActive]="['active']">
<a [routerLink]="['/macro', macro.id]" <a [routerLink]="['/macro', macro.id]"
[class.disabled]="state.updatingFirmware">{{macro.name}}</a> [class.disabled]="state.updatingFirmware">{{macro.name}}</a>
<span *ngIf="state.macroUsageCountVisible"
class="sidebar__macro_count badge"
title="This is the number of times the macro is used across all keymaps."
data-toggle="tooltip"
data-placement="bottom"
data-container="body">{{ macro.usageCount }}</span>
</div> </div>
</li> </li>
</ul> </ul>

View File

@@ -148,12 +148,6 @@ ul {
right: 19px; right: 19px;
top: 3px; top: 3px;
} }
&__macro_count {
position: absolute;
right: 11px;
top: 1px;
}
} }
.menu--bottom { .menu--bottom {

View File

@@ -2,9 +2,10 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
OnDestroy, ElementRef,
OnInit, OnDestroy, OnInit,
Renderer2 Renderer2,
ViewChild
} from '@angular/core'; } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations'; import { animate, state, style, transition, trigger } from '@angular/animations';
@@ -37,6 +38,7 @@ import { SideMenuPageState } from '../../models/side-menu-page-state';
export class SideMenuComponent implements OnInit, OnDestroy { export class SideMenuComponent implements OnInit, OnDestroy {
state: SideMenuPageState; state: SideMenuPageState;
animation: { [key: string]: 'active' | 'inactive' }; animation: { [key: string]: 'active' | 'inactive' };
@ViewChild('deviceName') deviceName: ElementRef;
private stateSubscription: Subscription; private stateSubscription: Subscription;

View File

@@ -28,7 +28,7 @@ export interface SliderProps {
] ]
}) })
export class SliderWrapperComponent implements AfterViewInit, ControlValueAccessor, OnDestroy { export class SliderWrapperComponent implements AfterViewInit, ControlValueAccessor, OnDestroy {
@ViewChild(NouisliderComponent, { static: false }) slider: NouisliderComponent; @ViewChild(NouisliderComponent) slider: NouisliderComponent;
@Input() label: string; @Input() label: string;
@Input() tooltip: string; @Input() tooltip: string;
@Input() min: number; @Input() min: number;

View File

@@ -1,4 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" <svg xmlns="http://www.w3.org/2000/svg"
class="svgKeyboard"
[attr.viewBox]="viewBox" [attr.viewBox]="viewBox"
height="100%" height="100%"
width="100%"> width="100%">

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -3,8 +3,14 @@
width: 100%; width: 100%;
position: relative; position: relative;
} }
.svgKeyboard {
z-index: 50;
}
editable-text { editable-text {
padding-left: 2em; padding-left: 2em;
padding-right: 2em; padding-right: 2em;
display: block; display: block;
z-index: 51;
} }

View File

@@ -91,7 +91,6 @@ export class SvgKeyboardComponent {
this.modules = []; this.modules = [];
this.viewBox = '-520 582 1100 470'; this.viewBox = '-520 582 1100 470';
this.moduleAnimationStates = []; this.moduleAnimationStates = [];
this.moduleVisibilityAnimationStates = [];
} }
ngOnInit() { ngOnInit() {

View File

@@ -1,4 +1,8 @@
:host { :host {
/deep/ text {
dominant-baseline: central;
}
cursor: pointer; cursor: pointer;
outline: none; outline: none;

View File

@@ -79,7 +79,7 @@ export class SvgKeyboardKeyComponent implements OnChanges {
@Output() keyClick = new EventEmitter<SvgKeyClickEvent>(); @Output() keyClick = new EventEmitter<SvgKeyClickEvent>();
@Output() capture = new EventEmitter<SvgKeyCaptureEvent>(); @Output() capture = new EventEmitter<SvgKeyCaptureEvent>();
@ViewChild('svgRec', { static: false }) svgRec: ElementRef<HTMLElement>; @ViewChild('svgRec') svgRec: ElementRef<HTMLElement>;
enumLabelTypes = LabelTypes; enumLabelTypes = LabelTypes;

View File

@@ -25,17 +25,17 @@
</svg> </svg>
<svg viewBox="0 0 100 100" [attr.width]="control.width" [attr.height]="control.height" [attr.x]="control.x" [attr.y]="control.y" <svg viewBox="0 0 100 100" [attr.width]="control.width" [attr.height]="control.height" [attr.x]="control.x" [attr.y]="control.y"
preserveAspectRatio="none" [class.disabled]="control.disabled"> preserveAspectRatio="none" [class.disabled]="control.disabled">
<svg:text text-anchor="middle" alignment-baseline="middle" x="50" y="55">C</svg:text> <svg:text [attr.text-anchor]="'middle'" [attr.x]="50" [attr.y]="50">C</svg:text>
</svg> </svg>
<svg viewBox="0 0 100 100" [attr.width]="option.width" [attr.height]="option.height" [attr.x]="option.x" [attr.y]="option.y" <svg viewBox="0 0 100 100" [attr.width]="option.width" [attr.height]="option.height" [attr.x]="option.x" [attr.y]="option.y"
preserveAspectRatio="none" [class.disabled]="option.disabled"> preserveAspectRatio="none" [class.disabled]="option.disabled">
<svg:use *ngIf="modifierIconNames.option" [attr.xlink:href]="modifierIconNames.option" /> <svg:use *ngIf="modifierIconNames.option" [attr.xlink:href]="modifierIconNames.option" />
<svg:text *ngIf="!modifierIconNames.option" text-anchor="middle" alignment-baseline="middle" x="50" y="55">A</svg:text> <svg:text *ngIf="!modifierIconNames.option" [attr.text-anchor]="'middle'" [attr.x]="50" [attr.y]="50">A</svg:text>
</svg> </svg>
<svg viewBox="0 0 100 100" [attr.width]="command.width" [attr.height]="command.height" [attr.x]="command.x" [attr.y]="command.y" <svg viewBox="0 0 100 100" [attr.width]="command.width" [attr.height]="command.height" [attr.x]="command.x" [attr.y]="command.y"
preserveAspectRatio="none" [class.disabled]="command.disabled"> preserveAspectRatio="none" [class.disabled]="command.disabled">
<svg:use *ngIf="modifierIconNames.command" [attr.xlink:href]="modifierIconNames.command" /> <svg:use *ngIf="modifierIconNames.command" [attr.xlink:href]="modifierIconNames.command" />
<svg:text *ngIf="!modifierIconNames.command" text-anchor="middle" alignment-baseline="middle" x="50" y="55">S</svg:text> <svg:text *ngIf="!modifierIconNames.command" [attr.text-anchor]="'middle'" [attr.x]="50" [attr.y]="50">S</svg:text>
</svg> </svg>
</svg> </svg>
<svg:g svg-secondary-role <svg:g svg-secondary-role

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -5,12 +5,12 @@
[attr.y]="0" [attr.y]="0"
[attr.text-anchor]="'middle'" [attr.text-anchor]="'middle'"
[attr.font-size]="25"> [attr.font-size]="25">
<tspan dy="45"> Click </tspan> <tspan dy="34"> Click </tspan>
</svg:text> </svg:text>
<svg:text <svg:text
[attr.x]="50" [attr.x]="50"
[attr.y]="0" [attr.y]="0"
[attr.text-anchor]="'middle'" [attr.text-anchor]="'middle'"
[attr.font-size]="25"> [attr.font-size]="25">
<tspan dy="80"> {{ button }} </tspan> <tspan dy="70"> {{ button }} </tspan>
</svg:text> </svg:text>

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 403 B

View File

@@ -28,26 +28,6 @@ export class SvgMouseKeyComponent implements OnChanges {
this.type = 'click'; this.type = 'click';
this.param = 'Middle'; this.param = 'Middle';
break; break;
case MouseActionParam.button4:
this.type = 'click';
this.param = 'Button 4';
break;
case MouseActionParam.button5:
this.type = 'click';
this.param = 'Button 5';
break;
case MouseActionParam.button6:
this.type = 'click';
this.param = 'Button 6';
break;
case MouseActionParam.button7:
this.type = 'click';
this.param = 'Button 7';
break;
case MouseActionParam.button8:
this.type = 'click';
this.param = 'Button 8';
break;
case MouseActionParam.scrollDown: case MouseActionParam.scrollDown:
this.type = 'scroll'; this.type = 'scroll';
this.param = 'down'; this.param = 'down';

View File

@@ -4,6 +4,6 @@
[attr.y]="0" [attr.y]="0"
[attr.text-anchor]="'middle'" [attr.text-anchor]="'middle'"
[attr.font-size]="24"> [attr.font-size]="24">
<tspan dy="45"> Move </tspan> <tspan dy="34"> Move </tspan>
</svg:text> </svg:text>
<svg:use [attr.xlink:href]="directionIcon" width="30" height="30" x="35" y="55"></svg:use> <svg:use [attr.xlink:href]="directionIcon" width="30" height="30" x="35" y="55"></svg:use>

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 332 B

View File

@@ -4,6 +4,6 @@
[attr.y]="0" [attr.y]="0"
[attr.text-anchor]="'middle'" [attr.text-anchor]="'middle'"
[attr.font-size]="24"> [attr.font-size]="24">
<tspan dy="45"> Scroll </tspan> <tspan dy="34"> Scroll </tspan>
</svg:text> </svg:text>
<svg:use [attr.xlink:href]="directionIcon" width="30" height="30" x="35" y="55"></svg:use> <svg:use [attr.xlink:href]="directionIcon" width="30" height="30" x="35" y="55"></svg:use>

Before

Width:  |  Height:  |  Size: 335 B

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -5,12 +5,12 @@
[attr.y]="0" [attr.y]="0"
[attr.text-anchor]="'middle'" [attr.text-anchor]="'middle'"
[attr.font-size]="25"> [attr.font-size]="25">
<tspan dy="45"> Speed </tspan> <tspan dy="34"> Speed </tspan>
</svg:text> </svg:text>
<svg:text <svg:text
[attr.x]="50" [attr.x]="50"
[attr.y]="0" [attr.y]="0"
[attr.text-anchor]="'middle'" [attr.text-anchor]="'middle'"
[attr.font-size]="30"> [attr.font-size]="30">
<tspan dy="80"> {{ sign }} </tspan> <tspan dy="70"> {{ sign }} </tspan>
</svg:text> </svg:text>

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 400 B

View File

@@ -1,9 +1,8 @@
<svg:text <svg:text
[attr.x]="textX" [attr.x]="0"
[attr.y]="textY" [attr.y]="textY"
text-anchor="middle" [attr.text-anchor]="'middle'">
alignment-baseline="middle"> <tspan [attr.x]="spanX" dy="0">{{ text }}</tspan>
{{ text }}
</svg:text> </svg:text>
<svg:g svg-secondary-role <svg:g svg-secondary-role
*ngIf="secondaryText" *ngIf="secondaryText"

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 316 B

View File

@@ -14,8 +14,8 @@ export class SvgOneLineTextKeyComponent implements OnChanges {
@Input() text: string; @Input() text: string;
@Input() secondaryText: string; @Input() secondaryText: string;
textX: number;
textY: number; textY: number;
spanX: number;
secondaryTextY: number; secondaryTextY: number;
secondaryHeight: number; secondaryHeight: number;
@@ -34,8 +34,8 @@ export class SvgOneLineTextKeyComponent implements OnChanges {
secondaryYModifier = 5; secondaryYModifier = 5;
} }
this.textX = this.width / 2;
this.textY = this.height / 2 - textYModifier; this.textY = this.height / 2 - textYModifier;
this.spanX = this.width / 2;
this.secondaryHeight = this.height / 4; this.secondaryHeight = this.height / 4;
this.secondaryTextY = this.height - this.secondaryHeight - SECONDARY_ROLE_BOTTOM_MARGIN - secondaryYModifier; this.secondaryTextY = this.height - this.secondaryHeight - SECONDARY_ROLE_BOTTOM_MARGIN - secondaryYModifier;

View File

@@ -1,15 +1,14 @@
<svg [attr.viewBox]="viewBox" [attr.width]="width" [attr.height]="height" [attr.y]="y"> <svg [attr.viewBox]="viewBox" [attr.width]="width" [attr.height]="height" [attr.y]="y">
<g [attr.transform]="transform"> <g id="secondaryContent" [attr.transform]="transform">
<svg viewBox="0 0 14 14" width="12" height="12" x="2" [attr.y]="textY / 3.5"> <svg viewBox="0 0 14 14" width="12" height="12" x="2" [attr.y]="textY / 3.5">
<ellipse stroke="#fff" rx="6.5" ry="6.5" cy="7" cx="7" stroke-width="1" fill-opacity="0"/> <ellipse stroke="#fff" rx="6.5" ry="6.5" cy="7" cx="7" stroke-width="1" fill-opacity="0"/>
<text text-anchor="start" alignment-baseline="middle" font-family="Helvetica" font-size="12" y="7.8" x="4" stroke-width="0">2 <text text-anchor="start" font-family="Helvetica" font-size="12" y="7.8" x="4" stroke-width="0">2
</text> </text>
</svg> </svg>
<text [attr.y]="textY" <text [attr.y]="textY"
[attr.x]="textIndent" [attr.x]="textIndent"
font-size="12" font-size="12"
text-anchor="start" text-anchor="start">
alignment-baseline="middle">
{{ text }} {{ text }}
</text> </text>
</g> </g>

Before

Width:  |  Height:  |  Size: 715 B

After

Width:  |  Height:  |  Size: 667 B

View File

@@ -1,3 +0,0 @@
text {
dominant-baseline: text-bottom;
}

View File

@@ -1,10 +1,12 @@
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
ElementRef,
Input, Input,
OnChanges, OnChanges,
OnInit, OnInit,
SimpleChanges SimpleChanges,
ViewChild
} from '@angular/core'; } from '@angular/core';
import { getContentWidth } from '../../../../util'; import { getContentWidth } from '../../../../util';
@@ -16,7 +18,6 @@ const SECONDARY_STYLE: CSSStyleDeclaration = {
@Component({ @Component({
selector: 'g[svg-secondary-role]', selector: 'g[svg-secondary-role]',
templateUrl: './svg-secondary-role.component.html', templateUrl: './svg-secondary-role.component.html',
styleUrls: ['./svg-secondary-role.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class SvgSecondaryRoleComponent implements OnInit, OnChanges { export class SvgSecondaryRoleComponent implements OnInit, OnChanges {
@@ -25,6 +26,8 @@ export class SvgSecondaryRoleComponent implements OnInit, OnChanges {
@Input() y: number; @Input() y: number;
@Input() text: string; @Input() text: string;
@ViewChild('secondary') svgElement: ElementRef;
viewBox: string; viewBox: string;
textY: number; textY: number;
transform: string; transform: string;

View File

@@ -5,9 +5,8 @@
[attr.y]="useY"> [attr.y]="useY">
</svg:use> </svg:use>
<svg:text <svg:text
[attr.x]="textX" [attr.x]="0"
[attr.y]="textY" [attr.y]="textY"
text-anchor="middle" [attr.text-anchor]="'middle'">
alignment-baseline="middle"> <tspan [attr.x]="spanX">{{ abbreviation }}</tspan>
{{ abbreviation }}
</svg:text> </svg:text>

Before

Width:  |  Height:  |  Size: 305 B

After

Width:  |  Height:  |  Size: 313 B

View File

@@ -18,7 +18,7 @@ export class SvgSwitchKeymapKeyComponent implements OnInit {
useX: number; useX: number;
useY: number; useY: number;
textY: number; textY: number;
textX: number; spanX: number;
constructor(private mapperService: MapperService) { } constructor(private mapperService: MapperService) { }
@@ -30,6 +30,6 @@ export class SvgSwitchKeymapKeyComponent implements OnInit {
this.useX = this.width * 3 / 8; this.useX = this.width * 3 / 8;
this.useY = this.height / 5; this.useY = this.height / 5;
this.textY = this.height * 2 / 3; this.textY = this.height * 2 / 3;
this.textX = this.width / 2; this.spanX = this.width / 2;
} }
} }

View File

@@ -1,9 +1,8 @@
<svg:text <svg:text
[attr.x]="textX" [attr.x]="0"
[attr.y]="textY" [attr.y]="textY"
[attr.text-anchor]="textAnchor" [attr.text-anchor]="textAnchor">
alignment-baseline="middle"> <tspan [attr.x]="spanX">{{ text }}</tspan>
{{ text }}
</svg:text> </svg:text>
<svg:use [attr.xlink:href]="icon" <svg:use [attr.xlink:href]="icon"
[attr.width]="useWidth" [attr.width]="useWidth"

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -21,7 +21,7 @@ export class SvgTextIconKeyComponent implements OnChanges {
useY: number; useY: number;
textY: number; textY: number;
textAnchor: string; textAnchor: string;
textX: number; spanX: number;
secondaryTextY: number; secondaryTextY: number;
secondaryHeight: number; secondaryHeight: number;
@@ -46,7 +46,7 @@ export class SvgTextIconKeyComponent implements OnChanges {
this.useY = (this.width > 2 * this.height) ? this.height / 3 : this.height / 2; this.useY = (this.width > 2 * this.height) ? this.height / 3 : this.height / 2;
this.textY = ((this.width > 2 * this.height) ? this.height / 2 : this.height / 3) - textYModifier; this.textY = ((this.width > 2 * this.height) ? this.height / 2 : this.height / 3) - textYModifier;
this.textAnchor = (this.width > 2 * this.height) ? 'end' : 'middle'; this.textAnchor = (this.width > 2 * this.height) ? 'end' : 'middle';
this.textX = (this.width > 2 * this.height) ? 0.6 * this.width : this.width / 2; this.spanX = (this.width > 2 * this.height) ? 0.6 * this.width : this.width / 2;
this.secondaryHeight = this.height / 4; this.secondaryHeight = this.height / 4;
this.secondaryTextY = this.height - this.secondaryHeight - SECONDARY_ROLE_BOTTOM_MARGIN - secondaryYModifier; this.secondaryTextY = this.height - this.secondaryHeight - SECONDARY_ROLE_BOTTOM_MARGIN - secondaryYModifier;

View File

@@ -1,12 +1,12 @@
<svg:text <svg:text
[attr.x]="0" [attr.x]="0"
[attr.y]="textY" [attr.y]="textY"
text-anchor="middle" [attr.text-anchor]="'middle'">
alignment-baseline="middle">
<tspan <tspan
*ngFor="let text of texts; let index = index" *ngFor="let text of texts; let index = index"
[attr.x]="spanX" [attr.x]="spanX"
[attr.y]="spanYs[index]" [attr.y]="spanYs[index]"
dy="0"
>{{ text }}</tspan> >{{ text }}</tspan>
</svg:text> </svg:text>
<svg:g svg-secondary-role <svg:g svg-secondary-role

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 474 B

View File

@@ -27,11 +27,13 @@ export class SvgTwoLineTextKeyComponent implements OnChanges {
} }
calculatePositions(): void { calculatePositions(): void {
let textYModifier = 0;
let secondaryYModifier = 0; let secondaryYModifier = 0;
this.secondaryHeight = 0; this.secondaryHeight = 0;
let textContainerHeight = this.height; let textContainerHeight = this.height;
if (this.secondaryText) { if (this.secondaryText) {
textYModifier = this.height / 5;
secondaryYModifier = 0; secondaryYModifier = 0;
this.secondaryHeight = this.height / 4; this.secondaryHeight = this.height / 4;
textContainerHeight -= this.secondaryHeight; textContainerHeight -= this.secondaryHeight;
@@ -41,7 +43,7 @@ export class SvgTwoLineTextKeyComponent implements OnChanges {
this.spanX = this.width / 2; this.spanX = this.width / 2;
this.spanYs = []; this.spanYs = [];
for (let i = 0; i < this.texts.length; ++i) { for (let i = 0; i < this.texts.length; ++i) {
this.spanYs.push((0.85 - i * 0.5) * textContainerHeight); this.spanYs.push((0.75 - i * 0.5) * textContainerHeight);
} }
this.secondaryTextY = this.height - this.secondaryHeight - SECONDARY_ROLE_BOTTOM_MARGIN - secondaryYModifier; this.secondaryTextY = this.height - this.secondaryHeight - SECONDARY_ROLE_BOTTOM_MARGIN - secondaryYModifier;

View File

@@ -73,7 +73,7 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
@Output() descriptionChanged = new EventEmitter<ChangeKeymapDescription>(); @Output() descriptionChanged = new EventEmitter<ChangeKeymapDescription>();
@ViewChild(PopoverComponent, { read: ElementRef, static: false }) popover: ElementRef; @ViewChild(PopoverComponent, { read: ElementRef }) popover: ElementRef;
popoverShown: boolean; popoverShown: boolean;
keyEditConfig: { moduleId: number, keyId: number }; keyEditConfig: { moduleId: number, keyId: number };
@@ -218,7 +218,7 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
return; return;
} }
const el = event.target as Element; const el: Element = event.target as Element || event.srcElement;
const position: ClientRect = el.getBoundingClientRect(); const position: ClientRect = el.getBoundingClientRect();
let posLeft: number = this.tooltipData.posLeft; let posLeft: number = this.tooltipData.posLeft;
let posTop: number = this.tooltipData.posTop; let posTop: number = this.tooltipData.posTop;

View File

@@ -10,11 +10,13 @@ import { XtermLog } from '../../models/xterm-log';
export class XtermComponent implements OnChanges { export class XtermComponent implements OnChanges {
@Input() logs: Array<XtermLog> = []; @Input() logs: Array<XtermLog> = [];
@ViewChild('scrollMe', { static: false }) divElement: ElementRef; @ViewChild('scrollMe') divElement: ElementRef;
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (changes.logs) { if (changes.logs && this.divElement && this.divElement.nativeElement) {
this.scrollToTheEnd(); setTimeout(() => {
this.divElement.nativeElement.scrollTop = this.divElement.nativeElement.scrollHeight;
});
} }
} }
@@ -22,11 +24,4 @@ export class XtermComponent implements OnChanges {
return this.logs.reduce((value, line) => value + line.message + '\n', ''); return this.logs.reduce((value, line) => value + line.message + '\n', '');
} }
scrollToTheEnd(): void {
setTimeout(() => {
if (this.divElement && this.divElement.nativeElement) {
this.divElement.nativeElement.scrollTop = this.divElement.nativeElement.scrollHeight;
}
});
}
} }

View File

@@ -1,3 +1 @@
export * from './last-edited-key'; export * from './last-edited-key';
export * from './macro-menu-item';
export * from './side-menu-page-state';

View File

@@ -1,5 +0,0 @@
export interface MacroMenuItem {
id: number;
name: string;
usageCount: number;
}

View File

@@ -1,5 +1,4 @@
import { Keymap, Macro } from 'uhk-common'; import { Keymap, Macro } from 'uhk-common';
import { MacroMenuItem } from './macro-menu-item';
export interface SideMenuPageState { export interface SideMenuPageState {
showAddonMenu: boolean; showAddonMenu: boolean;
@@ -7,7 +6,6 @@ export interface SideMenuPageState {
updatingFirmware: boolean; updatingFirmware: boolean;
deviceName: string; deviceName: string;
keymaps: Keymap[]; keymaps: Keymap[];
macros: MacroMenuItem[]; macros: Macro[];
restoreUserConfiguration: boolean; restoreUserConfiguration: boolean;
macroUsageCountVisible: boolean;
} }

View File

@@ -19,9 +19,7 @@ export enum ActionTypes {
SetupPermissionError = '[app] Setup permission error', SetupPermissionError = '[app] Setup permission error',
LoadAppStartInfo = '[app] Load app start info', LoadAppStartInfo = '[app] Load app start info',
StartKeypressCapturing = '[app] Start keypress capturing', StartKeypressCapturing = '[app] Start keypress capturing',
StopKeypressCapturing = '[app] Stop keypress capturing', StopKeypressCapturing = '[app] Stop keypress capturing'
KeyDown = '[app] Key down',
KeyUp = '[app] Key up'
} }
export class AppBootstrappedAction implements Action { export class AppBootstrappedAction implements Action {
@@ -112,18 +110,6 @@ export class StopKeypressCapturingAction implements Action {
type = ActionTypes.StopKeypressCapturing; type = ActionTypes.StopKeypressCapturing;
} }
export class KeyDownAction implements Action {
readonly type = ActionTypes.KeyDown;
constructor(public payload: KeyboardEvent) {}
}
export class KeyUpAction implements Action {
readonly type = ActionTypes.KeyUp;
constructor(public payload: KeyboardEvent) {}
}
export type Actions export type Actions
= AppStartedAction = AppStartedAction
| AppBootstrappedAction | AppBootstrappedAction
@@ -141,6 +127,4 @@ export type Actions
| LoadAppStartInfoAction | LoadAppStartInfoAction
| StartKeypressCapturingAction | StartKeypressCapturingAction
| StopKeypressCapturingAction | StopKeypressCapturingAction
| KeyDownAction
| KeyUpAction
; ;

View File

@@ -1,7 +1,7 @@
import { ActionReducerMap, createSelector, MetaReducer } from '@ngrx/store'; import { ActionReducerMap, createSelector, MetaReducer } from '@ngrx/store';
import { routerReducer, RouterReducerState } from '@ngrx/router-store'; import { routerReducer, RouterReducerState } from '@ngrx/router-store';
import { storeFreeze } from 'ngrx-store-freeze'; import { storeFreeze } from 'ngrx-store-freeze';
import { HardwareModules, Keymap, UserConfiguration, PlayMacroAction } from 'uhk-common'; import { HardwareModules, Keymap, UserConfiguration } from 'uhk-common';
import * as fromUserConfig from './reducers/user-configuration'; import * as fromUserConfig from './reducers/user-configuration';
import * as fromPreset from './reducers/preset'; import * as fromPreset from './reducers/preset';
@@ -16,7 +16,6 @@ import { environment } from '../../environments/environment';
import { RouterStateUrl } from './router-util'; import { RouterStateUrl } from './router-util';
import { PrivilagePageSate } from '../models/privilage-page-sate'; import { PrivilagePageSate } from '../models/privilage-page-sate';
import { isVersionGte } from '../util'; import { isVersionGte } from '../util';
import { SideMenuPageState, MacroMenuItem } from '../models';
// State interface for the application // State interface for the application
export interface AppState { export interface AppState {
@@ -68,7 +67,6 @@ export const deviceConfigurationLoaded = createSelector(appState, fromApp.device
export const getAgentVersionInfo = createSelector(appState, fromApp.getAgentVersionInfo); export const getAgentVersionInfo = createSelector(appState, fromApp.getAgentVersionInfo);
export const getOperatingSystem = createSelector(appState, fromSelectors.getOperatingSystem); export const getOperatingSystem = createSelector(appState, fromSelectors.getOperatingSystem);
export const keypressCapturing = createSelector(appState, fromApp.keypressCapturing); export const keypressCapturing = createSelector(appState, fromApp.keypressCapturing);
export const getMacroUsageCountVisible = createSelector(appState, fromApp.macroUsageCountVisible);
export const runningOnNotSupportedWindows = createSelector(appState, fromApp.runningOnNotSupportedWindows); export const runningOnNotSupportedWindows = createSelector(appState, fromApp.runningOnNotSupportedWindows);
export const contributors = (state: AppState) => state.contributors; export const contributors = (state: AppState) => state.contributors;
export const firmwareUpgradeAllowed = createSelector(runningOnNotSupportedWindows, notSupportedOs => !notSupportedOs); export const firmwareUpgradeAllowed = createSelector(runningOnNotSupportedWindows, notSupportedOs => !notSupportedOs);
@@ -125,57 +123,25 @@ export const getPrivilegePageState = createSelector(appState, getUpdateUdevRules
}; };
}); });
export const getMacroMenuItems = (userConfiguration: UserConfiguration): MacroMenuItem[] => {
const macroMap = userConfiguration.macros.reduce((map, macro) => {
return map.set(macro.id, {
id: macro.id,
name: macro.name,
usageCount: 0
});
}, new Map<number, MacroMenuItem>());
for (const keymap of userConfiguration.keymaps) {
for (const layer of keymap.layers) {
for (const module of layer.modules) {
for (const keyAction of module.keyActions) {
if (!(keyAction instanceof PlayMacroAction)) {
continue;
}
const menuItem = macroMap.get(keyAction.macroId);
menuItem.usageCount++;
}
}
}
}
return Array
.from(macroMap.values())
.sort((first: MacroMenuItem, second: MacroMenuItem) => first.name.localeCompare(second.name));
};
export const getSideMenuPageState = createSelector( export const getSideMenuPageState = createSelector(
showAddonMenu, showAddonMenu,
runningInElectron, runningInElectron,
updatingFirmware, updatingFirmware,
getUserConfiguration, getUserConfiguration,
getRestoreUserConfiguration, getRestoreUserConfiguration,
getMacroUsageCountVisible,
(showAddonMenuValue: boolean, (showAddonMenuValue: boolean,
runningInElectronValue: boolean, runningInElectronValue: boolean,
updatingFirmwareValue: boolean, updatingFirmwareValue: boolean,
userConfiguration: UserConfiguration, userConfiguration: UserConfiguration,
restoreUserConfiguration: boolean, restoreUserConfiguration: boolean) => {
macroUsageCountVisible): SideMenuPageState => {
return { return {
showAddonMenu: showAddonMenuValue, showAddonMenu: showAddonMenuValue,
runInElectron: runningInElectronValue, runInElectron: runningInElectronValue,
updatingFirmware: updatingFirmwareValue, updatingFirmware: updatingFirmwareValue,
deviceName: userConfiguration.deviceName, deviceName: userConfiguration.deviceName,
keymaps: userConfiguration.keymaps, keymaps: userConfiguration.keymaps,
macros: getMacroMenuItems(userConfiguration), macros: userConfiguration.macros,
restoreUserConfiguration, restoreUserConfiguration
macroUsageCountVisible
}; };
} }
); );
@@ -191,6 +157,3 @@ export const layerDoubleTapSupported = createSelector(
return isVersionGte(hardwareModules.rightModuleInfo.firmwareVersion, '8.4.3'); return isVersionGte(hardwareModules.rightModuleInfo.firmwareVersion, '8.4.3');
} }
); );
export const extraMouseButtonsSupported = createSelector(getHardwareModules, (hardwareModules: HardwareModules): boolean => {
return isVersionGte(hardwareModules.rightModuleInfo.userConfigVersion, '4.1.1');
});

View File

@@ -30,7 +30,6 @@ export interface State {
platform?: string; platform?: string;
osVersion?: string; osVersion?: string;
keypressCapturing: boolean; keypressCapturing: boolean;
macroUsageCountVisible: boolean;
} }
export const initialState: State = { export const initialState: State = {
@@ -41,8 +40,7 @@ export const initialState: State = {
configLoading: true, configLoading: true,
agentVersionInfo: getVersions(), agentVersionInfo: getVersions(),
privilegeWhatWillThisDoClicked: false, privilegeWhatWillThisDoClicked: false,
keypressCapturing: false, keypressCapturing: false
macroUsageCountVisible: false
}; };
export function reducer( export function reducer(
@@ -158,8 +156,7 @@ export function reducer(
case App.ActionTypes.StartKeypressCapturing: case App.ActionTypes.StartKeypressCapturing:
return { return {
...state, ...state,
keypressCapturing: true, keypressCapturing: true
macroUsageCountVisible: false
}; };
case App.ActionTypes.StopKeypressCapturing: case App.ActionTypes.StopKeypressCapturing:
@@ -168,24 +165,6 @@ export function reducer(
keypressCapturing: false keypressCapturing: false
}; };
case App.ActionTypes.KeyDown: {
const event = (action as App.KeyDownAction).payload;
return {
...state,
macroUsageCountVisible: !state.keypressCapturing && !event.defaultPrevented && event.altKey
};
}
case App.ActionTypes.KeyUp: {
const event = (action as App.KeyDownAction).payload;
return {
...state,
macroUsageCountVisible: event.altKey
};
}
default: default:
return state; return state;
} }
@@ -218,4 +197,3 @@ export const runningOnNotSupportedWindows = (state: State): boolean => {
}; };
export const keypressCapturing = (state: State): boolean => state.keypressCapturing; export const keypressCapturing = (state: State): boolean => state.keypressCapturing;
export const macroUsageCountVisible = (state: State): boolean => state.macroUsageCountVisible;

View File

@@ -49,7 +49,7 @@ export const initialState: State = {
log: [{ message: '', cssClass: XtermCssClass.standard }], log: [{ message: '', cssClass: XtermCssClass.standard }],
restoringUserConfiguration: false, restoringUserConfiguration: false,
hasBackupUserConfiguration: false, hasBackupUserConfiguration: false,
halvesInfo: { isLeftHalfConnected: true, areHalvesMerged: false } halvesInfo: { isLeftHalfConnected: true, areHalvesMerged: true }
}; };
export function reducer(state = initialState, action: Action): State { export function reducer(state = initialState, action: Action): State {

View File

@@ -446,9 +446,16 @@ export function reducer(
const userConfiguration: UserConfiguration = Object.assign(new UserConfiguration(), state.userConfiguration); const userConfiguration: UserConfiguration = Object.assign(new UserConfiguration(), state.userConfiguration);
userConfiguration.macros = state.userConfiguration.macros.map((macro: Macro) => { userConfiguration.macros = state.userConfiguration.macros.map((macro: Macro) => {
if (macro.id === payload.id) { if (macro.id === payload.id) {
let newIndex: number = payload.newIndex;
// We need to reduce the new index for one when we are moving action down
if (newIndex > payload.oldIndex) {
--newIndex;
}
macro = new Macro(macro); macro = new Macro(macro);
macro.macroActions.splice( macro.macroActions.splice(
payload.newIndex, newIndex,
0, 0,
macro.macroActions.splice(payload.oldIndex, 1)[0] macro.macroActions.splice(payload.oldIndex, 1)[0]
); );

View File

@@ -15,7 +15,7 @@ import { effects } from './store/effects';
BrowserModule, BrowserModule,
SharedModule, SharedModule,
StoreModule.forRoot(reducers), StoreModule.forRoot(reducers),
StoreRouterConnectingModule.forRoot(), StoreRouterConnectingModule,
StoreDevtoolsModule.instrument({ StoreDevtoolsModule.instrument({
maxAge: 10 maxAge: 10
}), }),

View File

@@ -8,6 +8,4 @@ if (environment.production) {
enableProdMode(); enableProdMode();
} }
platformBrowserDynamic().bootstrapModule(UhkRendererModule, { platformBrowserDynamic().bootstrapModule(UhkRendererModule);
preserveWhitespaces: true
});

View File

@@ -8,6 +8,4 @@ if (environment.production) {
enableProdMode(); enableProdMode();
} }
platformBrowserDynamic().bootstrapModule(WebModule, { platformBrowserDynamic().bootstrapModule(WebModule);
preserveWhitespaces: true
});

View File

@@ -22,7 +22,7 @@ import { effects } from '../app/store/effects';
SharedModule, SharedModule,
routing, routing,
StoreModule.forRoot(reducers), StoreModule.forRoot(reducers),
StoreRouterConnectingModule.forRoot(), StoreRouterConnectingModule,
StoreDevtoolsModule.instrument({ StoreDevtoolsModule.instrument({
maxAge: 10 maxAge: 10
}), }),

View File

@@ -3,7 +3,7 @@
"compilerOptions": { "compilerOptions": {
"outDir": "./dist/out-tsc", "outDir": "./dist/out-tsc",
"baseUrl": "./", "baseUrl": "./",
"target": "es5", // Until https://github.com/electron/electron/issues/12011 not working without custom protocol "target": "es6",
"types": ["node"], "types": ["node"],
"lib": [ "lib": [
"es2016", "es2016",

View File

@@ -7,18 +7,9 @@ const rootDir = path.join(__dirname, '../../tmp');
const uhkHidDevice = new UhkHidDevice(logService, {}, rootDir); const uhkHidDevice = new UhkHidDevice(logService, {}, rootDir);
const uhkOperations = new UhkOperations(logService, uhkHidDevice, rootDir); const uhkOperations = new UhkOperations(logService, uhkHidDevice, rootDir);
process.on('uncaughtException', error => {
console.error('uncaughtException', error);
process.exit(1);
});
process.on('unhandledRejection', (reason: any, promise: Promise<any>): void => {
console.error('unhandledRejection', { reason, promise });
});
uhkOperations uhkOperations
.updateRightFirmwareWithKboot() .updateRightFirmware()
.then(() => uhkOperations.updateLeftModuleWithKboot()) .then(() => uhkOperations.updateLeftModule())
.then(() => console.log('Firmware upgrade finished')) .then(() => console.log('Firmware upgrade finished'))
.catch(error => { .catch(error => {
console.error(error); console.error(error);

View File

@@ -37,9 +37,9 @@
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}, },
"base64-js": { "base64-js": {
"version": "1.3.1", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
}, },
"bindings": { "bindings": {
"version": "1.5.0", "version": "1.5.0",
@@ -68,38 +68,20 @@
} }
}, },
"buffer": { "buffer": {
"version": "5.4.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.0.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz",
"integrity": "sha512-Xpgy0IwHK2N01ncykXTy6FpCWuM+CJSHoPVBLyNqyrWxsedpLvwsYUhf0ME3WRFNUhos0dMamz9cOS/xRDtU5g==", "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=",
"requires": { "requires": {
"base64-js": "^1.0.2", "base64-js": "0.0.8",
"ieee754": "^1.1.4" "ieee754": "^1.1.4",
"isarray": "^1.0.0"
} }
}, },
"buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"requires": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
},
"buffer-crc32": { "buffer-crc32": {
"version": "0.2.13", "version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
}, },
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
},
"chalk": { "chalk": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
@@ -111,9 +93,9 @@
} }
}, },
"chownr": { "chownr": {
"version": "1.1.2", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==" "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
@@ -121,11 +103,11 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
}, },
"color-convert": { "color-convert": {
"version": "1.9.3", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
"requires": { "requires": {
"color-name": "1.1.3" "color-name": "^1.1.1"
} }
}, },
"color-name": { "color-name": {
@@ -134,9 +116,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}, },
"commander": { "commander": {
"version": "2.20.0", "version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
@@ -273,9 +255,9 @@
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
}, },
"fd-slicer": { "fd-slicer": {
"version": "1.1.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
"requires": { "requires": {
"pend": "~1.2.0" "pend": "~1.2.0"
} }
@@ -290,11 +272,6 @@
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
}, },
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -330,9 +307,9 @@
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
}, },
"glob": { "glob": {
"version": "7.1.4", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"requires": { "requires": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
"inflight": "^1.0.4", "inflight": "^1.0.4",
@@ -343,9 +320,9 @@
} }
}, },
"graceful-fs": { "graceful-fs": {
"version": "4.2.1", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.1.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha512-b9usnbDGnD928gJB3LrCmxoibr3VE4U2SMo5PBuBnokWyDADTqDPXg4YpwKF1trpH+UbGp7QLicO3+aWEy0+mw==" "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
}, },
"graceful-readlink": { "graceful-readlink": {
"version": "1.0.1", "version": "1.0.1",
@@ -363,9 +340,9 @@
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
}, },
"ieee754": { "ieee754": {
"version": "1.1.13", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg=="
}, },
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
@@ -377,9 +354,9 @@
} }
}, },
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@@ -387,9 +364,9 @@
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
}, },
"interpret": { "interpret": {
"version": "1.2.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ="
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
@@ -415,9 +392,9 @@
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
}, },
"make-dir": { "make-dir": {
"version": "1.3.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz",
"integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==",
"requires": { "requires": {
"pify": "^3.0.0" "pify": "^3.0.0"
}, },
@@ -473,17 +450,17 @@
"integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==" "integrity": "sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA=="
}, },
"node-abi": { "node-abi": {
"version": "2.11.0", "version": "2.8.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.11.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.8.0.tgz",
"integrity": "sha512-kuy/aEg75u40v378WRllQ4ZexaXJiCvB68D2scDXclp/I4cRq6togpbOoKhmN07tns9Zldu51NNERo0wehfX9g==", "integrity": "sha512-1/aa2clS0pue0HjckL62CsbhWWU35HARvBDXcJtYKbYR7LnIutmpxmXbuDMV9kEviD2lP/wACOgWmmwljghHyQ==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
} }
}, },
"node-hid": { "node-hid": {
"version": "0.7.9", "version": "0.7.8",
"resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.9.tgz", "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-0.7.8.tgz",
"integrity": "sha512-vJnonTqmq3frCyTumJqG4g2IZcny3ynkfmbfDfQ90P3ZhRzcWYS/Um1ux6HFmAxmkaQnrZqIYHcGpL7kdqY8jA==", "integrity": "sha512-79Z9hw/pqIDp0kxvb353ivGgslo4i0hYQTcCqfRFxIJSO2gF9VtPla5uQY/9jTcDlON5O5YaqxbdH+8bs+m+1Q==",
"requires": { "requires": {
"bindings": "^1.5.0", "bindings": "^1.5.0",
"nan": "^2.13.2", "nan": "^2.13.2",
@@ -540,9 +517,9 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
}, },
"path-parse": { "path-parse": {
"version": "1.0.6", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME="
}, },
"pend": { "pend": {
"version": "1.2.0", "version": "1.2.0",
@@ -591,9 +568,9 @@
} }
}, },
"process-nextick-args": { "process-nextick-args": {
"version": "2.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
}, },
"pump": { "pump": {
"version": "2.0.1", "version": "2.0.1",
@@ -627,13 +604,6 @@
"safe-buffer": "~5.1.1", "safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1", "string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1" "util-deprecate": "~1.0.1"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
} }
}, },
"rechoir": { "rechoir": {
@@ -645,17 +615,17 @@
} }
}, },
"resolve": { "resolve": {
"version": "1.12.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.0.tgz",
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", "integrity": "sha512-QdgZ5bjR1WAlpLaO5yHepFvC+o3rCr6wpfE2tpJNMkXdulf2jKomQBdNRQITF3ZKHNlT71syG98yQP03gasgnA==",
"requires": { "requires": {
"path-parse": "^1.0.6" "path-parse": "^1.0.5"
} }
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.2.0", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
}, },
"seek-bzip": { "seek-bzip": {
"version": "1.0.5", "version": "1.0.5",
@@ -676,9 +646,9 @@
} }
}, },
"semver": { "semver": {
"version": "5.7.1", "version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
@@ -742,13 +712,6 @@
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": { "requires": {
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
} }
}, },
"strip-ansi": { "strip-ansi": {
@@ -803,16 +766,13 @@
} }
}, },
"tar-stream": { "tar-stream": {
"version": "1.6.2", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz",
"integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==",
"requires": { "requires": {
"bl": "^1.0.0", "bl": "^1.0.0",
"buffer-alloc": "^1.2.0",
"end-of-stream": "^1.0.0", "end-of-stream": "^1.0.0",
"fs-constants": "^1.0.0", "readable-stream": "^2.0.0",
"readable-stream": "^2.3.0",
"to-buffer": "^1.1.1",
"xtend": "^4.0.0" "xtend": "^4.0.0"
} }
}, },
@@ -829,11 +789,6 @@
"os-tmpdir": "~1.0.2" "os-tmpdir": "~1.0.2"
} }
}, },
"to-buffer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
},
"tunnel-agent": { "tunnel-agent": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -849,12 +804,12 @@
"dev": true "dev": true
}, },
"unbzip2-stream": { "unbzip2-stream": {
"version": "1.3.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
"integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
"requires": { "requires": {
"buffer": "^5.2.1", "buffer": "^3.0.1",
"through": "^2.3.8" "through": "^2.3.6"
} }
}, },
"util-deprecate": { "util-deprecate": {
@@ -881,17 +836,17 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
}, },
"yauzl": { "yauzl": {
"version": "2.10.0", "version": "2.9.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz",
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=",
"requires": { "requires": {
"buffer-crc32": "~0.2.3", "buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0" "fd-slicer": "~1.0.1"
} }
} }
} }

View File

@@ -13,7 +13,7 @@
"commander": "^2.11.0", "commander": "^2.11.0",
"decompress": "^4.2.0", "decompress": "^4.2.0",
"decompress-tarbz2": "^4.1.1", "decompress-tarbz2": "^4.1.1",
"node-hid": "0.7.9", "node-hid": "0.7.8",
"shelljs": "^0.7.8", "shelljs": "^0.7.8",
"tmp": "0.0.33", "tmp": "0.0.33",
"uhk-common": "1.0.0", "uhk-common": "1.0.0",

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env ts-node
///<reference path="./node_modules/@types/node/index.d.ts"/>
import { UhkBuffer, UserConfiguration } from 'uhk-common'; import { UhkBuffer, UserConfiguration } from 'uhk-common';
import * as fs from 'fs'; import * as fs from 'fs';

Some files were not shown because too many files have changed in this diff Show More