Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3295c5666 | ||
|
|
216793bbb8 | ||
|
|
558c8b0dbf | ||
|
|
e3c65f77df | ||
|
|
227f8f0d2c | ||
|
|
7e0bc39de1 | ||
|
|
c4d3648f73 | ||
|
|
547ab738c2 | ||
|
|
3de9e9aa84 | ||
|
|
01ac4c1e8b | ||
|
|
a0c8849f13 | ||
|
|
2a3dfcb0d0 | ||
|
|
2b3462c33f | ||
|
|
a0b838b2e9 | ||
|
|
90f56c350e | ||
|
|
5ceca41e0f | ||
|
|
721a4dc6e7 | ||
|
|
c9f03b4e57 | ||
|
|
bbb6839f7e | ||
|
|
dd973c80ea | ||
|
|
48574a121a | ||
|
|
8bc2462589 | ||
|
|
975ab8a5e9 | ||
|
|
f0a54768d4 | ||
|
|
0b69d01a0d | ||
|
|
838a92836c | ||
|
|
500ccc296b | ||
|
|
8bb9f7f839 | ||
|
|
5d1cc9202b | ||
|
|
c11658f1fc | ||
|
|
969c36561b | ||
|
|
04904aca5d | ||
|
|
ef0b0aa4ba | ||
|
|
3967593c9c | ||
|
|
b8be1c965b | ||
|
|
b32c93f0f8 | ||
|
|
711d3c0690 | ||
|
|
42b4465230 | ||
|
|
2bf7d545a2 | ||
|
|
d09c46af42 | ||
|
|
d57ba81d10 |
29
CHANGELOG.md
29
CHANGELOG.md
@@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## [1.0.4] - 2017-12-30
|
||||||
|
|
||||||
|
Firmware: [8.0.0](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/8.0.0) | Device Protocol: 4.0.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||||
|
|
||||||
|
- Add mouse speed settings.
|
||||||
|
|
||||||
|
## [1.0.3] - 2017-12-28
|
||||||
|
|
||||||
|
Firmware: [8.0.**0**](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/8.0.**0**) | Device Protocol: 4.0.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||||
|
|
||||||
|
- Add LED brightness settings.
|
||||||
|
- Some key actions, for example Left Arrow were displayed as text with modifiers and as icon without modifires. Now, they're always displayed as icons.
|
||||||
|
- Clean up firmware update console messages a bit.
|
||||||
|
- Remove the add keymap button because this feature is not only useless but confusing until it gets reimplemented.
|
||||||
|
- Explicitly mention on the macro tab of the key action popover that macro playback is not implemented yet.
|
||||||
|
- Downgrade to firmware 8.0.0 because the left I2C watchdog of firmware 8.0.1 is not proven yet.
|
||||||
|
|
||||||
|
## [1.0.2] - 2017-12-25
|
||||||
|
|
||||||
|
Firmware: [**8.0.1**](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/8.0.1) | Device Protocol: 4.0.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||||
|
|
||||||
|
- Fix firmware upgrade on Linux.
|
||||||
|
|
||||||
|
## [1.0.1] - 2017-12-22
|
||||||
|
|
||||||
|
Firmware: [7.0.0](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/7.0.0) | Device Protocol: 4.0.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||||
|
|
||||||
|
- Fix Linux privilege escalation when udev rules aren't set up.
|
||||||
|
|
||||||
## [1.0.0] - 2017-12-14
|
## [1.0.0] - 2017-12-14
|
||||||
|
|
||||||
Firmware: [**7**.0.0](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/7.0.0) | Device Protocol: 4.0.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
Firmware: [**7**.0.0](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/7.0.0) | Device Protocol: 4.0.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -7,7 +7,17 @@ Agent is the configuration application of the [Ultimate Hacking Keyboard](https:
|
|||||||
|
|
||||||
[Give it a whirl!](http://ultimatehackingkeyboard.github.io/agent/)
|
[Give it a whirl!](http://ultimatehackingkeyboard.github.io/agent/)
|
||||||
|
|
||||||
## Set up instructions
|
## Two builds to rule them all
|
||||||
|
|
||||||
|
It's worth mentioning that Agent has two builds.
|
||||||
|
|
||||||
|
The **electron build** is the desktop application which is meant to be used if you have an actual UHK at hand. It starts with an opening screen which detects your UHK. You cannot get past this screen without connecting a UHK via USB.
|
||||||
|
|
||||||
|
The **web build** is meant to be used for demonstation purposes, so people who don't yet own a UHK can get a feel of Agent and its capabilities in their browser. Eventually, WebUSB support will be added to the web build, making it able to communicate with the UHK. Given the sandboxed nature of browers, the web build will always lack features that the electron build offers, so this won't make the electron build obsolete.
|
||||||
|
|
||||||
|
The two builds share code as much as possible.
|
||||||
|
|
||||||
|
## Building the electron application
|
||||||
|
|
||||||
First up, make sure that node >=8.1.x and npm >=5.1.x are installed on your system. Next up:
|
First up, make sure that node >=8.1.x and npm >=5.1.x are installed on your system. Next up:
|
||||||
|
|
||||||
@@ -24,6 +34,13 @@ npm run electron
|
|||||||
|
|
||||||
At this point, Agent should be running on your machine.
|
At this point, Agent should be running on your machine.
|
||||||
|
|
||||||
|
## Developing the web application
|
||||||
|
|
||||||
|
- The frontend code is located in `packages/uhk-web/`
|
||||||
|
- Run the project locally with `npm run server:web`
|
||||||
|
- View the app at `http://localhost:8080`
|
||||||
|
- The app will automatically reload when you make changes
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Wanna contribute? Please let us show you [how](CONTRIBUTING.md).
|
Wanna contribute? Please let us show you [how](CONTRIBUTING.md).
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "uhk-agent",
|
"name": "uhk-agent",
|
||||||
"version": "1.0.0",
|
"version": "1.0.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"author": "Ultimate Gadget Laboratories",
|
"author": "Ultimate Gadget Laboratories",
|
||||||
"main": "electron/dist/electron-main.js",
|
"main": "electron/dist/electron-main.js",
|
||||||
"version": "1.0.0",
|
"version": "1.0.4",
|
||||||
"description": "Agent is the configuration application of the Ultimate Hacking Keyboard.",
|
"description": "Agent is the configuration application of the Ultimate Hacking Keyboard.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -86,6 +86,7 @@
|
|||||||
"server:web": "lerna exec --scope uhk-web npm start",
|
"server:web": "lerna exec --scope uhk-web npm start",
|
||||||
"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:auto-write-config": "lerna exec --scope uhk-agent npm run auto-write-config",
|
||||||
"standard-version": "standard-version",
|
"standard-version": "standard-version",
|
||||||
"pack": "node ./scripts/release.js",
|
"pack": "node ./scripts/release.js",
|
||||||
"sprites": "node ./scripts/generate-svg-sprites",
|
"sprites": "node ./scripts/generate-svg-sprites",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron ./dist/electron-main.js",
|
"start": "electron ./dist/electron-main.js",
|
||||||
|
"auto-write-config": "electron ./dist/electron-main.js --auto-write-config",
|
||||||
"build": "webpack && npm run install:build-deps && npm run build:usb && npm run download-firmware && npm run copy-blhost",
|
"build": "webpack && npm run install:build-deps && npm run build:usb && npm run download-firmware && npm run copy-blhost",
|
||||||
"build:usb": "electron-rebuild -w node-hid -p -m ./dist",
|
"build:usb": "electron-rebuild -w node-hid -p -m ./dist",
|
||||||
"install:build-deps": "cd ./dist && npm i",
|
"install:build-deps": "cd ./dist && npm i",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import * as url from 'url';
|
|||||||
import * as commandLineArgs from 'command-line-args';
|
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 { LogRegExps } from 'uhk-common';
|
||||||
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';
|
||||||
@@ -18,12 +18,14 @@ import { AppService } from './services/app.service';
|
|||||||
import { SudoService } from './services/sudo.service';
|
import { SudoService } from './services/sudo.service';
|
||||||
import { UhkBlhost } from '../../uhk-usb/src';
|
import { UhkBlhost } from '../../uhk-usb/src';
|
||||||
import * as isDev from 'electron-is-dev';
|
import * as isDev from 'electron-is-dev';
|
||||||
|
import { CommandLineInputs } from './models/command-line-inputs';
|
||||||
|
|
||||||
const optionDefinitions = [
|
const optionDefinitions = [
|
||||||
{name: 'addons', type: Boolean, defaultOption: false}
|
{name: 'addons', type: Boolean},
|
||||||
|
{name: 'auto-write-config', type: Boolean}
|
||||||
];
|
];
|
||||||
|
|
||||||
const options: CommandLineArgs = commandLineArgs(optionDefinitions);
|
const options: CommandLineInputs = commandLineArgs(optionDefinitions);
|
||||||
|
|
||||||
// import './dev-extension';
|
// import './dev-extension';
|
||||||
// require('electron-debug')({ showDevTools: true, enabled: true });
|
// require('electron-debug')({ showDevTools: true, enabled: true });
|
||||||
|
|||||||
4
packages/uhk-agent/src/models/command-line-inputs.ts
Normal file
4
packages/uhk-agent/src/models/command-line-inputs.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export interface CommandLineInputs {
|
||||||
|
addons?: boolean;
|
||||||
|
'auto-write-config'?: boolean;
|
||||||
|
}
|
||||||
@@ -16,9 +16,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-hid": "0.5.7"
|
"node-hid": "0.5.7"
|
||||||
},
|
},
|
||||||
"firmwareVersion": "7.0.0",
|
"firmwareVersion": "8.0.0",
|
||||||
"deviceProtocolVersion": "4.0.0",
|
"deviceProtocolVersion": "4.0.0",
|
||||||
"moduleProtocolVersion": "3.0.0",
|
|
||||||
"userConfigVersion": "4.0.0",
|
"userConfigVersion": "4.0.0",
|
||||||
"hardwareConfigVersion": "1.0.0"
|
"hardwareConfigVersion": "1.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,13 @@ export class AppUpdateService extends MainServiceBase {
|
|||||||
});
|
});
|
||||||
|
|
||||||
autoUpdater.on('error', (ev: any, err: string) => {
|
autoUpdater.on('error', (ev: any, err: string) => {
|
||||||
console.error('[AppUpdateService] error', err);
|
this.logService.error('[AppUpdateService] error', err);
|
||||||
this.sendIpcToWindow(IpcEvents.autoUpdater.autoUpdateError, err.substr(0, 100));
|
let msg = 'Electron updater error';
|
||||||
|
if (err) {
|
||||||
|
msg = err.substr(0, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendIpcToWindow(IpcEvents.autoUpdater.autoUpdateError, msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
autoUpdater.on('download-progress', (progressObj: ProgressInfo) => {
|
autoUpdater.on('download-progress', (progressObj: ProgressInfo) => {
|
||||||
|
|||||||
@@ -3,19 +3,21 @@ import { UhkHidDevice } from 'uhk-usb';
|
|||||||
import { readFile } from 'fs';
|
import { readFile } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import { AppStartInfo, CommandLineArgs, IpcEvents, LogService } from 'uhk-common';
|
import { AppStartInfo, IpcEvents, LogService } from 'uhk-common';
|
||||||
import { MainServiceBase } from './main-service-base';
|
import { MainServiceBase } from './main-service-base';
|
||||||
import { DeviceService } from './device.service';
|
import { DeviceService } from './device.service';
|
||||||
|
import { CommandLineInputs } from '../models/command-line-inputs';
|
||||||
|
|
||||||
export class AppService extends MainServiceBase {
|
export class AppService extends MainServiceBase {
|
||||||
constructor(protected logService: LogService,
|
constructor(protected logService: LogService,
|
||||||
protected win: Electron.BrowserWindow,
|
protected win: Electron.BrowserWindow,
|
||||||
private deviceService: DeviceService,
|
private deviceService: DeviceService,
|
||||||
private options: CommandLineArgs,
|
private options: CommandLineInputs,
|
||||||
private uhkHidDeviceService: UhkHidDevice) {
|
private uhkHidDeviceService: UhkHidDevice) {
|
||||||
super(logService, win);
|
super(logService, win);
|
||||||
|
|
||||||
ipcMain.on(IpcEvents.app.getAppStartInfo, this.handleAppStartInfo.bind(this));
|
ipcMain.on(IpcEvents.app.getAppStartInfo, this.handleAppStartInfo.bind(this));
|
||||||
|
ipcMain.on(IpcEvents.app.exit, this.exit.bind(this));
|
||||||
logService.info('[AppService] init success');
|
logService.info('[AppService] init success');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,8 +27,11 @@ export class AppService extends MainServiceBase {
|
|||||||
const packageJson = await this.getPackageJson();
|
const packageJson = await this.getPackageJson();
|
||||||
|
|
||||||
const response: AppStartInfo = {
|
const response: AppStartInfo = {
|
||||||
commandLineArgs: this.options,
|
commandLineArgs: {
|
||||||
deviceConnected: this.deviceService.isConnected,
|
addons: this.options.addons || false,
|
||||||
|
autoWriteConfig: this.options['auto-write-config'] || false
|
||||||
|
},
|
||||||
|
deviceConnected: this.uhkHidDeviceService.deviceConnected(),
|
||||||
hasPermission: this.uhkHidDeviceService.hasPermission(),
|
hasPermission: this.uhkHidDeviceService.hasPermission(),
|
||||||
agentVersionInfo: {
|
agentVersionInfo: {
|
||||||
version: packageJson.version,
|
version: packageJson.version,
|
||||||
@@ -57,4 +62,9 @@ export class AppService extends MainServiceBase {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private exit() {
|
||||||
|
this.logService.info('[AppService] exit');
|
||||||
|
this.win.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { ipcMain } from 'electron';
|
import { ipcMain } from 'electron';
|
||||||
import { ConfigurationReply, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
import { ConfigurationReply, DeviceConnectionState, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
||||||
import { Constants, snooze, UhkHidDevice, UhkOperations } from 'uhk-usb';
|
import { snooze, UhkHidDevice, UhkOperations } from 'uhk-usb';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
import { Device, devices } from 'node-hid';
|
|
||||||
import { emptyDir } from 'fs-extra';
|
import { emptyDir } from 'fs-extra';
|
||||||
|
|
||||||
import 'rxjs/add/observable/interval';
|
import 'rxjs/add/observable/interval';
|
||||||
@@ -19,13 +18,11 @@ import { QueueManager } from './queue-manager';
|
|||||||
/**
|
/**
|
||||||
* IpcMain pair of the UHK Communication
|
* IpcMain pair of the UHK Communication
|
||||||
* Functionality:
|
* Functionality:
|
||||||
* - Detect device is connected or not
|
|
||||||
* - Send UserConfiguration to the UHK Device
|
* - Send UserConfiguration to the UHK Device
|
||||||
* - Read UserConfiguration from the UHK Device
|
* - Read UserConfiguration from the UHK Device
|
||||||
*/
|
*/
|
||||||
export class DeviceService {
|
export class DeviceService {
|
||||||
private pollTimer$: Subscription;
|
private pollTimer$: Subscription;
|
||||||
private connected = false;
|
|
||||||
private queueManager = new QueueManager();
|
private queueManager = new QueueManager();
|
||||||
|
|
||||||
constructor(private logService: LogService,
|
constructor(private logService: LogService,
|
||||||
@@ -66,14 +63,6 @@ export class DeviceService {
|
|||||||
logService.debug('[DeviceService] init success');
|
logService.debug('[DeviceService] init success');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return with true is an UHK Device is connected to the computer.
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
public get isConnected(): boolean {
|
|
||||||
return this.connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return with the actual UserConfiguration from UHK Device
|
* Return with the actual UserConfiguration from UHK Device
|
||||||
* @returns {Promise<Buffer>}
|
* @returns {Promise<Buffer>}
|
||||||
@@ -89,7 +78,6 @@ export class DeviceService {
|
|||||||
success: true,
|
success: true,
|
||||||
...result
|
...result
|
||||||
};
|
};
|
||||||
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
response = {
|
response = {
|
||||||
success: false,
|
success: false,
|
||||||
@@ -103,7 +91,6 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this.connected = false;
|
|
||||||
this.stopPollTimer();
|
this.stopPollTimer();
|
||||||
this.logService.info('[DeviceService] Device connection checker stopped.');
|
this.logService.info('[DeviceService] Device connection checker stopped.');
|
||||||
}
|
}
|
||||||
@@ -154,15 +141,16 @@ export class DeviceService {
|
|||||||
|
|
||||||
this.pollTimer$ = Observable.interval(1000)
|
this.pollTimer$ = Observable.interval(1000)
|
||||||
.startWith(0)
|
.startWith(0)
|
||||||
.map(() => {
|
.map(() => this.device.deviceConnected())
|
||||||
return devices().some((dev: Device) => dev.vendorId === Constants.VENDOR_ID &&
|
|
||||||
dev.productId === Constants.PRODUCT_ID);
|
|
||||||
})
|
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.do((connected: boolean) => {
|
.do((connected: boolean) => {
|
||||||
this.connected = connected;
|
const response: DeviceConnectionState = {
|
||||||
this.win.webContents.send(IpcEvents.device.deviceConnectionStateChanged, connected);
|
connected,
|
||||||
this.logService.info(`[DeviceService] Device connection state changed to: ${connected}`);
|
hasPermission: this.device.hasPermission()
|
||||||
|
};
|
||||||
|
|
||||||
|
this.win.webContents.send(IpcEvents.device.deviceConnectionStateChanged, response);
|
||||||
|
this.logService.info('[DeviceService] Device connection state changed to:', response);
|
||||||
})
|
})
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { ipcMain, app } from 'electron';
|
|||||||
import * as isDev from 'electron-is-dev';
|
import * as isDev from 'electron-is-dev';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as sudo from 'sudo-prompt';
|
import * as sudo from 'sudo-prompt';
|
||||||
|
import { dirSync } from 'tmp';
|
||||||
|
import { emptyDir, copy } from 'fs-extra';
|
||||||
|
|
||||||
import { IpcEvents, LogService, IpcResponse } from 'uhk-common';
|
import { IpcEvents, LogService, IpcResponse } from 'uhk-common';
|
||||||
|
|
||||||
@@ -10,7 +12,7 @@ export class SudoService {
|
|||||||
|
|
||||||
constructor(private logService: LogService) {
|
constructor(private logService: LogService) {
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
this.rootDir = path.join(path.join(process.cwd(), process.argv[1]), '..');
|
this.rootDir = path.join(path.join(process.cwd(), process.argv[1]), '../../../../');
|
||||||
} else {
|
} else {
|
||||||
this.rootDir = path.dirname(app.getAppPath());
|
this.rootDir = path.dirname(app.getAppPath());
|
||||||
}
|
}
|
||||||
@@ -18,10 +20,10 @@ export class SudoService {
|
|||||||
ipcMain.on(IpcEvents.device.setPrivilegeOnLinux, this.setPrivilege.bind(this));
|
ipcMain.on(IpcEvents.device.setPrivilegeOnLinux, this.setPrivilege.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private setPrivilege(event: Electron.Event) {
|
private async setPrivilege(event: Electron.Event) {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
this.setPrivilegeOnLinux(event);
|
await this.setPrivilegeOnLinux(event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
const response: IpcResponse = {
|
const response: IpcResponse = {
|
||||||
@@ -34,23 +36,31 @@ export class SudoService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setPrivilegeOnLinux(event: Electron.Event) {
|
private async setPrivilegeOnLinux(event: Electron.Event) {
|
||||||
const scriptPath = path.join(this.rootDir, 'rules/setup-rules.sh');
|
const tmpDirectory = dirSync();
|
||||||
|
const rulesDir = path.join(this.rootDir, 'rules');
|
||||||
|
this.logService.debug('[SudoService] Copy rules dir', { src: rulesDir, dst: tmpDirectory.name });
|
||||||
|
await copy(rulesDir, tmpDirectory.name);
|
||||||
|
|
||||||
|
const scriptPath = path.join(tmpDirectory.name, 'setup-rules.sh');
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
name: 'Setting UHK access rules'
|
name: 'Setting UHK access rules'
|
||||||
};
|
};
|
||||||
const command = `sh ${scriptPath}`;
|
const command = `sh ${scriptPath}`;
|
||||||
console.log(command);
|
this.logService.debug('[SudoService] Set privilege command: ', command);
|
||||||
sudo.exec(command, options, (error: any) => {
|
sudo.exec(command, options, async (error: any) => {
|
||||||
const response = new IpcResponse();
|
const response = new IpcResponse();
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
this.logService.error('[SudoService] Error when set privilege: ', error);
|
||||||
response.success = false;
|
response.success = false;
|
||||||
response.error = error;
|
response.error = error;
|
||||||
} else {
|
} else {
|
||||||
response.success = true;
|
response.success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await emptyDir(tmpDirectory.name);
|
||||||
event.sender.send(IpcEvents.device.setPrivilegeOnLinuxReply, response);
|
event.sender.send(IpcEvents.device.setPrivilegeOnLinuxReply, response);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export interface CommandLineArgs {
|
export interface CommandLineArgs {
|
||||||
addons: boolean;
|
addons: boolean;
|
||||||
|
autoWriteConfig: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export interface DeviceConnectionState {
|
||||||
|
connected: boolean;
|
||||||
|
hasPermission: boolean;
|
||||||
|
}
|
||||||
@@ -4,3 +4,4 @@ export * from './ipc-response';
|
|||||||
export * from './app-start-info';
|
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';
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ class App {
|
|||||||
public static readonly appStarted = 'app-started';
|
public static readonly appStarted = 'app-started';
|
||||||
public static readonly getAppStartInfo = 'app-get-start-info';
|
public static readonly getAppStartInfo = 'app-get-start-info';
|
||||||
public static readonly getAppStartInfoReply = 'app-get-start-info-reply';
|
public static readonly getAppStartInfoReply = 'app-get-start-info-reply';
|
||||||
|
public static readonly exit = 'app-exit';
|
||||||
}
|
}
|
||||||
|
|
||||||
class AutoUpdate {
|
class AutoUpdate {
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ export enum UsbCommand {
|
|||||||
SetTestLed = 0x0a,
|
SetTestLed = 0x0a,
|
||||||
GetDebugBuffer = 0x0b,
|
GetDebugBuffer = 0x0b,
|
||||||
GetAdcValue = 0x0c,
|
GetAdcValue = 0x0c,
|
||||||
SetLedPwmBrightness = 0x0d
|
SetLedPwmBrightness = 0x0d,
|
||||||
|
GetModuleProperties = 0x0e
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EepromOperation {
|
export enum EepromOperation {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class UhkBlhost {
|
|||||||
let blhostPath;
|
let blhostPath;
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'linux':
|
case 'linux':
|
||||||
blhostPath = 'linux/amd64/blhost';
|
blhostPath = 'linux/x86_64/blhost';
|
||||||
break;
|
break;
|
||||||
case 'darwin':
|
case 'darwin':
|
||||||
blhostPath = 'mac/blhost';
|
blhostPath = 'mac/blhost';
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export class UhkHidDevice {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private _device: HID;
|
private _device: HID;
|
||||||
|
private _hasPermission = false;
|
||||||
|
|
||||||
constructor(private logService: LogService) {
|
constructor(private logService: LogService) {
|
||||||
}
|
}
|
||||||
@@ -38,8 +39,18 @@ export class UhkHidDevice {
|
|||||||
*/
|
*/
|
||||||
public hasPermission(): boolean {
|
public hasPermission(): boolean {
|
||||||
try {
|
try {
|
||||||
devices();
|
if (this._hasPermission) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.deviceConnected()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._hasPermission = this.getDevice() !== null;
|
||||||
|
this.close();
|
||||||
|
|
||||||
|
return this._hasPermission;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logService.error('[UhkHidDevice] hasPermission', err);
|
this.logService.error('[UhkHidDevice] hasPermission', err);
|
||||||
}
|
}
|
||||||
@@ -47,6 +58,21 @@ export class UhkHidDevice {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return with true is an UHK Device is connected to the computer.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public deviceConnected(): boolean {
|
||||||
|
const connected = devices().some((dev: Device) => dev.vendorId === Constants.VENDOR_ID &&
|
||||||
|
dev.productId === Constants.PRODUCT_ID);
|
||||||
|
|
||||||
|
if (!connected) {
|
||||||
|
this._hasPermission = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send data to the UHK device and wait for the response.
|
* Send data to the UHK device and wait for the response.
|
||||||
* Throw an error when 1st byte of the response is not 0
|
* Throw an error when 1st byte of the response is not 0
|
||||||
@@ -225,7 +251,7 @@ export class UhkHidDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function kbootKommandName(module: ModuleSlotToI2cAddress): string {
|
function kbootKommandName(module: ModuleSlotToI2cAddress): string {
|
||||||
switch (module) {
|
switch (module) {
|
||||||
case ModuleSlotToI2cAddress.leftHalf:
|
case ModuleSlotToI2cAddress.leftHalf:
|
||||||
return 'leftHalf';
|
return 'leftHalf';
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class UhkOperations {
|
|||||||
await this.blhost.runBlhostCommand([...prefix, 'flash-erase-region', '0xc000', '475136']);
|
await this.blhost.runBlhostCommand([...prefix, 'flash-erase-region', '0xc000', '475136']);
|
||||||
await this.blhost.runBlhostCommand([...prefix, 'flash-image', `"${firmwarePath}"`]);
|
await this.blhost.runBlhostCommand([...prefix, 'flash-image', `"${firmwarePath}"`]);
|
||||||
await this.blhost.runBlhostCommand([...prefix, 'reset']);
|
await this.blhost.runBlhostCommand([...prefix, 'reset']);
|
||||||
this.logService.debug('[UhkOperations] End flashing right firmware');
|
this.logService.debug('[UhkOperations] Right firmware successfully flashed');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateLeftModule(firmwarePath = this.getLeftModuleFirmwarePath()) {
|
public async updateLeftModule(firmwarePath = this.getLeftModuleFirmwarePath()) {
|
||||||
@@ -58,7 +58,8 @@ export class UhkOperations {
|
|||||||
await this.device.sendKbootCommandToModule(ModuleSlotToI2cAddress.leftHalf, KbootCommands.idle);
|
await this.device.sendKbootCommandToModule(ModuleSlotToI2cAddress.leftHalf, KbootCommands.idle);
|
||||||
this.device.close();
|
this.device.close();
|
||||||
|
|
||||||
this.logService.debug('[UhkOperations] End flashing left module firmware');
|
this.logService.debug('[UhkOperations] Left firmware successfully flashed');
|
||||||
|
this.logService.debug('[UhkOperations] Both left and right firmwares successfully flashed');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export async function retry(command: Function, maxTry = 3, logService?: LogServi
|
|||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
if (logService) {
|
if (logService) {
|
||||||
logService.error(`[retry] failed, but try run FUNCTION:\n ${command}, \n retry: ${retryCount}`);
|
logService.info(`[retry] failed, but try run FUNCTION:\n ${command}, \n retry: ${retryCount}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,13 @@
|
|||||||
"prefix": "app",
|
"prefix": "app",
|
||||||
"styles": [
|
"styles": [
|
||||||
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
|
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||||
|
"../node_modules/nouislider/distribute/nouislider.min.css",
|
||||||
"styles.scss"
|
"styles.scss"
|
||||||
],
|
],
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"../node_modules/bootstrap/dist/js/bootstrap.js",
|
"../node_modules/bootstrap/dist/js/bootstrap.js",
|
||||||
"../node_modules/select2/dist/js/select2.full.js"
|
"../node_modules/select2/dist/js/select2.full.js",
|
||||||
|
"../node_modules/nouislider/distribute/nouislider.js"
|
||||||
],
|
],
|
||||||
"environmentSource": "environments/environment.ts",
|
"environmentSource": "environments/environment.ts",
|
||||||
"environments": {
|
"environments": {
|
||||||
|
|||||||
10
packages/uhk-web/package-lock.json
generated
10
packages/uhk-web/package-lock.json
generated
@@ -5828,6 +5828,11 @@
|
|||||||
"dragula": "3.7.2"
|
"dragula": "3.7.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ng2-nouislider": {
|
||||||
|
"version": "1.7.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ng2-nouislider/-/ng2-nouislider-1.7.6.tgz",
|
||||||
|
"integrity": "sha1-YMq2P7hUbT+HGT4ImcUn0N2A3gs="
|
||||||
|
},
|
||||||
"ng2-select2": {
|
"ng2-select2": {
|
||||||
"version": "1.0.0-beta.10",
|
"version": "1.0.0-beta.10",
|
||||||
"resolved": "https://registry.npmjs.org/ng2-select2/-/ng2-select2-1.0.0-beta.10.tgz",
|
"resolved": "https://registry.npmjs.org/ng2-select2/-/ng2-select2-1.0.0-beta.10.tgz",
|
||||||
@@ -6843,6 +6848,11 @@
|
|||||||
"sort-keys": "1.1.2"
|
"sort-keys": "1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nouislider": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nouislider/-/nouislider-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-lENwxlpoYg4/5gjdaY/PMNHeVL+CMJyrO+7RzXi1MqhSSGwuJsQSJteXCQV5bE2UKEdSLARWrqIF8XSWAq7h+A=="
|
||||||
|
},
|
||||||
"npm-run-path": {
|
"npm-run-path": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||||
|
|||||||
@@ -69,9 +69,11 @@
|
|||||||
"less-loader": "4.0.5",
|
"less-loader": "4.0.5",
|
||||||
"lodash": "4.17.4",
|
"lodash": "4.17.4",
|
||||||
"ng2-dragula": "1.5.0",
|
"ng2-dragula": "1.5.0",
|
||||||
|
"ng2-nouislider": "^1.7.6",
|
||||||
"ng2-select2": "1.0.0-beta.10",
|
"ng2-select2": "1.0.0-beta.10",
|
||||||
"ngrx-store-freeze": "0.1.9",
|
"ngrx-store-freeze": "0.1.9",
|
||||||
"node-hid": "0.5.4",
|
"node-hid": "0.5.4",
|
||||||
|
"nouislider": "^10.1.0",
|
||||||
"postcss-loader": "1.3.3",
|
"postcss-loader": "1.3.3",
|
||||||
"postcss-url": "5.1.2",
|
"postcss-url": "5.1.2",
|
||||||
"protractor": "5.1.2",
|
"protractor": "5.1.2",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Routes } from '@angular/router';
|
|||||||
import { DeviceConfigurationComponent } from './configuration/device-configuration.component';
|
import { DeviceConfigurationComponent } from './configuration/device-configuration.component';
|
||||||
import { DeviceFirmwareComponent } from './firmware/device-firmware.component';
|
import { DeviceFirmwareComponent } from './firmware/device-firmware.component';
|
||||||
import { MouseSpeedComponent } from './mouse-speed/mouse-speed.component';
|
import { MouseSpeedComponent } from './mouse-speed/mouse-speed.component';
|
||||||
|
import { LEDBrightnessComponent } from './led-brightness/led-brightness.component';
|
||||||
|
|
||||||
export const deviceRoutes: Routes = [
|
export const deviceRoutes: Routes = [
|
||||||
{
|
{
|
||||||
@@ -21,6 +22,10 @@ export const deviceRoutes: Routes = [
|
|||||||
path: 'mouse-speed',
|
path: 'mouse-speed',
|
||||||
component: MouseSpeedComponent
|
component: MouseSpeedComponent
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'led-brightness',
|
||||||
|
component: LEDBrightnessComponent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'firmware',
|
path: 'firmware',
|
||||||
component: DeviceFirmwareComponent
|
component: DeviceFirmwareComponent
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from './configuration/device-configuration.component';
|
export * from './configuration/device-configuration.component';
|
||||||
export * from './firmware/device-firmware.component';
|
export * from './firmware/device-firmware.component';
|
||||||
export * from './mouse-speed/mouse-speed.component';
|
export * from './mouse-speed/mouse-speed.component';
|
||||||
|
export * from './led-brightness/led-brightness.component';
|
||||||
export * from './device.routes';
|
export * from './device.routes';
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<h1>
|
||||||
|
<i class="fa fa-sliders"></i>
|
||||||
|
<span>LED brightness</span>
|
||||||
|
</h1>
|
||||||
|
<div class="row led-setting">
|
||||||
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<slider-wrapper
|
||||||
|
label="LED display icon and layer texts brightness"
|
||||||
|
[min]="0"
|
||||||
|
[max]="255"
|
||||||
|
[step]="1"
|
||||||
|
[pips]="sliderPips"
|
||||||
|
[(ngModel)]="iconsAndLayerTextsBrightness"
|
||||||
|
(ngModelChange)="onSetPropertyValue('iconsAndLayerTextsBrightness', $event)"></slider-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row led-setting">
|
||||||
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<slider-wrapper
|
||||||
|
label="LED display alphanumeric segments brightness"
|
||||||
|
[min]="0"
|
||||||
|
[max]="255"
|
||||||
|
[step]="1"
|
||||||
|
[pips]="sliderPips"
|
||||||
|
[(ngModel)]="alphanumericSegmentsBrightness"
|
||||||
|
(ngModelChange)="onSetPropertyValue('alphanumericSegmentsBrightness', $event)"></slider-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row led-setting">
|
||||||
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<slider-wrapper
|
||||||
|
label="Key backlight brightness"
|
||||||
|
[min]="0"
|
||||||
|
[max]="255"
|
||||||
|
[step]="1"
|
||||||
|
[pips]="sliderPips"
|
||||||
|
[(ngModel)]="keyBacklightBrightness"
|
||||||
|
(ngModelChange)="onSetPropertyValue('keyBacklightBrightness', $event)"></slider-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
:host {
|
||||||
|
overflow-y: auto;
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.led-setting {
|
||||||
|
margin-bottom: 6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { AfterViewInit, Component, OnInit, OnDestroy, ViewChildren, QueryList } from '@angular/core';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState, getUserConfiguration } from '../../../store';
|
||||||
|
import { SetUserConfigurationValueAction } from '../../../store/actions/user-config';
|
||||||
|
import { SliderPips } from '../../slider-wrapper/slider-wrapper.component';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { UserConfiguration } from 'uhk-common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'device-led-brightness',
|
||||||
|
templateUrl: './led-brightness.component.html',
|
||||||
|
styleUrls: ['./led-brightness.component.scss'],
|
||||||
|
host: {
|
||||||
|
'class': 'container-fluid'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class LEDBrightnessComponent implements OnInit, OnDestroy {
|
||||||
|
public iconsAndLayerTextsBrightness: number = 0;
|
||||||
|
public alphanumericSegmentsBrightness: number = 0;
|
||||||
|
public keyBacklightBrightness: number = 0;
|
||||||
|
public sliderPips: SliderPips = {
|
||||||
|
mode: 'positions',
|
||||||
|
values: [0, 50, 100],
|
||||||
|
density: 6,
|
||||||
|
stepped: true
|
||||||
|
};
|
||||||
|
|
||||||
|
private userConfig$: Store<UserConfiguration>;
|
||||||
|
private userConfigSubscription: Subscription;
|
||||||
|
|
||||||
|
constructor(private store: Store<AppState>) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.userConfig$ = this.store.select(getUserConfiguration);
|
||||||
|
this.userConfigSubscription = this.userConfig$.subscribe(config => {
|
||||||
|
this.iconsAndLayerTextsBrightness = config.iconsAndLayerTextsBrightness;
|
||||||
|
this.alphanumericSegmentsBrightness = config.alphanumericSegmentsBrightness;
|
||||||
|
this.keyBacklightBrightness = config.keyBacklightBrightness;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.userConfigSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSetPropertyValue(propertyName: string, value: number): void {
|
||||||
|
this.store.dispatch(new SetUserConfigurationValueAction({
|
||||||
|
propertyName,
|
||||||
|
value
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,41 @@
|
|||||||
<i class="fa fa-sliders"></i>
|
<i class="fa fa-sliders"></i>
|
||||||
<span>Mouse speed</span>
|
<span>Mouse speed</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<h3>Mouse pointer speed</h3>
|
||||||
Coming soon ...
|
<div class="row mouse-speed-setting" *ngFor="let prop of moveProps">
|
||||||
</p>
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<slider-wrapper
|
||||||
|
[label]="prop.title"
|
||||||
|
[tooltip]="prop.tooltip"
|
||||||
|
[min]="moveSettings.min"
|
||||||
|
[max]="moveSettings.max"
|
||||||
|
[step]="moveSettings.step"
|
||||||
|
[pips]="sliderPips"
|
||||||
|
[valueUnit]="prop.valueUnit"
|
||||||
|
[(ngModel)]="prop.value"
|
||||||
|
(ngModelChange)="onSetPropertyValue(prop.prop, $event)"></slider-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>Mouse scroll speed</h3>
|
||||||
|
<div class="row mouse-speed-setting" *ngFor="let prop of scrollProps">
|
||||||
|
<div class="col-xs-12 col-md-6">
|
||||||
|
<slider-wrapper
|
||||||
|
[label]="prop.title"
|
||||||
|
[tooltip]="prop.tooltip"
|
||||||
|
[min]="scrollSettings.min"
|
||||||
|
[max]="scrollSettings.max"
|
||||||
|
[step]="scrollSettings.step"
|
||||||
|
[pips]="sliderPips"
|
||||||
|
[valueUnit]="prop.valueUnit"
|
||||||
|
[(ngModel)]="prop.value"
|
||||||
|
(ngModelChange)="onSetPropertyValue(prop.prop, $event)"></slider-wrapper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-danger mouse-speed-reset-button"
|
||||||
|
mwlConfirmationPopover
|
||||||
|
title="Are you sure?"
|
||||||
|
placement="top"
|
||||||
|
confirmText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
(confirm)="resetToDefault()">Reset speeds to default
|
||||||
|
</button>
|
||||||
@@ -4,4 +4,25 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mouse-speed-reset-button {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mouse-speed-setting {
|
||||||
|
margin-bottom: 6rem;
|
||||||
|
|
||||||
|
+ h3 {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState, getUserConfiguration } from '../../../store';
|
||||||
|
import { SetUserConfigurationValueAction } from '../../../store/actions/user-config';
|
||||||
|
import { DefaultUserConfigurationService } from '../../../services/default-user-configuration.service';
|
||||||
|
import { SliderPips, SliderProps } from '../../slider-wrapper/slider-wrapper.component';
|
||||||
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
|
import { UserConfiguration } from 'uhk-common';
|
||||||
|
import { ResetMouseSpeedSettingsAction } from '../../../store/actions/device';
|
||||||
|
|
||||||
|
const MOUSE_MOVE_VALUE_MULTIPLIER = 25;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'device-mouse-speed',
|
selector: 'device-mouse-speed',
|
||||||
@@ -8,5 +18,131 @@ import { Component } from '@angular/core';
|
|||||||
'class': 'container-fluid'
|
'class': 'container-fluid'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export class MouseSpeedComponent {
|
export class MouseSpeedComponent implements OnInit, OnDestroy {
|
||||||
|
public moveProps = [
|
||||||
|
{
|
||||||
|
prop: 'mouseMoveInitialSpeed',
|
||||||
|
title: 'Initial speed',
|
||||||
|
tooltip: 'When mouse movement begins, this is the starting speed.',
|
||||||
|
valueUnit: 'px/s',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseMoveBaseSpeed',
|
||||||
|
title: 'Base speed',
|
||||||
|
tooltip: 'This speed is reached after the initial moving speed sufficiently ramps up.',
|
||||||
|
valueUnit: 'px/s',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseMoveAcceleration',
|
||||||
|
title: 'Acceleration',
|
||||||
|
tooltip: 'The rate of acceleration from the initial movement speed to the base speed.',
|
||||||
|
valueUnit: 'px/s²',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseMoveDeceleratedSpeed',
|
||||||
|
title: 'Decelerated speed',
|
||||||
|
tooltip: 'This speed is used while moving with the <i>decelerate key</i> pressed.',
|
||||||
|
valueUnit: 'px/s',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseMoveAcceleratedSpeed',
|
||||||
|
title: 'Accelerated speed',
|
||||||
|
tooltip: 'This speed is used while moving with the <i>accelerate key</i> pressed.',
|
||||||
|
valueUnit: 'px/s',
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
public scrollProps = [
|
||||||
|
{
|
||||||
|
prop: 'mouseScrollInitialSpeed',
|
||||||
|
title: 'Initial speed',
|
||||||
|
tooltip: 'When mouse scrolling begins, this is the starting speed.',
|
||||||
|
valueUnit: 'pulse/s',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseScrollBaseSpeed',
|
||||||
|
title: 'Base speed',
|
||||||
|
tooltip: 'This speed is reached after the initial scrolling speed sufficiently ramps up.',
|
||||||
|
valueUnit: 'pulse/s',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseScrollAcceleration',
|
||||||
|
title: 'Acceleration',
|
||||||
|
tooltip: 'The rate of acceleration from the initial scrolling speed to the base speed.',
|
||||||
|
valueUnit: 'pulse/s²',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseScrollDeceleratedSpeed',
|
||||||
|
title: 'Decelerated speed',
|
||||||
|
tooltip: 'This speed is used while scrolling with the <i>decelerate key</i> pressed.',
|
||||||
|
valueUnit: 'pulse/s',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'mouseScrollAcceleratedSpeed',
|
||||||
|
title: 'Accelerated speed',
|
||||||
|
tooltip: 'This speed is used while scrolling with the <i>accelerate key</i> pressed.',
|
||||||
|
valueUnit: 'pulse/s',
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
public sliderPips: SliderPips = {
|
||||||
|
mode: 'positions',
|
||||||
|
values: [0, 50, 100],
|
||||||
|
density: 6,
|
||||||
|
stepped: true
|
||||||
|
};
|
||||||
|
|
||||||
|
public moveSettings: SliderProps = {
|
||||||
|
min: MOUSE_MOVE_VALUE_MULTIPLIER,
|
||||||
|
max: 6375,
|
||||||
|
step: MOUSE_MOVE_VALUE_MULTIPLIER
|
||||||
|
};
|
||||||
|
|
||||||
|
public scrollSettings: SliderProps = {
|
||||||
|
min: 1,
|
||||||
|
max: 255,
|
||||||
|
step: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
private userConfig$: Store<UserConfiguration>;
|
||||||
|
private userConfigSubscription: Subscription;
|
||||||
|
|
||||||
|
constructor(private store: Store<AppState>, private defaultUserConfigurationService: DefaultUserConfigurationService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.userConfig$ = this.store.select(getUserConfiguration);
|
||||||
|
this.userConfigSubscription = this.userConfig$.subscribe(config => {
|
||||||
|
this.moveProps.forEach(moveProp => {
|
||||||
|
moveProp.value = config[moveProp.prop] * MOUSE_MOVE_VALUE_MULTIPLIER || 0;
|
||||||
|
});
|
||||||
|
this.scrollProps.forEach(scrollProp => {
|
||||||
|
scrollProp.value = config[scrollProp.prop] || 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.userConfigSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSetPropertyValue(propertyName: string, value: number): void {
|
||||||
|
this.store.dispatch(new SetUserConfigurationValueAction({
|
||||||
|
propertyName,
|
||||||
|
value: propertyName.indexOf('mouseMove') !== -1 ? value / MOUSE_MOVE_VALUE_MULTIPLIER : value
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
resetToDefault() {
|
||||||
|
this.store.dispatch(new ResetMouseSpeedSettingsAction());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<span> No macros are available to choose from. Create a macro first! </span>
|
<span> No macros are available to choose from. Create a macro first! </span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngIf]="macroOptions.length > 0">
|
<ng-template [ngIf]="macroOptions.length > 0">
|
||||||
|
<p><i>Please note that macro playback is not implemented yet. You can bind macros, but they don't have any effect.</i></p>
|
||||||
<div class="macro-selector">
|
<div class="macro-selector">
|
||||||
<b> Play macro: </b>
|
<b> Play macro: </b>
|
||||||
<select2 [data]="macroOptions" [value]="macroOptions[selectedMacroIndex].id" (valueChanged)="onChange($event)" [width]="'100%'"></select2>
|
<select2 [data]="macroOptions" [value]="macroOptions[selectedMacroIndex].id" (valueChanged)="onChange($event)" [width]="'100%'"></select2>
|
||||||
|
|||||||
@@ -23,6 +23,12 @@
|
|||||||
[class.disabled]="updatingFirmware$ | async">Mouse speed</a>
|
[class.disabled]="updatingFirmware$ | async">Mouse speed</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="sidebar__level-2--item">
|
||||||
|
<div class="sidebar__level-2" [routerLinkActive]="['active']">
|
||||||
|
<a [routerLink]="['/device/led-brightness']"
|
||||||
|
[class.disabled]="updatingFirmware$ | async">LED brightness</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
<li class="sidebar__level-2--item">
|
<li class="sidebar__level-2--item">
|
||||||
<div class="sidebar__level-2" [routerLinkActive]="['active']">
|
<div class="sidebar__level-2" [routerLinkActive]="['active']">
|
||||||
<a [routerLink]="['/device/configuration']"
|
<a [routerLink]="['/device/configuration']"
|
||||||
@@ -40,11 +46,11 @@
|
|||||||
<li class="sidebar__level-1--item">
|
<li class="sidebar__level-1--item">
|
||||||
<div class="sidebar__level-1">
|
<div class="sidebar__level-1">
|
||||||
<i class="fa fa-keyboard-o"></i> Keymaps
|
<i class="fa fa-keyboard-o"></i> Keymaps
|
||||||
<a [routerLink]="['/keymap/add']"
|
<!--a [routerLink]="['/keymap/add']"
|
||||||
class="btn btn-default pull-right btn-sm"
|
class="btn btn-default pull-right btn-sm"
|
||||||
[class.disabled]="updatingFirmware$ | async">
|
[class.disabled]="updatingFirmware$ | async">
|
||||||
<i class="fa fa-plus"></i>
|
<i class="fa fa-plus"></i>
|
||||||
</a>
|
</a-->
|
||||||
<i class="fa fa-chevron-up pull-right"
|
<i class="fa fa-chevron-up pull-right"
|
||||||
(click)="toggleHide($event, 'keymap')"></i>
|
(click)="toggleHide($event, 'keymap')"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<label *ngIf="label">
|
||||||
|
<span>{{label}}</span>
|
||||||
|
<icon name="question-circle"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
[title]="tooltip"
|
||||||
|
html="true"
|
||||||
|
data-placement="bottom"
|
||||||
|
*ngIf="tooltip"></icon>
|
||||||
|
</label>
|
||||||
|
<div class="slider-wrapper">
|
||||||
|
<div class="slider-container">
|
||||||
|
<nouislider
|
||||||
|
[min]="min"
|
||||||
|
[max]="max"
|
||||||
|
[step]="step"
|
||||||
|
[keyboard]="true"
|
||||||
|
[tooltips]="true"
|
||||||
|
[(ngModel)]="value"
|
||||||
|
(ngModelChange)="onSliderChange($event)"></nouislider>
|
||||||
|
</div>
|
||||||
|
<div class="slider-value">
|
||||||
|
<div class="value-indicator">{{value}} {{valueUnit}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
:host {
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-left: 1.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-container {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-value {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-indicator {
|
||||||
|
margin: 1rem 1rem 1rem 3rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import { AfterViewInit, Component, EventEmitter, forwardRef, Input, Output, OnDestroy, ViewChild } from '@angular/core';
|
||||||
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
import { NouisliderComponent } from 'ng2-nouislider/src/nouislider';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Observer } from 'rxjs/Observer';
|
||||||
|
import 'rxjs/add/operator/debounceTime';
|
||||||
|
import 'rxjs/add/operator/distinctUntilChanged';
|
||||||
|
|
||||||
|
export interface SliderPips {
|
||||||
|
mode: string;
|
||||||
|
values: number[];
|
||||||
|
density: number;
|
||||||
|
stepped?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SliderProps {
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
step?: number;
|
||||||
|
pips?: SliderPips;
|
||||||
|
valueUnit?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'slider-wrapper',
|
||||||
|
templateUrl: './slider-wrapper.component.html',
|
||||||
|
styleUrls: ['./slider-wrapper.component.scss'],
|
||||||
|
providers: [
|
||||||
|
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderWrapperComponent), multi: true }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class SliderWrapperComponent implements AfterViewInit, ControlValueAccessor, OnDestroy {
|
||||||
|
@ViewChild(NouisliderComponent) slider: NouisliderComponent;
|
||||||
|
@Input() label: string;
|
||||||
|
@Input() tooltip: string;
|
||||||
|
@Input() min: number;
|
||||||
|
@Input() max: number;
|
||||||
|
@Input() step: number;
|
||||||
|
@Input() pips: SliderPips;
|
||||||
|
@Input() valueUnit: string;
|
||||||
|
@Output() onChange = new EventEmitter<number>();
|
||||||
|
|
||||||
|
public value: number;
|
||||||
|
private changeObserver$: Observer<number>;
|
||||||
|
private changeDebounceTime: number = 300;
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
if (this.pips) {
|
||||||
|
this.slider.slider.pips(this.pips);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide tooltips and show them when dragging slider handle
|
||||||
|
this.slider.slider.target.querySelector('.noUi-tooltip').style.display = 'none';
|
||||||
|
|
||||||
|
this.slider.slider.on('start', function() {
|
||||||
|
this.target.querySelector('.noUi-tooltip').style.display = 'block';
|
||||||
|
});
|
||||||
|
this.slider.slider.on('end', function() {
|
||||||
|
this.target.querySelector('.noUi-tooltip').style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
if (this.changeObserver$) {
|
||||||
|
this.changeObserver$.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeValue(value: number): void {
|
||||||
|
this.value = value || this.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: any): void {
|
||||||
|
this.propagateChange = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnTouched() {}
|
||||||
|
|
||||||
|
onSliderChange(value: number): void {
|
||||||
|
if (!this.changeObserver$) {
|
||||||
|
Observable.create(observer => {
|
||||||
|
this.changeObserver$ = observer;
|
||||||
|
}).debounceTime(this.changeDebounceTime)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.subscribe(this.propagateChange);
|
||||||
|
|
||||||
|
return; // No change event on first change as the value is just being set
|
||||||
|
}
|
||||||
|
this.changeObserver$.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private propagateChange: any = () => {};
|
||||||
|
}
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
<svg [attr.viewBox]="viewBox" [attr.width]="textContainer.width" [attr.height]="textContainer.height"
|
<svg [attr.viewBox]="viewBox" [attr.width]="textContainer.width" [attr.height]="textContainer.height"
|
||||||
[attr.x]="textContainer.x" [attr.y]="textContainer.y" [ngSwitch]="labelType">
|
[attr.x]="textContainer.x" [attr.y]="textContainer.y" [ngSwitch]="labelType">
|
||||||
|
<svg:g svg-single-icon-key *ngSwitchCase="'icon'"
|
||||||
|
[height]="height"
|
||||||
|
[width]="width"
|
||||||
|
[icon]="labelSource">
|
||||||
|
</svg:g>
|
||||||
<svg:g svg-one-line-text-key *ngSwitchCase="'one-line'"
|
<svg:g svg-one-line-text-key *ngSwitchCase="'one-line'"
|
||||||
[height]="height"
|
[height]="height"
|
||||||
[width]="width"
|
[width]="width"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -127,21 +127,23 @@ export class SvgKeystrokeKeyComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
let newLabelSource: string[];
|
|
||||||
if (this.keystrokeAction.hasScancode()) {
|
if (this.keystrokeAction.hasScancode()) {
|
||||||
const scancode: number = this.keystrokeAction.scancode;
|
const scancode: number = this.keystrokeAction.scancode;
|
||||||
newLabelSource = this.mapper.scanCodeToText(scancode, this.keystrokeAction.type);
|
this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode, this.keystrokeAction.type);
|
||||||
if (newLabelSource) {
|
if (this.labelSource) {
|
||||||
if (newLabelSource.length === 1) {
|
|
||||||
this.labelSource = newLabelSource[0];
|
|
||||||
this.labelType = 'one-line';
|
|
||||||
} else {
|
|
||||||
this.labelSource = newLabelSource;
|
|
||||||
this.labelType = 'two-line';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode, this.keystrokeAction.type);
|
|
||||||
this.labelType = 'icon';
|
this.labelType = 'icon';
|
||||||
|
} else {
|
||||||
|
let newLabelSource: string[];
|
||||||
|
newLabelSource = this.mapper.scanCodeToText(scancode, this.keystrokeAction.type);
|
||||||
|
if (newLabelSource) {
|
||||||
|
if (newLabelSource.length === 1) {
|
||||||
|
this.labelSource = newLabelSource[0];
|
||||||
|
this.labelType = 'one-line';
|
||||||
|
} else {
|
||||||
|
this.labelSource = newLabelSource;
|
||||||
|
this.labelType = 'two-line';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.labelType = 'empty';
|
this.labelType = 'empty';
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export interface UserConfigurationValue {
|
||||||
|
propertyName: string;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { Component } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'main-page',
|
selector: 'main-page',
|
||||||
templateUrl: './main.page.html',
|
templateUrl: './main.page.html',
|
||||||
styles: [':host{height:100%; display: inline-block; width: 100%}']
|
styles: [':host{height:100%; width:100%}']
|
||||||
})
|
})
|
||||||
export class MainPage {
|
export class MainPage {
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ export class AppRendererService {
|
|||||||
this.ipcRenderer.send(IpcEvents.app.getAppStartInfo);
|
this.ipcRenderer.send(IpcEvents.app.getAppStartInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit() {
|
||||||
|
this.logService.info('[AppRendererService] exit');
|
||||||
|
this.ipcRenderer.send(IpcEvents.app.exit);
|
||||||
|
}
|
||||||
|
|
||||||
private registerEvents() {
|
private registerEvents() {
|
||||||
this.ipcRenderer.on(IpcEvents.app.getAppStartInfoReply, (event: string, arg: AppStartInfo) => {
|
this.ipcRenderer.on(IpcEvents.app.getAppStartInfoReply, (event: string, arg: AppStartInfo) => {
|
||||||
this.dispachStoreAction(new ProcessAppStartInfoAction(arg));
|
this.dispachStoreAction(new ProcessAppStartInfoAction(arg));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable, NgZone } from '@angular/core';
|
import { Injectable, NgZone } from '@angular/core';
|
||||||
import { Action, Store } from '@ngrx/store';
|
import { Action, Store } from '@ngrx/store';
|
||||||
|
|
||||||
import { IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
import { DeviceConnectionState, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
||||||
import { AppState } from '../store';
|
import { AppState } from '../store';
|
||||||
import { IpcCommonRenderer } from './ipc-common-renderer';
|
import { IpcCommonRenderer } from './ipc-common-renderer';
|
||||||
import {
|
import {
|
||||||
@@ -47,7 +47,7 @@ export class DeviceRendererService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private registerEvents(): void {
|
private registerEvents(): void {
|
||||||
this.ipcRenderer.on(IpcEvents.device.deviceConnectionStateChanged, (event: string, arg: boolean) => {
|
this.ipcRenderer.on(IpcEvents.device.deviceConnectionStateChanged, (event: string, arg: DeviceConnectionState) => {
|
||||||
this.dispachStoreAction(new ConnectionStateChangedAction(arg));
|
this.dispachStoreAction(new ConnectionStateChangedAction(arg));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,11 @@ export class MapperService {
|
|||||||
default:
|
default:
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return 'assets/compiled_sprite.svg#' + map.get(scanCode);
|
const id = map.get(scanCode);
|
||||||
|
if (!id) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return `assets/compiled_sprite.svg#${id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getIcon(iconName: string): string {
|
public getIcon(iconName: string): string {
|
||||||
|
|||||||
@@ -4917,7 +4917,7 @@
|
|||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
"mouseAction": "scrollUp"
|
"mouseAction": "scrollDown"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
@@ -4936,7 +4936,7 @@
|
|||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
"mouseAction": "scrollDown"
|
"mouseAction": "scrollUp"
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@@ -5926,7 +5926,7 @@
|
|||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
"mouseAction": "scrollUp"
|
"mouseAction": "scrollDown"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
@@ -5945,7 +5945,7 @@
|
|||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
"mouseAction": "scrollDown"
|
"mouseAction": "scrollUp"
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@@ -6927,7 +6927,7 @@
|
|||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
"mouseAction": "scrollUp"
|
"mouseAction": "scrollDown"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
@@ -6946,7 +6946,7 @@
|
|||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
"keyActionType": "mouse",
|
"keyActionType": "mouse",
|
||||||
"mouseAction": "scrollDown"
|
"mouseAction": "scrollUp"
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@@ -7105,4 +7105,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,15 @@ import { ConfirmationPopoverModule } from 'angular-confirmation-popover';
|
|||||||
|
|
||||||
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
import { DragulaModule } from 'ng2-dragula/ng2-dragula';
|
||||||
import { Select2Module } from 'ng2-select2/ng2-select2';
|
import { Select2Module } from 'ng2-select2/ng2-select2';
|
||||||
|
import { NouisliderModule } from 'ng2-nouislider';
|
||||||
|
|
||||||
import { AddOnComponent } from './components/add-on';
|
import { AddOnComponent } from './components/add-on';
|
||||||
import { KeyboardSliderComponent } from './components/keyboard/slider';
|
import { KeyboardSliderComponent } from './components/keyboard/slider';
|
||||||
import {
|
import {
|
||||||
DeviceConfigurationComponent,
|
DeviceConfigurationComponent,
|
||||||
DeviceFirmwareComponent,
|
DeviceFirmwareComponent,
|
||||||
MouseSpeedComponent
|
MouseSpeedComponent,
|
||||||
|
LEDBrightnessComponent
|
||||||
} from './components/device';
|
} from './components/device';
|
||||||
import { KeymapAddComponent, KeymapEditComponent, KeymapHeaderComponent } from './components/keymap';
|
import { KeymapAddComponent, KeymapEditComponent, KeymapHeaderComponent } from './components/keymap';
|
||||||
import { LayersComponent } from './components/layers';
|
import { LayersComponent } from './components/layers';
|
||||||
@@ -98,6 +100,7 @@ import { LoadingDevicePageComponent } from './pages/loading-page/loading-device.
|
|||||||
import { UhkDeviceLoadingGuard } from './services/uhk-device-loading.guard';
|
import { UhkDeviceLoadingGuard } from './services/uhk-device-loading.guard';
|
||||||
import { UhkDeviceLoadedGuard } from './services/uhk-device-loaded.guard';
|
import { UhkDeviceLoadedGuard } from './services/uhk-device-loaded.guard';
|
||||||
import { XtermComponent } from './components/xterm/xterm.component';
|
import { XtermComponent } from './components/xterm/xterm.component';
|
||||||
|
import { SliderWrapperComponent } from './components/slider-wrapper/slider-wrapper.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -105,6 +108,7 @@ import { XtermComponent } from './components/xterm/xterm.component';
|
|||||||
DeviceConfigurationComponent,
|
DeviceConfigurationComponent,
|
||||||
DeviceFirmwareComponent,
|
DeviceFirmwareComponent,
|
||||||
MouseSpeedComponent,
|
MouseSpeedComponent,
|
||||||
|
LEDBrightnessComponent,
|
||||||
KeymapEditComponent,
|
KeymapEditComponent,
|
||||||
KeymapHeaderComponent,
|
KeymapHeaderComponent,
|
||||||
NotificationComponent,
|
NotificationComponent,
|
||||||
@@ -163,7 +167,8 @@ import { XtermComponent } from './components/xterm/xterm.component';
|
|||||||
MainPage,
|
MainPage,
|
||||||
ProgressButtonComponent,
|
ProgressButtonComponent,
|
||||||
LoadingDevicePageComponent,
|
LoadingDevicePageComponent,
|
||||||
XtermComponent
|
XtermComponent,
|
||||||
|
SliderWrapperComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -172,6 +177,7 @@ import { XtermComponent } from './components/xterm/xterm.component';
|
|||||||
DragulaModule,
|
DragulaModule,
|
||||||
routing,
|
routing,
|
||||||
Select2Module,
|
Select2Module,
|
||||||
|
NouisliderModule,
|
||||||
NotifierModule.withConfig(angularNotifierConfig),
|
NotifierModule.withConfig(angularNotifierConfig),
|
||||||
ConfirmationPopoverModule.forRoot({
|
ConfirmationPopoverModule.forRoot({
|
||||||
confirmButtonType: 'danger' // set defaults here
|
confirmButtonType: 'danger' // set defaults here
|
||||||
@@ -187,7 +193,6 @@ import { XtermComponent } from './components/xterm/xterm.component';
|
|||||||
DataStorageRepositoryService,
|
DataStorageRepositoryService,
|
||||||
DefaultUserConfigurationService,
|
DefaultUserConfigurationService,
|
||||||
LogService,
|
LogService,
|
||||||
DefaultUserConfigurationService,
|
|
||||||
AppUpdateRendererService,
|
AppUpdateRendererService,
|
||||||
AppRendererService,
|
AppRendererService,
|
||||||
IpcCommonRenderer,
|
IpcCommonRenderer,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
import { AppStartInfo, HardwareConfiguration, Notification, type, VersionInformation } from 'uhk-common';
|
import { AppStartInfo, CommandLineArgs, HardwareConfiguration, Notification, type, VersionInformation } from 'uhk-common';
|
||||||
import { ElectronLogEntry } from '../../models/xterm-log';
|
import { ElectronLogEntry } from '../../models/xterm-log';
|
||||||
|
|
||||||
const PREFIX = '[app] ';
|
const PREFIX = '[app] ';
|
||||||
@@ -10,7 +10,7 @@ export const ActionTypes = {
|
|||||||
APP_BOOTSRAPPED: type(PREFIX + 'bootstrapped'),
|
APP_BOOTSRAPPED: type(PREFIX + 'bootstrapped'),
|
||||||
APP_STARTED: type(PREFIX + 'started'),
|
APP_STARTED: type(PREFIX + 'started'),
|
||||||
APP_SHOW_NOTIFICATION: type(PREFIX + 'show notification'),
|
APP_SHOW_NOTIFICATION: type(PREFIX + 'show notification'),
|
||||||
APP_TOGGLE_ADDON_MENU: type(PREFIX + 'toggle add-on menu'),
|
APPLY_COMMAND_LINE_ARGS: type(PREFIX + 'apply command line args'),
|
||||||
APP_PROCESS_START_INFO: type(PREFIX + 'process start info'),
|
APP_PROCESS_START_INFO: type(PREFIX + 'process start info'),
|
||||||
UNDO_LAST: type(PREFIX + 'undo last action'),
|
UNDO_LAST: type(PREFIX + 'undo last action'),
|
||||||
UNDO_LAST_SUCCESS: type(PREFIX + 'undo last action success'),
|
UNDO_LAST_SUCCESS: type(PREFIX + 'undo last action success'),
|
||||||
@@ -34,10 +34,10 @@ export class ShowNotificationAction implements Action {
|
|||||||
constructor(public payload: Notification) { }
|
constructor(public payload: Notification) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ToggleAddonMenuAction implements Action {
|
export class ApplyCommandLineArgsAction implements Action {
|
||||||
type = ActionTypes.APP_TOGGLE_ADDON_MENU;
|
type = ActionTypes.APPLY_COMMAND_LINE_ARGS;
|
||||||
|
|
||||||
constructor(public payload: boolean) { }
|
constructor(public payload: CommandLineArgs) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ProcessAppStartInfoAction implements Action {
|
export class ProcessAppStartInfoAction implements Action {
|
||||||
@@ -82,7 +82,7 @@ export type Actions
|
|||||||
= AppStartedAction
|
= AppStartedAction
|
||||||
| AppBootsrappedAction
|
| AppBootsrappedAction
|
||||||
| ShowNotificationAction
|
| ShowNotificationAction
|
||||||
| ToggleAddonMenuAction
|
| ApplyCommandLineArgsAction
|
||||||
| ProcessAppStartInfoAction
|
| ProcessAppStartInfoAction
|
||||||
| UndoLastAction
|
| UndoLastAction
|
||||||
| UndoLastSuccessAction
|
| UndoLastSuccessAction
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
import { IpcResponse, type } from 'uhk-common';
|
import { DeviceConnectionState, IpcResponse, type } from 'uhk-common';
|
||||||
|
|
||||||
const PREFIX = '[device] ';
|
const PREFIX = '[device] ';
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@ export const ActionTypes = {
|
|||||||
SET_PRIVILEGE_ON_LINUX: type(PREFIX + 'set privilege on linux'),
|
SET_PRIVILEGE_ON_LINUX: type(PREFIX + 'set privilege on linux'),
|
||||||
SET_PRIVILEGE_ON_LINUX_REPLY: type(PREFIX + 'set privilege on linux reply'),
|
SET_PRIVILEGE_ON_LINUX_REPLY: type(PREFIX + 'set privilege on linux reply'),
|
||||||
CONNECTION_STATE_CHANGED: type(PREFIX + 'connection state changed'),
|
CONNECTION_STATE_CHANGED: type(PREFIX + 'connection state changed'),
|
||||||
PERMISSION_STATE_CHANGED: type(PREFIX + 'permission state changed'),
|
|
||||||
SAVE_CONFIGURATION: type(PREFIX + 'save configuration'),
|
SAVE_CONFIGURATION: type(PREFIX + 'save configuration'),
|
||||||
SAVE_CONFIGURATION_REPLY: type(PREFIX + 'save configuration reply'),
|
SAVE_CONFIGURATION_REPLY: type(PREFIX + 'save configuration reply'),
|
||||||
SAVING_CONFIGURATION: type(PREFIX + 'saving configuration'),
|
SAVING_CONFIGURATION: type(PREFIX + 'saving configuration'),
|
||||||
@@ -17,6 +16,7 @@ export const ActionTypes = {
|
|||||||
SAVE_TO_KEYBOARD_FAILED: type(PREFIX + 'save to keyboard failed'),
|
SAVE_TO_KEYBOARD_FAILED: type(PREFIX + 'save to keyboard failed'),
|
||||||
HIDE_SAVE_TO_KEYBOARD_BUTTON: type(PREFIX + 'hide save to keyboard button'),
|
HIDE_SAVE_TO_KEYBOARD_BUTTON: type(PREFIX + 'hide save to keyboard button'),
|
||||||
RESET_USER_CONFIGURATION: type(PREFIX + 'reset user configuration'),
|
RESET_USER_CONFIGURATION: type(PREFIX + 'reset user configuration'),
|
||||||
|
RESET_MOUSE_SPEED_SETTINGS: type(PREFIX + 'reset mouse speed settings'),
|
||||||
UPDATE_FIRMWARE: type(PREFIX + 'update firmware'),
|
UPDATE_FIRMWARE: type(PREFIX + 'update firmware'),
|
||||||
UPDATE_FIRMWARE_WITH: type(PREFIX + 'update firmware with'),
|
UPDATE_FIRMWARE_WITH: type(PREFIX + 'update firmware with'),
|
||||||
UPDATE_FIRMWARE_REPLY: type(PREFIX + 'update firmware reply'),
|
UPDATE_FIRMWARE_REPLY: type(PREFIX + 'update firmware reply'),
|
||||||
@@ -39,14 +39,7 @@ export class SetPrivilegeOnLinuxReplyAction implements Action {
|
|||||||
export class ConnectionStateChangedAction implements Action {
|
export class ConnectionStateChangedAction implements Action {
|
||||||
type = ActionTypes.CONNECTION_STATE_CHANGED;
|
type = ActionTypes.CONNECTION_STATE_CHANGED;
|
||||||
|
|
||||||
constructor(public payload: boolean) {
|
constructor(public payload: DeviceConnectionState) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PermissionStateChangedAction implements Action {
|
|
||||||
type = ActionTypes.PERMISSION_STATE_CHANGED;
|
|
||||||
|
|
||||||
constructor(public payload: boolean) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,17 +110,21 @@ export class UpdateFirmwareOkButtonAction implements Action {
|
|||||||
type = ActionTypes.UPDATE_FIRMWARE_OK_BUTTON;
|
type = ActionTypes.UPDATE_FIRMWARE_OK_BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ResetMouseSpeedSettingsAction implements Action {
|
||||||
|
type = ActionTypes.RESET_MOUSE_SPEED_SETTINGS;
|
||||||
|
}
|
||||||
|
|
||||||
export type Actions
|
export type Actions
|
||||||
= SetPrivilegeOnLinuxAction
|
= SetPrivilegeOnLinuxAction
|
||||||
| SetPrivilegeOnLinuxReplyAction
|
| SetPrivilegeOnLinuxReplyAction
|
||||||
| ConnectionStateChangedAction
|
| ConnectionStateChangedAction
|
||||||
| PermissionStateChangedAction
|
|
||||||
| ShowSaveToKeyboardButtonAction
|
| ShowSaveToKeyboardButtonAction
|
||||||
| SaveConfigurationAction
|
| SaveConfigurationAction
|
||||||
| SaveConfigurationReplyAction
|
| SaveConfigurationReplyAction
|
||||||
| SaveToKeyboardSuccessAction
|
| SaveToKeyboardSuccessAction
|
||||||
| SaveToKeyboardSuccessFailed
|
| SaveToKeyboardSuccessFailed
|
||||||
| HideSaveToKeyboardButton
|
| HideSaveToKeyboardButton
|
||||||
|
| ResetMouseSpeedSettingsAction
|
||||||
| ResetUserConfigurationAction
|
| ResetUserConfigurationAction
|
||||||
| UpdateFirmwareAction
|
| UpdateFirmwareAction
|
||||||
| UpdateFirmwareWithAction
|
| UpdateFirmwareWithAction
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Action } from '@ngrx/store';
|
import { Action } from '@ngrx/store';
|
||||||
import { type, UserConfiguration, ConfigurationReply } from 'uhk-common';
|
import { type, UserConfiguration, ConfigurationReply } from 'uhk-common';
|
||||||
|
import { UserConfigurationValue } from '../../models/user-configuration-value';
|
||||||
|
|
||||||
const PREFIX = '[user-config] ';
|
const PREFIX = '[user-config] ';
|
||||||
|
|
||||||
@@ -13,7 +14,8 @@ export const ActionTypes = {
|
|||||||
SAVE_USER_CONFIG_IN_JSON_FILE: type(PREFIX + 'Save User Config in JSON file'),
|
SAVE_USER_CONFIG_IN_JSON_FILE: type(PREFIX + 'Save User Config in JSON file'),
|
||||||
SAVE_USER_CONFIG_IN_BIN_FILE: type(PREFIX + 'Save User Config in binary file'),
|
SAVE_USER_CONFIG_IN_BIN_FILE: type(PREFIX + 'Save User Config in binary file'),
|
||||||
LOAD_RESET_USER_CONFIGURATION: type(PREFIX + 'Load reset user configuration'),
|
LOAD_RESET_USER_CONFIGURATION: type(PREFIX + 'Load reset user configuration'),
|
||||||
RENAME_USER_CONFIGURATION: type(PREFIX + 'Rename user configuration')
|
RENAME_USER_CONFIGURATION: type(PREFIX + 'Rename user configuration'),
|
||||||
|
SET_USER_CONFIGURATION_VALUE: type(PREFIX + 'Set user configuration value')
|
||||||
};
|
};
|
||||||
|
|
||||||
export class LoadUserConfigAction implements Action {
|
export class LoadUserConfigAction implements Action {
|
||||||
@@ -67,6 +69,13 @@ export class RenameUserConfigurationAction implements Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SetUserConfigurationValueAction implements Action {
|
||||||
|
type = ActionTypes.SET_USER_CONFIGURATION_VALUE;
|
||||||
|
|
||||||
|
constructor(public payload: UserConfigurationValue) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type Actions
|
export type Actions
|
||||||
= LoadUserConfigAction
|
= LoadUserConfigAction
|
||||||
| LoadUserConfigSuccessAction
|
| LoadUserConfigSuccessAction
|
||||||
@@ -77,4 +86,5 @@ export type Actions
|
|||||||
| SaveUserConfigInBinaryFileAction
|
| SaveUserConfigInBinaryFileAction
|
||||||
| LoadResetUserConfigurationAction
|
| LoadResetUserConfigurationAction
|
||||||
| RenameUserConfigurationAction
|
| RenameUserConfigurationAction
|
||||||
|
| SetUserConfigurationValueAction
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Action } from '@ngrx/store';
|
import { Action, Store } from '@ngrx/store';
|
||||||
import { Actions, Effect } from '@ngrx/effects';
|
import { Actions, Effect } from '@ngrx/effects';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { NotifierService } from 'angular-notifier';
|
import { NotifierService } from 'angular-notifier';
|
||||||
@@ -13,16 +13,22 @@ import 'rxjs/add/operator/catch';
|
|||||||
import { AppStartInfo, LogService, Notification, NotificationType } from 'uhk-common';
|
import { AppStartInfo, LogService, Notification, NotificationType } from 'uhk-common';
|
||||||
import {
|
import {
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
|
ApplyCommandLineArgsAction,
|
||||||
AppStartedAction,
|
AppStartedAction,
|
||||||
DismissUndoNotificationAction,
|
DismissUndoNotificationAction,
|
||||||
ProcessAppStartInfoAction,
|
ProcessAppStartInfoAction,
|
||||||
ShowNotificationAction,
|
ShowNotificationAction,
|
||||||
ToggleAddonMenuAction,
|
UndoLastAction,
|
||||||
UndoLastAction, UpdateAgentVersionInformationAction
|
UpdateAgentVersionInformationAction
|
||||||
} from '../actions/app';
|
} from '../actions/app';
|
||||||
import { AppRendererService } from '../../services/app-renderer.service';
|
import { AppRendererService } from '../../services/app-renderer.service';
|
||||||
import { AppUpdateRendererService } from '../../services/app-update-renderer.service';
|
import { AppUpdateRendererService } from '../../services/app-update-renderer.service';
|
||||||
import { ConnectionStateChangedAction, PermissionStateChangedAction } from '../actions/device';
|
import {
|
||||||
|
ActionTypes as DeviceActions,
|
||||||
|
ConnectionStateChangedAction,
|
||||||
|
SaveToKeyboardSuccessAction
|
||||||
|
} from '../actions/device';
|
||||||
|
import { AppState, autoWriteUserConfiguration } from '../index';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApplicationEffects {
|
export class ApplicationEffects {
|
||||||
@@ -56,9 +62,11 @@ export class ApplicationEffects {
|
|||||||
.mergeMap((appInfo: AppStartInfo) => {
|
.mergeMap((appInfo: AppStartInfo) => {
|
||||||
this.logService.debug('[AppEffect][processStartInfo] payload:', appInfo);
|
this.logService.debug('[AppEffect][processStartInfo] payload:', appInfo);
|
||||||
return [
|
return [
|
||||||
new ToggleAddonMenuAction(appInfo.commandLineArgs.addons),
|
new ApplyCommandLineArgsAction(appInfo.commandLineArgs),
|
||||||
new ConnectionStateChangedAction(appInfo.deviceConnected),
|
new ConnectionStateChangedAction({
|
||||||
new PermissionStateChangedAction(appInfo.hasPermission),
|
connected: appInfo.deviceConnected,
|
||||||
|
hasPermission: appInfo.hasPermission
|
||||||
|
}),
|
||||||
new UpdateAgentVersionInformationAction(appInfo.agentVersionInfo)
|
new UpdateAgentVersionInformationAction(appInfo.agentVersionInfo)
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
@@ -68,10 +76,20 @@ export class ApplicationEffects {
|
|||||||
.map(action => action.payload)
|
.map(action => action.payload)
|
||||||
.mergeMap((action: Action) => [action, new DismissUndoNotificationAction()]);
|
.mergeMap((action: Action) => [action, new DismissUndoNotificationAction()]);
|
||||||
|
|
||||||
|
@Effect({dispatch: false}) saveToKeyboardSuccess$ = this.actions$
|
||||||
|
.ofType<SaveToKeyboardSuccessAction>(DeviceActions.SAVE_TO_KEYBOARD_SUCCESS)
|
||||||
|
.withLatestFrom(this.store.select(autoWriteUserConfiguration))
|
||||||
|
.do(([action, autoWriteUserConfig]) => {
|
||||||
|
if (autoWriteUserConfig) {
|
||||||
|
this.appRendererService.exit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions,
|
constructor(private actions$: Actions,
|
||||||
private notifierService: NotifierService,
|
private notifierService: NotifierService,
|
||||||
private appUpdateRendererService: AppUpdateRendererService,
|
private appUpdateRendererService: AppUpdateRendererService,
|
||||||
private appRendererService: AppRendererService,
|
private appRendererService: AppRendererService,
|
||||||
private logService: LogService) {
|
private logService: LogService,
|
||||||
|
private store: Store<AppState>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Action, Store } from '@ngrx/store';
|
import { Action, Store } from '@ngrx/store';
|
||||||
import { Actions, Effect, toPayload } from '@ngrx/effects';
|
import { Actions, Effect } from '@ngrx/effects';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import 'rxjs/add/observable/of';
|
import 'rxjs/add/observable/of';
|
||||||
@@ -13,13 +13,13 @@ import 'rxjs/add/operator/mergeMap';
|
|||||||
import 'rxjs/add/operator/withLatestFrom';
|
import 'rxjs/add/operator/withLatestFrom';
|
||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
|
|
||||||
import { IpcResponse, NotificationType, UhkBuffer, UserConfiguration } from 'uhk-common';
|
import { DeviceConnectionState, IpcResponse, NotificationType, UhkBuffer, UserConfiguration } from 'uhk-common';
|
||||||
import {
|
import {
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
ConnectionStateChangedAction,
|
ConnectionStateChangedAction,
|
||||||
HideSaveToKeyboardButton,
|
HideSaveToKeyboardButton,
|
||||||
PermissionStateChangedAction,
|
|
||||||
SaveConfigurationAction,
|
SaveConfigurationAction,
|
||||||
|
SaveConfigurationReplyAction,
|
||||||
SaveToKeyboardSuccessAction,
|
SaveToKeyboardSuccessAction,
|
||||||
SaveToKeyboardSuccessFailed,
|
SaveToKeyboardSuccessFailed,
|
||||||
SetPrivilegeOnLinuxReplyAction,
|
SetPrivilegeOnLinuxReplyAction,
|
||||||
@@ -46,35 +46,25 @@ export class DeviceEffects {
|
|||||||
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
||||||
.ofType<ConnectionStateChangedAction>(ActionTypes.CONNECTION_STATE_CHANGED)
|
.ofType<ConnectionStateChangedAction>(ActionTypes.CONNECTION_STATE_CHANGED)
|
||||||
.map(action => action.payload)
|
.map(action => action.payload)
|
||||||
.do((connected: boolean) => {
|
.do((state: DeviceConnectionState) => {
|
||||||
if (connected) {
|
if (!state.hasPermission) {
|
||||||
|
this.router.navigate(['/privilege']);
|
||||||
|
}
|
||||||
|
else if (state.connected) {
|
||||||
this.router.navigate(['/']);
|
this.router.navigate(['/']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.router.navigate(['/detection']);
|
this.router.navigate(['/detection']);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.switchMap((connected: boolean) => {
|
.switchMap((state: DeviceConnectionState) => {
|
||||||
if (connected) {
|
if (state.connected && state.hasPermission) {
|
||||||
return Observable.of(new LoadConfigFromDeviceAction());
|
return Observable.of(new LoadConfigFromDeviceAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Observable.empty();
|
return Observable.empty();
|
||||||
});
|
});
|
||||||
|
|
||||||
@Effect({dispatch: false})
|
|
||||||
permissionStateChange$: Observable<boolean> = this.actions$
|
|
||||||
.ofType<PermissionStateChangedAction>(ActionTypes.PERMISSION_STATE_CHANGED)
|
|
||||||
.map(action => action.payload)
|
|
||||||
.do((hasPermission: boolean) => {
|
|
||||||
if (hasPermission) {
|
|
||||||
this.router.navigate(['/detection']);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.router.navigate(['/privilege']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
@Effect({dispatch: false})
|
@Effect({dispatch: false})
|
||||||
setPrivilegeOnLinux$: Observable<Action> = this.actions$
|
setPrivilegeOnLinux$: Observable<Action> = this.actions$
|
||||||
.ofType(ActionTypes.SET_PRIVILEGE_ON_LINUX)
|
.ofType(ActionTypes.SET_PRIVILEGE_ON_LINUX)
|
||||||
@@ -89,14 +79,16 @@ export class DeviceEffects {
|
|||||||
.mergeMap((response: any) => {
|
.mergeMap((response: any) => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return [
|
return [
|
||||||
new ConnectionStateChangedAction(true),
|
new ConnectionStateChangedAction({
|
||||||
new PermissionStateChangedAction(true)
|
connected: true,
|
||||||
|
hasPermission: true
|
||||||
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
<any>new ShowNotificationAction({
|
<any>new ShowNotificationAction({
|
||||||
type: NotificationType.Error,
|
type: NotificationType.Error,
|
||||||
message: response.error.message
|
message: response.error.message || response.error
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
@@ -113,8 +105,8 @@ export class DeviceEffects {
|
|||||||
|
|
||||||
@Effect()
|
@Effect()
|
||||||
saveConfigurationReply$: Observable<Action> = this.actions$
|
saveConfigurationReply$: Observable<Action> = this.actions$
|
||||||
.ofType(ActionTypes.SAVE_CONFIGURATION_REPLY)
|
.ofType<SaveConfigurationReplyAction>(ActionTypes.SAVE_CONFIGURATION_REPLY)
|
||||||
.map(toPayload)
|
.map(action => action.payload)
|
||||||
.mergeMap((response: IpcResponse) => {
|
.mergeMap((response: IpcResponse) => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return [
|
return [
|
||||||
@@ -138,6 +130,30 @@ export class DeviceEffects {
|
|||||||
.switchMap(() => Observable.of(new HideSaveToKeyboardButton()))
|
.switchMap(() => Observable.of(new HideSaveToKeyboardButton()))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@Effect()
|
||||||
|
resetMouseSpeedSettings$: Observable<Action> = this.actions$
|
||||||
|
.ofType(ActionTypes.RESET_MOUSE_SPEED_SETTINGS)
|
||||||
|
.switchMap(() => {
|
||||||
|
const config = this.defaultUserConfigurationService.getDefault();
|
||||||
|
const mouseSpeedDefaultSettings = {};
|
||||||
|
const mouseSpeedProps = [
|
||||||
|
'mouseMoveInitialSpeed',
|
||||||
|
'mouseMoveAcceleration',
|
||||||
|
'mouseMoveDeceleratedSpeed',
|
||||||
|
'mouseMoveBaseSpeed',
|
||||||
|
'mouseMoveAcceleratedSpeed',
|
||||||
|
'mouseScrollInitialSpeed',
|
||||||
|
'mouseScrollAcceleration',
|
||||||
|
'mouseScrollDeceleratedSpeed',
|
||||||
|
'mouseScrollBaseSpeed',
|
||||||
|
'mouseScrollAcceleratedSpeed'
|
||||||
|
];
|
||||||
|
mouseSpeedProps.forEach(prop => {
|
||||||
|
mouseSpeedDefaultSettings[prop] = config[prop];
|
||||||
|
});
|
||||||
|
return Observable.of(new LoadResetUserConfigurationAction(<UserConfiguration>mouseSpeedDefaultSettings));
|
||||||
|
});
|
||||||
|
|
||||||
@Effect() resetUserConfiguration$: Observable<Action> = this.actions$
|
@Effect() resetUserConfiguration$: Observable<Action> = this.actions$
|
||||||
.ofType(ActionTypes.RESET_USER_CONFIGURATION)
|
.ofType(ActionTypes.RESET_USER_CONFIGURATION)
|
||||||
.switchMap(() => {
|
.switchMap(() => {
|
||||||
|
|||||||
@@ -12,35 +12,27 @@ import 'rxjs/add/operator/startWith';
|
|||||||
import 'rxjs/add/operator/withLatestFrom';
|
import 'rxjs/add/operator/withLatestFrom';
|
||||||
import 'rxjs/add/operator/mergeMap';
|
import 'rxjs/add/operator/mergeMap';
|
||||||
import 'rxjs/add/observable/of';
|
import 'rxjs/add/observable/of';
|
||||||
|
import 'rxjs/add/observable/empty';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConfigurationReply,
|
ConfigurationReply, HardwareConfiguration, LogService, NotificationType, UhkBuffer,
|
||||||
HardwareConfiguration,
|
|
||||||
LogService,
|
|
||||||
NotificationType,
|
|
||||||
UhkBuffer,
|
|
||||||
UserConfiguration
|
UserConfiguration
|
||||||
} from 'uhk-common';
|
} from 'uhk-common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActionTypes,
|
ActionTypes, LoadConfigFromDeviceReplyAction, LoadUserConfigSuccessAction, RenameUserConfigurationAction,
|
||||||
LoadConfigFromDeviceReplyAction,
|
|
||||||
LoadUserConfigSuccessAction,
|
|
||||||
RenameUserConfigurationAction,
|
|
||||||
SaveUserConfigSuccessAction
|
SaveUserConfigSuccessAction
|
||||||
} from '../actions/user-config';
|
} from '../actions/user-config';
|
||||||
|
|
||||||
import { DataStorageRepositoryService } from '../../services/datastorage-repository.service';
|
import { DataStorageRepositoryService } from '../../services/datastorage-repository.service';
|
||||||
import { DefaultUserConfigurationService } from '../../services/default-user-configuration.service';
|
import { DefaultUserConfigurationService } from '../../services/default-user-configuration.service';
|
||||||
import { AppState, getPrevUserConfiguration, getUserConfiguration } from '../index';
|
import { AppState, autoWriteUserConfiguration, getPrevUserConfiguration, getUserConfiguration } from '../index';
|
||||||
import { KeymapAction, KeymapActions, MacroAction, MacroActions } from '../actions';
|
import { KeymapAction, KeymapActions, MacroAction, MacroActions } from '../actions';
|
||||||
import {
|
import {
|
||||||
DismissUndoNotificationAction,
|
DismissUndoNotificationAction, LoadHardwareConfigurationSuccessAction, ShowNotificationAction,
|
||||||
LoadHardwareConfigurationSuccessAction,
|
|
||||||
ShowNotificationAction,
|
|
||||||
UndoLastAction
|
UndoLastAction
|
||||||
} from '../actions/app';
|
} from '../actions/app';
|
||||||
import { ShowSaveToKeyboardButtonAction } from '../actions/device';
|
import { SaveConfigurationAction, ShowSaveToKeyboardButtonAction } from '../actions/device';
|
||||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||||
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
||||||
|
|
||||||
@@ -80,7 +72,7 @@ export class UserConfigEffects {
|
|||||||
KeymapActions.SET_DEFAULT, KeymapActions.REMOVE, KeymapActions.SAVE_KEY,
|
KeymapActions.SET_DEFAULT, KeymapActions.REMOVE, KeymapActions.SAVE_KEY,
|
||||||
MacroActions.ADD, MacroActions.DUPLICATE, MacroActions.EDIT_NAME, MacroActions.REMOVE, MacroActions.ADD_ACTION,
|
MacroActions.ADD, MacroActions.DUPLICATE, MacroActions.EDIT_NAME, MacroActions.REMOVE, MacroActions.ADD_ACTION,
|
||||||
MacroActions.SAVE_ACTION, MacroActions.DELETE_ACTION, MacroActions.REORDER_ACTION,
|
MacroActions.SAVE_ACTION, MacroActions.DELETE_ACTION, MacroActions.REORDER_ACTION,
|
||||||
ActionTypes.RENAME_USER_CONFIGURATION) as
|
ActionTypes.RENAME_USER_CONFIGURATION, ActionTypes.SET_USER_CONFIGURATION_VALUE) as
|
||||||
Observable<KeymapAction | MacroAction | RenameUserConfigurationAction>)
|
Observable<KeymapAction | MacroAction | RenameUserConfigurationAction>)
|
||||||
.withLatestFrom(this.store.select(getUserConfiguration), this.store.select(getPrevUserConfiguration))
|
.withLatestFrom(this.store.select(getUserConfiguration), this.store.select(getPrevUserConfiguration))
|
||||||
.mergeMap(([action, config, prevUserConfiguration]) => {
|
.mergeMap(([action, config, prevUserConfiguration]) => {
|
||||||
@@ -193,6 +185,19 @@ export class UserConfigEffects {
|
|||||||
saveAs(blob, 'UserConfiguration.bin');
|
saveAs(blob, 'UserConfiguration.bin');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@Effect() loadUserConfigurationSuccess$ = this.actions$
|
||||||
|
.ofType(ActionTypes.LOAD_USER_CONFIG_SUCCESS)
|
||||||
|
.withLatestFrom(this.store.select(autoWriteUserConfiguration))
|
||||||
|
.switchMap(([action, autoWriteUserConfig]) => {
|
||||||
|
this.logService.debug('[UserConfigEffect] LOAD_USER_CONFIG_SUCCESS', {autoWriteUserConfig});
|
||||||
|
if (autoWriteUserConfig) {
|
||||||
|
return Observable.of(new SaveConfigurationAction());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Observable.empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions,
|
constructor(private actions$: Actions,
|
||||||
private dataStorageRepository: DataStorageRepositoryService,
|
private dataStorageRepository: DataStorageRepositoryService,
|
||||||
private store: Store<AppState>,
|
private store: Store<AppState>,
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export const getDeviceName = (state: AppState) => state.userConfiguration.device
|
|||||||
|
|
||||||
export const appState = (state: AppState) => state.app;
|
export const appState = (state: AppState) => state.app;
|
||||||
export const showAddonMenu = createSelector(appState, fromApp.showAddonMenu);
|
export const showAddonMenu = createSelector(appState, fromApp.showAddonMenu);
|
||||||
|
export const autoWriteUserConfiguration = createSelector(appState, fromApp.autoWriteUserConfiguration);
|
||||||
export const getUndoableNotification = createSelector(appState, fromApp.getUndoableNotification);
|
export const getUndoableNotification = createSelector(appState, fromApp.getUndoableNotification);
|
||||||
export const getPrevUserConfiguration = createSelector(appState, fromApp.getPrevUserConfiguration);
|
export const getPrevUserConfiguration = createSelector(appState, fromApp.getPrevUserConfiguration);
|
||||||
export const runningInElectron = createSelector(appState, fromApp.runningInElectron);
|
export const runningInElectron = createSelector(appState, fromApp.runningInElectron);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { KeyboardLayout } from '../../keyboard/keyboard-layout.enum';
|
|||||||
export interface State {
|
export interface State {
|
||||||
started: boolean;
|
started: boolean;
|
||||||
showAddonMenu: boolean;
|
showAddonMenu: boolean;
|
||||||
|
autoWriteUserConfiguration: boolean;
|
||||||
undoableNotification?: Notification;
|
undoableNotification?: Notification;
|
||||||
navigationCountAfterNotification: number;
|
navigationCountAfterNotification: number;
|
||||||
prevUserConfig?: UserConfiguration;
|
prevUserConfig?: UserConfiguration;
|
||||||
@@ -23,6 +24,7 @@ export interface State {
|
|||||||
export const initialState: State = {
|
export const initialState: State = {
|
||||||
started: false,
|
started: false,
|
||||||
showAddonMenu: false,
|
showAddonMenu: false,
|
||||||
|
autoWriteUserConfiguration: false,
|
||||||
navigationCountAfterNotification: 0,
|
navigationCountAfterNotification: 0,
|
||||||
runningInElectron: runInElectron(),
|
runningInElectron: runInElectron(),
|
||||||
configLoading: true
|
configLoading: true
|
||||||
@@ -37,10 +39,11 @@ export function reducer(state = initialState, action: Action & { payload: any })
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
case ActionTypes.APP_TOGGLE_ADDON_MENU: {
|
case ActionTypes.APPLY_COMMAND_LINE_ARGS: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
showAddonMenu: action.payload
|
showAddonMenu: action.payload.addons,
|
||||||
|
autoWriteUserConfiguration: action.payload.autoWriteConfig
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +127,7 @@ export function reducer(state = initialState, action: Action & { payload: any })
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const showAddonMenu = (state: State) => state.showAddonMenu;
|
export const showAddonMenu = (state: State) => state.showAddonMenu;
|
||||||
|
export const autoWriteUserConfiguration = (state: State) => state.autoWriteUserConfiguration;
|
||||||
export const getUndoableNotification = (state: State) => state.undoableNotification;
|
export const getUndoableNotification = (state: State) => state.undoableNotification;
|
||||||
export const getPrevUserConfiguration = (state: State) => state.prevUserConfig;
|
export const getPrevUserConfiguration = (state: State) => state.prevUserConfig;
|
||||||
export const runningInElectron = (state: State) => state.runningInElectron;
|
export const runningInElectron = (state: State) => state.runningInElectron;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { Action } from '@ngrx/store';
|
|||||||
import {
|
import {
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
ConnectionStateChangedAction,
|
ConnectionStateChangedAction,
|
||||||
PermissionStateChangedAction,
|
SaveConfigurationAction,
|
||||||
SaveConfigurationAction, UpdateFirmwareFailedAction
|
UpdateFirmwareFailedAction
|
||||||
} from '../actions/device';
|
} from '../actions/device';
|
||||||
import { ActionTypes as AppActions, ElectronMainLogReceivedAction } from '../actions/app';
|
import { ActionTypes as AppActions, ElectronMainLogReceivedAction } from '../actions/app';
|
||||||
import { initProgressButtonState, ProgressButtonState } from './progress-button-state';
|
import { initProgressButtonState, ProgressButtonState } from './progress-button-state';
|
||||||
@@ -30,17 +30,14 @@ export const initialState: State = {
|
|||||||
|
|
||||||
export function reducer(state = initialState, action: Action) {
|
export function reducer(state = initialState, action: Action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.CONNECTION_STATE_CHANGED:
|
case ActionTypes.CONNECTION_STATE_CHANGED: {
|
||||||
|
const data = (<ConnectionStateChangedAction>action).payload;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
connected: (<ConnectionStateChangedAction>action).payload
|
connected: data.connected,
|
||||||
};
|
hasPermission: data.hasPermission
|
||||||
|
|
||||||
case ActionTypes.PERMISSION_STATE_CHANGED:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
hasPermission: (<PermissionStateChangedAction>action).payload
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case ActionTypes.SAVING_CONFIGURATION: {
|
case ActionTypes.SAVING_CONFIGURATION: {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -246,6 +246,11 @@ export function reducer(state = initialState, action: Action & { payload?: any }
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ActionTypes.SET_USER_CONFIGURATION_VALUE: {
|
||||||
|
changedUserConfiguration[action.payload.propertyName] = action.payload.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,3 +90,7 @@ a.disabled {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.noUi-value {
|
||||||
|
top: 2rem;
|
||||||
|
}
|
||||||
|
|||||||
@@ -85,10 +85,12 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"script-loader!./node_modules/bootstrap/dist/js/bootstrap.js",
|
"script-loader!./node_modules/bootstrap/dist/js/bootstrap.js",
|
||||||
"script-loader!./node_modules/select2/dist/js/select2.full.js"
|
"script-loader!./node_modules/select2/dist/js/select2.full.js",
|
||||||
|
"script-loader!./node_modules/nouislider/distribute/nouislider.js"
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
|
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||||
|
"./node_modules/nouislider/distribute/nouislider.min.css",
|
||||||
"./src/styles.scss"
|
"./src/styles.scss"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -126,6 +128,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"exclude": [
|
"exclude": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.css$/,
|
"test": /\.css$/,
|
||||||
@@ -150,6 +153,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"exclude": [
|
"exclude": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.scss$|\.sass$/,
|
"test": /\.scss$|\.sass$/,
|
||||||
@@ -182,6 +186,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"exclude": [
|
"exclude": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.less$/,
|
"test": /\.less$/,
|
||||||
@@ -212,6 +217,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"exclude": [
|
"exclude": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.styl$/,
|
"test": /\.styl$/,
|
||||||
@@ -243,6 +249,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"include": [
|
"include": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.css$/,
|
"test": /\.css$/,
|
||||||
@@ -267,6 +274,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"include": [
|
"include": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.scss$|\.sass$/,
|
"test": /\.scss$|\.sass$/,
|
||||||
@@ -299,6 +307,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"include": [
|
"include": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.less$/,
|
"test": /\.less$/,
|
||||||
@@ -329,6 +338,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
"include": [
|
"include": [
|
||||||
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
path.join(process.cwd(), "node_modules/bootstrap/dist/css/bootstrap.min.css"),
|
||||||
|
path.join(process.cwd(), "node_modules/nouislider/distribute/nouislider.min.css"),
|
||||||
path.join(process.cwd(), "src/styles.scss")
|
path.join(process.cwd(), "src/styles.scss")
|
||||||
],
|
],
|
||||||
"test": /\.styl$/,
|
"test": /\.styl$/,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
const uhk = require('./uhk');
|
const uhk = require('./uhk');
|
||||||
|
|
||||||
const device = uhk.getUhkDevice();
|
const device = uhk.getUhkDevice();
|
||||||
const sendData = new Buffer([uhk.usbCommands.getProperty, uhk.devicePropertyIds.configSizes]);
|
const sendData = new Buffer([uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.configSizes]);
|
||||||
device.write(uhk.getTransferData(sendData));
|
device.write(uhk.getTransferData(sendData));
|
||||||
const response = Buffer.from(device.readSync());
|
const response = Buffer.from(device.readSync());
|
||||||
|
|
||||||
|
|||||||
16
packages/usb/get-left-firmware-version.js
Executable file
16
packages/usb/get-left-firmware-version.js
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const uhk = require('./uhk');
|
||||||
|
|
||||||
|
const device = uhk.getUhkDevice();
|
||||||
|
const sendData = new Buffer([uhk.usbCommands.getModuleProperty, uhk.modulePropertyIds.protocolVersions]);
|
||||||
|
console.log(sendData)
|
||||||
|
device.write(uhk.getTransferData(sendData));
|
||||||
|
const response = Buffer.from(device.readSync());
|
||||||
|
console.log(response)
|
||||||
|
const firmwareMajorVersion = response[7] + (response[8]<<8);
|
||||||
|
const firmwareMinorVersion = response[9] + (response[10]<<8);
|
||||||
|
const firmwarePatchVersion = response[11] + (response[12]<<8);
|
||||||
|
|
||||||
|
console.log(`firmwareMajorVersion: ${firmwareMajorVersion}`);
|
||||||
|
console.log(`firmwareMinorVersion: ${firmwareMinorVersion}`);
|
||||||
|
console.log(`firmwarePatchVersion: ${firmwarePatchVersion}`);
|
||||||
14
packages/usb/get-module-state.js
Executable file
14
packages/usb/get-module-state.js
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const uhk = require('./uhk');
|
||||||
|
const device = uhk.getUhkDevice();
|
||||||
|
|
||||||
|
function getModuleState() {
|
||||||
|
const payload = new Buffer([uhk.usbCommands.getModuleProperty, 1]);
|
||||||
|
console.log('Sending ', uhk.bufferToString(payload));
|
||||||
|
device.write(uhk.getTransferData(payload));
|
||||||
|
const receivedBuffer = device.readSync();
|
||||||
|
console.log('Received', uhk.bufferToString(receivedBuffer));
|
||||||
|
setTimeout(getModuleState, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
getModuleState();
|
||||||
15
packages/usb/get-right-firmware-version.js
Executable file
15
packages/usb/get-right-firmware-version.js
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const uhk = require('./uhk');
|
||||||
|
|
||||||
|
const device = uhk.getUhkDevice();
|
||||||
|
const sendData = new Buffer([uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.protocolVersions]);
|
||||||
|
device.write(uhk.getTransferData(sendData));
|
||||||
|
const response = Buffer.from(device.readSync());
|
||||||
|
|
||||||
|
const firmwareMajorVersion = response[1] + (response[2]<<8);
|
||||||
|
const firmwareMinorVersion = response[3] + (response[4]<<8);
|
||||||
|
const firmwarePatchVersion = response[5] + (response[6]<<8);
|
||||||
|
|
||||||
|
console.log(`firmwareMajorVersion: ${firmwareMajorVersion}`);
|
||||||
|
console.log(`firmwareMinorVersion: ${firmwareMinorVersion}`);
|
||||||
|
console.log(`firmwarePatchVersion: ${firmwarePatchVersion}`);
|
||||||
@@ -6,7 +6,7 @@ let counter = 1;
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
console.log(`hidapi sync test ${counter++}`);
|
console.log(`hidapi sync test ${counter++}`);
|
||||||
const sendData = new Buffer([uhk.usbCommands.getProperty, uhk.devicePropertyIds.configSizes]);
|
const sendData = new Buffer([uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.configSizes]);
|
||||||
device.write(uhk.getTransferData(sendData));
|
device.write(uhk.getTransferData(sendData));
|
||||||
device.readSync()
|
device.readSync()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ let offset = 0;
|
|||||||
let configBuffer = new Buffer(0);
|
let configBuffer = new Buffer(0);
|
||||||
let chunkSizeToRead;
|
let chunkSizeToRead;
|
||||||
|
|
||||||
const payload = new Buffer([uhk.usbCommands.getProperty, uhk.devicePropertyIds.configSizes]);
|
const payload = new Buffer([uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.configSizes]);
|
||||||
device.write(uhk.getTransferData(payload));
|
device.write(uhk.getTransferData(payload));
|
||||||
let buffer = Buffer.from(device.readSync());
|
let buffer = Buffer.from(device.readSync());
|
||||||
const hardwareConfigMaxSize = buffer[1] + (buffer[2]<<8);
|
const hardwareConfigMaxSize = buffer[1] + (buffer[2]<<8);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ exports = module.exports = moduleExports = {
|
|||||||
getTransferData,
|
getTransferData,
|
||||||
checkModuleSlot,
|
checkModuleSlot,
|
||||||
usbCommands: {
|
usbCommands: {
|
||||||
getProperty : 0x00,
|
getDeviceProperty : 0x00,
|
||||||
reenumerate : 0x01,
|
reenumerate : 0x01,
|
||||||
jumpToModuleBootloader : 0x02,
|
jumpToModuleBootloader : 0x02,
|
||||||
sendKbootCommandToModule: 0x03,
|
sendKbootCommandToModule: 0x03,
|
||||||
@@ -76,6 +76,7 @@ exports = module.exports = moduleExports = {
|
|||||||
getDebugBuffer : 0x0b,
|
getDebugBuffer : 0x0b,
|
||||||
getAdcValue : 0x0c,
|
getAdcValue : 0x0c,
|
||||||
setLedPwmBrightness : 0x0d,
|
setLedPwmBrightness : 0x0d,
|
||||||
|
getModuleProperty : 0x0e,
|
||||||
},
|
},
|
||||||
enumerationModes: {
|
enumerationModes: {
|
||||||
bootloader: 0,
|
bootloader: 0,
|
||||||
@@ -101,6 +102,9 @@ exports = module.exports = moduleExports = {
|
|||||||
protocolVersions: 1,
|
protocolVersions: 1,
|
||||||
configSizes: 2,
|
configSizes: 2,
|
||||||
},
|
},
|
||||||
|
modulePropertyIds: {
|
||||||
|
protocolVersions: 0,
|
||||||
|
},
|
||||||
configBufferIds,
|
configBufferIds,
|
||||||
eepromOperations,
|
eepromOperations,
|
||||||
eepromTransfer: {
|
eepromTransfer: {
|
||||||
|
|||||||
12
packages/usb/update-loop-getkey.sh
Executable file
12
packages/usb/update-loop-getkey.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
firmwarePath=$1
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
read -n 1 char
|
||||||
|
if [[ $char == "a" ]]; then
|
||||||
|
./update-firmwares-and-configs.js "$firmwarePath" ansi
|
||||||
|
elif [[ $char == "i" ]]; then
|
||||||
|
./update-firmwares-and-configs.js "$firmwarePath" iso
|
||||||
|
fi
|
||||||
|
done
|
||||||
@@ -23,7 +23,7 @@ let offset = 0;
|
|||||||
let configBuffer = fs.readFileSync(configBin);
|
let configBuffer = fs.readFileSync(configBin);
|
||||||
let chunkSizeToRead;
|
let chunkSizeToRead;
|
||||||
|
|
||||||
const payload = new Buffer([uhk.usbCommands.getProperty, uhk.devicePropertyIds.configSizes]);
|
const payload = new Buffer([uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.configSizes]);
|
||||||
|
|
||||||
device.write(uhk.getTransferData(payload));
|
device.write(uhk.getTransferData(payload));
|
||||||
let buffer = Buffer.from(device.readSync());
|
let buffer = Buffer.from(device.readSync());
|
||||||
|
|||||||
1
packages/usb/zadic/install-win-driver-ia32.bat
Normal file
1
packages/usb/zadic/install-win-driver-ia32.bat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
zadic-ia32.exe --vid 0x1d50 --pid 0x6120 --iface 0 --usealldevices --noprompt
|
||||||
1
packages/usb/zadic/install-win-driver-x64.bat
Normal file
1
packages/usb/zadic/install-win-driver-x64.bat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
zadic-x64.exe --vid 0x1d50 --pid 0x6120 --iface 0 --usealldevices --noprompt
|
||||||
BIN
packages/usb/zadic/zadic-ia32.exe
Normal file
BIN
packages/usb/zadic/zadic-ia32.exe
Normal file
Binary file not shown.
BIN
packages/usb/zadic/zadic-x64.exe
Normal file
BIN
packages/usb/zadic/zadic-x64.exe
Normal file
Binary file not shown.
Reference in New Issue
Block a user