fix(user-config): Layer switcher key behaviour on non-base layers (#440)
* refactor(user-config): Optimize imports * feat(user-config): Clone SwitchLayerAction to destination layer * fix(user-config): Fix Keymap SwitchLayerAction normalization * test(user-config): Remove spy callThrough * build: Add uhk-common test runner * build: delete test serialization files * fix(user-config): Add missing "type": "basic" properties to the user-config.json * test(user-config): Add KeyMacroAction tests * fix(user-config): Delete SwitchLayerAction from non destination layer * fix(user-config): Keymap normalize delete SwitchLayerActions from non base layers * ci: turn of uhk-web tests * ci: turn off karma watch mode in uhk-web test
This commit is contained in:
committed by
László Monda
parent
46b97a9b62
commit
7baf9ad009
@@ -25,12 +25,16 @@ addons:
|
|||||||
- libudev-dev
|
- libudev-dev
|
||||||
- build-essential
|
- build-essential
|
||||||
- libusb-1.0-0-dev
|
- libusb-1.0-0-dev
|
||||||
|
chrome: stable
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- nvm install
|
- nvm install
|
||||||
- npm install
|
- npm install
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
- sleep 3 # give xvfb some time to start
|
||||||
- npm run build
|
- npm run build
|
||||||
- npm run lint
|
- npm run lint
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ shallow_clone: true
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: Install-Product node $env:nodejs_version
|
- ps: Install-Product node $env:nodejs_version
|
||||||
|
- choco install chromium
|
||||||
- set CI=true
|
- set CI=true
|
||||||
- set PATH=%APPDATA%\npm;%PATH%
|
- set PATH=%APPDATA%\npm;%PATH%
|
||||||
- node -v
|
- node -v
|
||||||
@@ -27,5 +28,6 @@ install:
|
|||||||
test_script:
|
test_script:
|
||||||
- appveyor-retry npm run build
|
- appveyor-retry npm run build
|
||||||
- npm run lint
|
- npm run lint
|
||||||
|
- set CHROME_BIN="C:\Program Files (x86)\Chromium\Application\chrome.exe"
|
||||||
- npm run test
|
- npm run test
|
||||||
- npm run release
|
- npm run release
|
||||||
|
|||||||
@@ -50,7 +50,10 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "lerna bootstrap",
|
"postinstall": "lerna bootstrap",
|
||||||
"test": "lerna exec --scope test-serializer npm test",
|
"test":"run-p -sn test:test-serializer test:uhk-common test:uhk-web",
|
||||||
|
"test:test-serializer": "lerna exec --scope test-serializer npm test",
|
||||||
|
"test:uhk-common": "lerna exec --scope uhk-common npm test",
|
||||||
|
"test:uhk-web": "lerna exec --scope uhk-web npm test",
|
||||||
"lint": "run-s -scn lint:ts lint:style",
|
"lint": "run-s -scn lint:ts lint:style",
|
||||||
"lint:ts": "run-p -sn lint:ts:electron-main lint:ts:electron-renderer lint:ts:web lint:ts:test-serializer lint:ts:uhk-usb",
|
"lint:ts": "run-p -sn lint:ts:electron-main lint:ts:electron-renderer lint:ts:web lint:ts:test-serializer lint:ts:uhk-usb",
|
||||||
"lint:ts:electron-main": "tslint --type-check --project ./packages/uhk-agent/tsconfig.json",
|
"lint:ts:electron-main": "tslint --type-check --project ./packages/uhk-agent/tsconfig.json",
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,8 +1,7 @@
|
|||||||
import { UhkBuffer } from '../uhk-buffer';
|
import { UhkBuffer } from '../uhk-buffer';
|
||||||
import { Layer } from './layer';
|
import { Layer } from './layer';
|
||||||
import { Macro } from './macro';
|
import { Macro } from './macro';
|
||||||
import { SwitchLayerAction } from './key-action/switch-layer-action';
|
import { KeyActionHelper, SwitchLayerAction } from './key-action';
|
||||||
import { KeyAction } from './key-action/key-action';
|
|
||||||
import { UserConfiguration } from './user-configuration';
|
import { UserConfiguration } from './user-configuration';
|
||||||
|
|
||||||
export class Keymap {
|
export class Keymap {
|
||||||
@@ -97,30 +96,64 @@ export class Keymap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private normalize() {
|
private normalize() {
|
||||||
// Removes all the SwitchLayerActions from any non base layer
|
if (this.layers.length < 1) {
|
||||||
for (let i = 1; i < this.layers.length; ++i) {
|
return;
|
||||||
for (const module of this.layers[i].modules) {
|
|
||||||
module.keyActions = module.keyActions.map(keyAction => {
|
|
||||||
if (keyAction instanceof SwitchLayerAction) {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
return keyAction;
|
|
||||||
});
|
for (let moduleId = 0; moduleId < this.layers[0].modules.length && moduleId < 2; moduleId++) {
|
||||||
|
const baseModule = this.layers[0].modules[moduleId];
|
||||||
|
for (let keyActionId = 0; keyActionId < baseModule.keyActions.length; keyActionId++) {
|
||||||
|
const baseKeyAction = baseModule.keyActions[keyActionId];
|
||||||
|
|
||||||
|
if (baseKeyAction instanceof SwitchLayerAction) {
|
||||||
|
const destinationLayerId = baseKeyAction.layer + 1;
|
||||||
|
if (this.layers.length < destinationLayerId) {
|
||||||
|
// TODO: What should we do???
|
||||||
|
console.error(`${this.name} has not enough layer. Need: ${destinationLayerId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the SwitchLayerActions from the base layer to any none base layer
|
for (let currentLayerId = 1; currentLayerId < this.layers.length; currentLayerId++) {
|
||||||
const baseLayerModules = this.layers[0].modules;
|
const currentLayer = this.layers[currentLayerId];
|
||||||
for (let i = 0; i < baseLayerModules.length; ++i) {
|
if (currentLayer.modules.length < moduleId) {
|
||||||
baseLayerModules[i].keyActions.forEach((keyAction: KeyAction, keyActionIndex: number) => {
|
// TODO: What should we do???
|
||||||
if (keyAction instanceof SwitchLayerAction) {
|
console.error(`${this.name}.layers[${currentLayerId}] has not enough module. Need: ${moduleId}`);
|
||||||
for (let j = 1; j < this.layers.length; ++j) {
|
continue;
|
||||||
this.layers[j].modules[i].keyActions[keyActionIndex] = new SwitchLayerAction(keyAction);
|
|
||||||
}
|
}
|
||||||
}
|
const currentModule = currentLayer.modules[moduleId];
|
||||||
});
|
const currentKeyAction = currentModule.keyActions[keyActionId];
|
||||||
|
|
||||||
|
if (baseKeyAction instanceof SwitchLayerAction) {
|
||||||
|
if (currentLayerId - 1 === baseKeyAction.layer) {
|
||||||
|
if (currentKeyAction instanceof SwitchLayerAction) {
|
||||||
|
if (currentKeyAction.layer === baseKeyAction.layer &&
|
||||||
|
currentKeyAction.isLayerToggleable === baseKeyAction.isLayerToggleable) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line: max-line-length
|
||||||
|
const error = `${this.name}.layers[${currentLayerId}]modules[${moduleId}].keyActions[${keyActionId}]` +
|
||||||
|
` is different switch layer. ${currentKeyAction} will be override with ${baseKeyAction}`;
|
||||||
|
console.warn(error);
|
||||||
|
} else {
|
||||||
|
// tslint:disable-next-line: max-line-length
|
||||||
|
const error = `${this.name}.layers[${currentLayerId}]modules[${moduleId}].keyActions[${keyActionId}]` +
|
||||||
|
` is not switch layer. ${currentKeyAction} will be override with ${baseKeyAction}`;
|
||||||
|
console.warn(error);
|
||||||
|
}
|
||||||
|
currentModule.keyActions[keyActionId] = KeyActionHelper.createKeyAction(baseKeyAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (currentKeyAction instanceof SwitchLayerAction) {
|
||||||
|
// tslint:disable-next-line: max-line-length
|
||||||
|
const error = `${this.name}.layers[${currentLayerId}]modules[${moduleId}].keyActions[${keyActionId}]` +
|
||||||
|
` is switch layer action, but the base key action is not switch layer action, so will delete`;
|
||||||
|
console.warn(error);
|
||||||
|
currentModule.keyActions[keyActionId] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { KeyMacroAction } from './key-macro-action';
|
||||||
|
import { binaryDefaultHelper, jsonDefaultHelper } from '../../../../test/serializer-test-helper';
|
||||||
|
import { MacroSubAction } from './macro-action';
|
||||||
|
import { KeystrokeType } from '../key-action';
|
||||||
|
|
||||||
|
describe('key-macro-action', () => {
|
||||||
|
it('should be instantiate', () => {
|
||||||
|
const action = new KeyMacroAction();
|
||||||
|
expect(action).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('full serialization', () => {
|
||||||
|
it('should json match', () => {
|
||||||
|
const action = new KeyMacroAction();
|
||||||
|
action.action = MacroSubAction.hold;
|
||||||
|
action.type = KeystrokeType.basic;
|
||||||
|
action.scancode = 100;
|
||||||
|
jsonDefaultHelper(action);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should binary match', () => {
|
||||||
|
const action = new KeyMacroAction();
|
||||||
|
action.action = MacroSubAction.hold;
|
||||||
|
action.type = KeystrokeType.basic;
|
||||||
|
action.scancode = 100;
|
||||||
|
binaryDefaultHelper(action);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
import { UserConfiguration } from '../user-configuration';
|
||||||
|
|
||||||
|
describe('keymap', () => {
|
||||||
|
it('should normalize SwitchLayerAction if non base layer action is not SwitchLayerAction', () => {
|
||||||
|
const inputJsonConfig = {
|
||||||
|
dataModelVersion: 1,
|
||||||
|
moduleConfigurations: [],
|
||||||
|
macros: [],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 44
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const expectedJsonConfig = {
|
||||||
|
dataModelVersion: 1,
|
||||||
|
moduleConfigurations: [],
|
||||||
|
macros: [],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
spyOn(console, 'warn');
|
||||||
|
const inputUserConfig = new UserConfiguration().fromJsonObject(inputJsonConfig);
|
||||||
|
|
||||||
|
expect(inputUserConfig.toJsonObject()).toEqual(expectedJsonConfig);
|
||||||
|
// tslint:disable-next-line: max-line-length
|
||||||
|
expect(console.warn).toHaveBeenCalledWith('QWERTY.layers[1]modules[0].keyActions[0] is not switch layer. <KeystrokeAction type="basic" scancode="44"> will be override with <SwitchLayerAction layer="0" toggle="false">');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should normalize SwitchLayerAction if non base layer action is other SwitchLayerAction', () => {
|
||||||
|
const inputJsonConfig = {
|
||||||
|
dataModelVersion: 1,
|
||||||
|
moduleConfigurations: [],
|
||||||
|
macros: [],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'fn',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const expectedJsonConfig = {
|
||||||
|
dataModelVersion: 1,
|
||||||
|
moduleConfigurations: [],
|
||||||
|
macros: [],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
spyOn(console, 'warn');
|
||||||
|
const inputUserConfig = new UserConfiguration().fromJsonObject(inputJsonConfig);
|
||||||
|
|
||||||
|
expect(inputUserConfig.toJsonObject()).toEqual(expectedJsonConfig);
|
||||||
|
// tslint:disable-next-line: max-line-length
|
||||||
|
expect(console.warn).toHaveBeenCalledWith('QWERTY.layers[1]modules[0].keyActions[0] is different switch layer. <SwitchLayerAction layer="1" toggle="false"> will be override with <SwitchLayerAction layer="0" toggle="false">');
|
||||||
|
});
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
|||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
"build": "ng build --prod --aot --base-href=\"\"",
|
"build": "ng build --prod --aot --base-href=\"\"",
|
||||||
"test": "ng test",
|
"test": "ng test --watch false",
|
||||||
"lint": "ng lint",
|
"lint": "ng lint",
|
||||||
"e2e": "ng e2e",
|
"e2e": "ng e2e",
|
||||||
"build:renderer": "webpack --config webpack.config.js",
|
"build:renderer": "webpack --config webpack.config.js",
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
"karma-jasmine": "1.1.0",
|
"karma-jasmine": "1.1.0",
|
||||||
"karma-jasmine-html-reporter": "0.2.2",
|
"karma-jasmine-html-reporter": "0.2.2",
|
||||||
"less-loader": "4.0.5",
|
"less-loader": "4.0.5",
|
||||||
|
"lodash": "4.17.4",
|
||||||
"ng2-dragula": "1.5.0",
|
"ng2-dragula": "1.5.0",
|
||||||
"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",
|
||||||
|
|||||||
@@ -7074,7 +7074,8 @@
|
|||||||
"macroActionType": "key",
|
"macroActionType": "key",
|
||||||
"action": "press",
|
"action": "press",
|
||||||
"scancode": 15,
|
"scancode": 15,
|
||||||
"modifierMask": 1
|
"modifierMask": 1,
|
||||||
|
"type": "basic"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"macroActionType": "text",
|
"macroActionType": "text",
|
||||||
@@ -7083,7 +7084,8 @@
|
|||||||
{
|
{
|
||||||
"macroActionType": "key",
|
"macroActionType": "key",
|
||||||
"action": "press",
|
"action": "press",
|
||||||
"scancode": 40
|
"scancode": 40,
|
||||||
|
"type": "basic"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,396 @@
|
|||||||
|
import { reducer, initialState } from './user-configuration';
|
||||||
|
import { KeystrokeAction, KeystrokeType, SwitchLayerAction, UserConfiguration, LayerName, Keymap } from 'uhk-common';
|
||||||
|
|
||||||
|
import { getDefaultUserConfig } from '../../../../test/user-config-helper';
|
||||||
|
import { KeymapActions } from '../actions';
|
||||||
|
|
||||||
|
describe('user-configuration reducer', () => {
|
||||||
|
it('should be initiate with default state', () => {
|
||||||
|
const result = reducer(undefined, {} as any);
|
||||||
|
expect(result).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('SAVE_KEY', () => {
|
||||||
|
it('should process KeyStrokeAction', () => {
|
||||||
|
const defaultUserConfig = new UserConfiguration().fromJsonObject(getDefaultUserConfig());
|
||||||
|
const state = new UserConfiguration().fromJsonObject(getDefaultUserConfig());
|
||||||
|
const keystrokeAction = new KeystrokeAction({_scancode: 100, type: KeystrokeType.basic} as any);
|
||||||
|
const saveKeyAction: KeymapActions.SaveKeyAction = {
|
||||||
|
type: KeymapActions.SAVE_KEY,
|
||||||
|
payload: {
|
||||||
|
keymap: new Keymap(defaultUserConfig.keymaps[0]),
|
||||||
|
layer: 0,
|
||||||
|
module: 0,
|
||||||
|
key: 0,
|
||||||
|
keyAction: keystrokeAction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const result = reducer(state, saveKeyAction);
|
||||||
|
const expectedKeyAction = <KeystrokeAction>result.keymaps[0].layers[0].modules[0].keyActions[0];
|
||||||
|
expect(expectedKeyAction).toEqual(keystrokeAction);
|
||||||
|
expect(result).not.toBe(defaultUserConfig);
|
||||||
|
// check key actions not changed on other layers
|
||||||
|
for (let i = 1; i < result.keymaps[0].layers.length; i++) {
|
||||||
|
const keyAction = result.keymaps[0].layers[i].modules[0].keyActions[0];
|
||||||
|
const defaultKeyAction = defaultUserConfig.keymaps[0].layers[i].modules[0].keyActions[0];
|
||||||
|
|
||||||
|
expect(keyAction).toEqual(defaultKeyAction);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should copy the SwitchLayerAction to the destination layer', () => {
|
||||||
|
const defaultUserConfig = new UserConfiguration().fromJsonObject(getDefaultUserConfig());
|
||||||
|
const state = new UserConfiguration().fromJsonObject(getDefaultUserConfig());
|
||||||
|
const destinationLayerId = LayerName.mod;
|
||||||
|
const switchLayerAction = new SwitchLayerAction({isLayerToggleable: false, layer: destinationLayerId} as any);
|
||||||
|
const saveKeyAction: KeymapActions.SaveKeyAction = {
|
||||||
|
type: KeymapActions.SAVE_KEY,
|
||||||
|
payload: {
|
||||||
|
keymap: new Keymap(defaultUserConfig.keymaps[0]),
|
||||||
|
layer: 0,
|
||||||
|
module: 0,
|
||||||
|
key: 0,
|
||||||
|
keyAction: switchLayerAction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const result = reducer(state, saveKeyAction);
|
||||||
|
expect(result).not.toBe(defaultUserConfig);
|
||||||
|
expect(result.toJsonObject()).toEqual({
|
||||||
|
dataModelVersion: 4,
|
||||||
|
moduleConfigurations: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
initialPointerSpeed: 1,
|
||||||
|
pointerAcceleration: 5,
|
||||||
|
maxPointerSpeed: 200
|
||||||
|
}
|
||||||
|
],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 37
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'keyActionType': 'switchLayer',
|
||||||
|
'layer': 'mod',
|
||||||
|
'toggle': false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 30
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
pointerRole: 'scroll',
|
||||||
|
keyActions: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'none',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'keyActionType': 'switchLayer',
|
||||||
|
'layer': 'mod',
|
||||||
|
'toggle': false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'none',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 41
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 58
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'scroll',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
keyActionType: 'switchKeymap',
|
||||||
|
keymapAbbreviation: 'DVO'
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
macros: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should copy the SwitchLayerAction to the destination layer and clear the modified', () => {
|
||||||
|
const defaultUserConfig = new UserConfiguration().fromJsonObject(getDefaultUserConfig());
|
||||||
|
const state = new UserConfiguration().fromJsonObject(getDefaultUserConfig());
|
||||||
|
const destinationLayerId = LayerName.fn;
|
||||||
|
const switchLayerAction = new SwitchLayerAction({isLayerToggleable: false, layer: destinationLayerId} as any);
|
||||||
|
const saveKeyAction: KeymapActions.SaveKeyAction = {
|
||||||
|
type: KeymapActions.SAVE_KEY,
|
||||||
|
payload: {
|
||||||
|
keymap: new Keymap(defaultUserConfig.keymaps[0]),
|
||||||
|
layer: 0,
|
||||||
|
module: 0,
|
||||||
|
key: 2,
|
||||||
|
keyAction: switchLayerAction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const result = reducer(state, saveKeyAction);
|
||||||
|
expect(result).not.toBe(defaultUserConfig);
|
||||||
|
expect(result.toJsonObject()).toEqual({
|
||||||
|
dataModelVersion: 4,
|
||||||
|
moduleConfigurations: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
initialPointerSpeed: 1,
|
||||||
|
pointerAcceleration: 5,
|
||||||
|
maxPointerSpeed: 200
|
||||||
|
}
|
||||||
|
],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 37
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'keyActionType': 'switchLayer',
|
||||||
|
'layer': 'fn',
|
||||||
|
'toggle': false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 30
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
pointerRole: 'scroll',
|
||||||
|
keyActions: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'none',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 65
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'none',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 41
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 58
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'fn',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'scroll',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
keyActionType: 'switchKeymap',
|
||||||
|
keymapAbbreviation: 'DVO'
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
macros: []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,7 +4,7 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
import 'rxjs/add/observable/of';
|
import 'rxjs/add/observable/of';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
import { Keymap, KeyActionHelper, Layer, Macro, Module, UserConfiguration } from 'uhk-common';
|
import { KeyAction, Keymap, KeyActionHelper, Layer, Macro, Module, SwitchLayerAction, UserConfiguration } from 'uhk-common';
|
||||||
import { KeymapActions, MacroActions } from '../actions';
|
import { KeymapActions, MacroActions } from '../actions';
|
||||||
import { AppState } from '../index';
|
import { AppState } from '../index';
|
||||||
import { ActionTypes } from '../actions/user-config';
|
import { ActionTypes } from '../actions/user-config';
|
||||||
@@ -107,21 +107,31 @@ export function reducer(state = initialState, action: Action & { payload?: any }
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KeymapActions.SAVE_KEY: {
|
case KeymapActions.SAVE_KEY: {
|
||||||
|
const keyIndex: number = action.payload.key;
|
||||||
|
const layerIndex: number = action.payload.layer;
|
||||||
|
const moduleIndex: number = action.payload.module;
|
||||||
|
const newKeyAction = KeyActionHelper.createKeyAction(action.payload.keyAction);
|
||||||
const newKeymap: Keymap = Object.assign(new Keymap(), action.payload.keymap);
|
const newKeymap: Keymap = Object.assign(new Keymap(), action.payload.keymap);
|
||||||
newKeymap.layers = newKeymap.layers.slice();
|
newKeymap.layers = newKeymap.layers.slice();
|
||||||
|
|
||||||
const layerIndex: number = action.payload.layer;
|
newKeymap.layers = newKeymap.layers.map((layer, index) => {
|
||||||
const newLayer: Layer = Object.assign(new Layer(), newKeymap.layers[layerIndex]);
|
const newLayer = Object.assign(new Layer(), layer);
|
||||||
newKeymap.layers[layerIndex] = newLayer;
|
|
||||||
|
|
||||||
const moduleIndex: number = action.payload.module;
|
if (index === layerIndex) {
|
||||||
const newModule: Module = Object.assign(new Module(), newLayer.modules[moduleIndex]);
|
setKeyActionToLayer(newLayer, moduleIndex, keyIndex, newKeyAction);
|
||||||
newLayer.modules = newLayer.modules.slice();
|
}
|
||||||
newLayer.modules[moduleIndex] = newModule;
|
// If the key action is a SwitchLayerAction then set the same SwitchLayerAction
|
||||||
|
// on the target layer
|
||||||
const keyIndex: number = action.payload.key;
|
else if (newKeyAction instanceof SwitchLayerAction) {
|
||||||
newModule.keyActions = newModule.keyActions.slice();
|
if (index - 1 === newKeyAction.layer) {
|
||||||
newModule.keyActions[keyIndex] = KeyActionHelper.createKeyAction(action.payload.keyAction);
|
const clonedAction = KeyActionHelper.createKeyAction(action.payload.keyAction);
|
||||||
|
setKeyActionToLayer(newLayer, moduleIndex, keyIndex, clonedAction);
|
||||||
|
}else {
|
||||||
|
setKeyActionToLayer(newLayer, moduleIndex, keyIndex, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newLayer;
|
||||||
|
});
|
||||||
|
|
||||||
changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
|
changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
|
||||||
if (keymap.abbreviation === newKeymap.abbreviation) {
|
if (keymap.abbreviation === newKeymap.abbreviation) {
|
||||||
@@ -357,3 +367,12 @@ function checkExistence(layers: Layer[], property: string, value: any): Layer[]
|
|||||||
|
|
||||||
return newLayers;
|
return newLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setKeyActionToLayer(newLayer: Layer, moduleIndex: number, keyIndex: number, newKeyAction: KeyAction): void {
|
||||||
|
const newModule: Module = Object.assign(new Module(), newLayer.modules[moduleIndex]);
|
||||||
|
newLayer.modules = newLayer.modules.slice();
|
||||||
|
newLayer.modules[moduleIndex] = newModule;
|
||||||
|
|
||||||
|
newModule.keyActions = newModule.keyActions.slice();
|
||||||
|
newModule.keyActions[keyIndex] = newKeyAction;
|
||||||
|
}
|
||||||
|
|||||||
164
packages/uhk-web/test/user-config-helper.ts
Normal file
164
packages/uhk-web/test/user-config-helper.ts
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
|
const defaultUserConfig = {
|
||||||
|
dataModelVersion: 4,
|
||||||
|
moduleConfigurations: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
initialPointerSpeed: 1,
|
||||||
|
pointerAcceleration: 5,
|
||||||
|
maxPointerSpeed: 200
|
||||||
|
}
|
||||||
|
],
|
||||||
|
keymaps: [
|
||||||
|
{
|
||||||
|
isDefault: true,
|
||||||
|
abbreviation: 'QWR',
|
||||||
|
name: 'QWERTY',
|
||||||
|
description: '',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 37
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'keyActionType': 'switchLayer',
|
||||||
|
'layer': 'mod',
|
||||||
|
'toggle': false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 30
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
pointerRole: 'scroll',
|
||||||
|
keyActions: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'none',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'switchLayer',
|
||||||
|
layer: 'mod',
|
||||||
|
toggle: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'none',
|
||||||
|
keyActions: [
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 41
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keyActionType: 'keystroke',
|
||||||
|
type: 'basic',
|
||||||
|
scancode: 58
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'scroll',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
keyActionType: 'switchKeymap',
|
||||||
|
keymapAbbreviation: 'DVO'
|
||||||
|
},
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointerRole: 'move',
|
||||||
|
keyActions: [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
macros: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getDefaultUserConfig() {
|
||||||
|
return cloneDeep(defaultUserConfig);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user