diff --git a/shared/src/components/keymap/header/keymap-header.component.html b/shared/src/components/keymap/header/keymap-header.component.html
index e5c712f6..e6d684c0 100644
--- a/shared/src/components/keymap/header/keymap-header.component.html
+++ b/shared/src/components/keymap/header/keymap-header.component.html
@@ -5,14 +5,12 @@
keymap
(, private renderer: Renderer) { }
+ constructor(private store: Store, private renderer: Renderer2) { }
ngOnChanges(changes: SimpleChanges) {
if (changes['keymap']) {
this.setKeymapTitle();
+ this.setName();
+ this.setAbbreviation();
}
if (changes['deletable']) {
this.setTrashTitle();
@@ -64,7 +66,7 @@ export class KeymapHeaderComponent implements OnChanges {
editKeymapName(name: string) {
if (name.length === 0) {
- this.renderer.setElementProperty(this.keymapName.nativeElement, 'value', this.keymap.name);
+ this.setName();
return;
}
@@ -75,12 +77,12 @@ export class KeymapHeaderComponent implements OnChanges {
const regexp = new RegExp(/^[a-zA-Z\d]+$/g);
if (newAbbr.length < 1 || newAbbr.length > 3 || !regexp.test(newAbbr)) {
- this.renderer.setElementProperty(this.keymapAbbr.nativeElement, 'value', this.keymap.abbreviation);
+ this.setAbbreviation();
return;
}
newAbbr = newAbbr.toUpperCase();
- this.store.dispatch(KeymapActions.editKeymapAbbr(this.keymap.abbreviation, newAbbr));
+ this.store.dispatch(KeymapActions.editKeymapAbbr(this.keymap.name, this.keymap.abbreviation, newAbbr));
}
setKeymapTitle(): void {
@@ -96,4 +98,12 @@ export class KeymapHeaderComponent implements OnChanges {
onDownloadIconClick(): void {
this.downloadClick.emit();
}
+
+ private setName(): void {
+ this.renderer.setProperty(this.keymapName.nativeElement, 'value', this.keymap.name);
+ }
+
+ private setAbbreviation() {
+ this.renderer.setProperty(this.keymapAbbr.nativeElement, 'value', this.keymap.abbreviation);
+ }
}
diff --git a/shared/src/components/macro/header/macro-header.component.html b/shared/src/components/macro/header/macro-header.component.html
index 916d26ee..2f89df39 100644
--- a/shared/src/components/macro/header/macro-header.component.html
+++ b/shared/src/components/macro/header/macro-header.component.html
@@ -5,7 +5,6 @@
diff --git a/shared/src/components/macro/header/macro-header.component.ts b/shared/src/components/macro/header/macro-header.component.ts
index 3e038d99..c60f737a 100644
--- a/shared/src/components/macro/header/macro-header.component.ts
+++ b/shared/src/components/macro/header/macro-header.component.ts
@@ -1,5 +1,12 @@
import {
- AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Input, OnChanges, Renderer,
+ AfterViewInit,
+ ChangeDetectionStrategy,
+ Component,
+ ElementRef,
+ Input,
+ OnChanges,
+ Renderer2,
+ SimpleChanges,
ViewChild
} from '@angular/core';
@@ -21,17 +28,20 @@ export class MacroHeaderComponent implements AfterViewInit, OnChanges {
@Input() isNew: boolean;
@ViewChild('macroName') macroName: ElementRef;
- constructor(private store: Store, private renderer: Renderer) { }
+ constructor(private store: Store, private renderer: Renderer2) { }
- ngOnChanges() {
+ ngOnChanges(changes: SimpleChanges) {
if (this.isNew) {
- this.renderer.invokeElementMethod(this.macroName.nativeElement, 'select', []);
+ this.setFocusOnName();
+ }
+ if (changes['macro']) {
+ this.setName();
}
}
ngAfterViewInit() {
if (this.isNew) {
- this.renderer.invokeElementMethod(this.macroName.nativeElement, 'select', []);
+ this.setFocusOnName();
}
}
@@ -45,11 +55,19 @@ export class MacroHeaderComponent implements AfterViewInit, OnChanges {
editMacroName(name: string) {
if (name.length === 0) {
- this.renderer.setElementProperty(this.macroName.nativeElement, 'value', this.macro.name);
+ this.setName();
return;
}
this.store.dispatch(MacroActions.editMacroName(this.macro.id, name));
}
+ private setFocusOnName() {
+ this.macroName.nativeElement.select();
+ }
+
+ private setName(): void {
+ this.renderer.setProperty(this.macroName.nativeElement, 'value', this.macro.name);
+ }
+
}
diff --git a/shared/src/store/actions/keymap.ts b/shared/src/store/actions/keymap.ts
index d1460174..91944a0d 100644
--- a/shared/src/store/actions/keymap.ts
+++ b/shared/src/store/actions/keymap.ts
@@ -69,12 +69,13 @@ export namespace KeymapActions {
};
}
- export function editKeymapAbbr(abbr: string, newAbbr: string): Action {
+ export function editKeymapAbbr(name: string, abbr: string, newAbbr: string): Action {
return {
type: KeymapActions.EDIT_ABBR,
payload: {
- abbr: abbr,
- newAbbr: newAbbr
+ name,
+ abbr,
+ newAbbr
}
};
}
diff --git a/shared/src/store/effects/keymap.ts b/shared/src/store/effects/keymap.ts
index 0c91e38e..03df04ff 100644
--- a/shared/src/store/effects/keymap.ts
+++ b/shared/src/store/effects/keymap.ts
@@ -54,9 +54,14 @@ export class KeymapEffects {
@Effect({ dispatch: false }) editAbbr$: any = this.actions$
.ofType(KeymapActions.EDIT_ABBR)
- .map(action => action.payload.newAbbr)
- .do(newAbbr => {
- this.router.navigate(['/keymap', newAbbr]);
+ .withLatestFrom(this.store)
+ .do(([action, store]) => {
+ for (const keymap of store.userConfiguration.keymaps) {
+ if (keymap.name === action.payload.name && keymap.abbreviation === action.payload.newAbbr) {
+ this.router.navigate(['/keymap', action.payload.newAbbr]);
+ return;
+ }
+ }
});
constructor(private actions$: Actions, private router: Router, private store: Store) { }
diff --git a/shared/src/store/effects/macro.ts b/shared/src/store/effects/macro.ts
index 2a3448fe..5365c416 100644
--- a/shared/src/store/effects/macro.ts
+++ b/shared/src/store/effects/macro.ts
@@ -14,11 +14,11 @@ import { AppState } from '../index';
@Injectable()
export class MacroEffects {
- @Effect({dispatch: false}) remove$: any = this.actions$
+ @Effect({ dispatch: false }) remove$: any = this.actions$
.ofType(MacroActions.REMOVE)
.map(action => this.store.dispatch(KeymapActions.checkMacro(action.payload)))
.withLatestFrom(this.store)
- .map(latest => latest[1].userConfiguration.macros)
+ .map(([action, state]) => state.userConfiguration.macros)
.do(macros => {
if (macros.length === 0) {
this.router.navigate(['/macro']);
@@ -27,14 +27,23 @@ export class MacroEffects {
}
});
- @Effect({dispatch: false}) add$: any = this.actions$
+ @Effect({ dispatch: false }) add$: any = this.actions$
.ofType(MacroActions.ADD)
.withLatestFrom(this.store)
- .map(latest => latest[1].userConfiguration.macros)
+ .map(([action, state]) => state.userConfiguration.macros)
.map(macros => macros[macros.length - 1])
.do(lastMacro => {
this.router.navigate(['/macro', lastMacro.id, 'new']);
});
+ @Effect({ dispatch: false }) duplicate: any = this.actions$
+ .ofType(MacroActions.DUPLICATE)
+ .withLatestFrom(this.store)
+ .map(([action, state]) => state.userConfiguration.macros)
+ .map(macros => macros[macros.length - 1])
+ .do(lastMacro => {
+ this.router.navigate(['/macro', lastMacro.id]);
+ });
+
constructor(private actions$: Actions, private router: Router, private store: Store) {}
}
diff --git a/shared/src/store/reducers/user-configuration.ts b/shared/src/store/reducers/user-configuration.ts
index 4f1c27d2..6a4806ad 100644
--- a/shared/src/store/reducers/user-configuration.ts
+++ b/shared/src/store/reducers/user-configuration.ts
@@ -5,7 +5,7 @@ import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';
-import { Helper as KeyActionHelper, KeyAction } from '../../config-serializer/config-items/key-action';
+import { Helper as KeyActionHelper } from '../../config-serializer/config-items/key-action';
import { Keymap } from '../../config-serializer/config-items/keymap';
import { Macro } from '../../config-serializer/config-items/macro';
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
@@ -26,43 +26,51 @@ export default function (state = initialState, action: Action): UserConfiguratio
}
case KeymapActions.ADD:
- case KeymapActions.DUPLICATE:
- {
- const newKeymap: Keymap = new Keymap(action.payload);
- newKeymap.abbreviation = generateAbbr(state.keymaps, newKeymap.abbreviation);
- newKeymap.name = generateName(state.keymaps, newKeymap.name);
- newKeymap.isDefault = (state.keymaps.length === 0);
+ case KeymapActions.DUPLICATE: {
+ const newKeymap: Keymap = new Keymap(action.payload);
+ newKeymap.abbreviation = generateAbbr(state.keymaps, newKeymap.abbreviation);
+ newKeymap.name = generateName(state.keymaps, newKeymap.name);
+ newKeymap.isDefault = (state.keymaps.length === 0);
- changedUserConfiguration.keymaps = state.keymaps.concat(newKeymap);
- break;
- }
- case KeymapActions.EDIT_NAME:
- {
- const name: string = generateName(state.keymaps, action.payload.name);
+ changedUserConfiguration.keymaps = state.keymaps.concat(newKeymap);
+ break;
+ }
+ case KeymapActions.EDIT_NAME: {
+ const name: string = action.payload.name.toUpperCase();
- changedUserConfiguration.keymaps = state.keymaps.map((keymap: Keymap) => {
- if (keymap.abbreviation === action.payload.abbr) {
- keymap = Object.assign(new Keymap(), keymap);
- keymap.name = name;
- }
- return keymap;
- });
- break;
- }
- case KeymapActions.EDIT_ABBR:
- const abbr: string = generateAbbr(state.keymaps, action.payload.newAbbr);
+ const duplicate = state.keymaps.some((keymap: Keymap) => {
+ return keymap.name === name && keymap.abbreviation !== action.payload.abbr;
+ });
changedUserConfiguration.keymaps = state.keymaps.map((keymap: Keymap) => {
- if (keymap.abbreviation === action.payload.abbr) {
- keymap = Object.assign(new Keymap(), keymap);
+ keymap = Object.assign(new Keymap(), keymap);
+
+ if (!duplicate && keymap.abbreviation === action.payload.abbr) {
+ keymap.name = name;
+ }
+ return keymap;
+ });
+
+ break;
+ }
+ case KeymapActions.EDIT_ABBR: {
+ const abbr: string = action.payload.newAbbr.toUpperCase();
+
+ const duplicate = state.keymaps.some((keymap: Keymap) => {
+ return keymap.name !== action.payload.name && keymap.abbreviation === abbr;
+ });
+
+ changedUserConfiguration.keymaps = state.keymaps.map((keymap: Keymap) => {
+ keymap = Object.assign(new Keymap(), keymap);
+ if (!duplicate && keymap.abbreviation === action.payload.abbr) {
keymap.abbreviation = abbr;
- } else {
- keymap = keymap.renameKeymap(action.payload.abbr, action.payload.newAbbr);
}
return keymap;
});
break;
+ }
+
case KeymapActions.SET_DEFAULT:
changedUserConfiguration.keymaps = state.keymaps.map((keymap: Keymap) => {
if (keymap.abbreviation === action.payload || keymap.isDefault) {
@@ -101,33 +109,32 @@ export default function (state = initialState, action: Action): UserConfiguratio
});
break;
- case KeymapActions.SAVE_KEY:
- {
- const newKeymap: Keymap = Object.assign(new Keymap(), action.payload.keymap);
- newKeymap.layers = newKeymap.layers.slice();
+ case KeymapActions.SAVE_KEY: {
+ const newKeymap: Keymap = Object.assign(new Keymap(), action.payload.keymap);
+ newKeymap.layers = newKeymap.layers.slice();
- const layerIndex: number = action.payload.layer;
- const newLayer: Layer = Object.assign(new Layer(), newKeymap.layers[layerIndex]);
- newKeymap.layers[layerIndex] = newLayer;
+ const layerIndex: number = action.payload.layer;
+ const newLayer: Layer = Object.assign(new Layer(), newKeymap.layers[layerIndex]);
+ newKeymap.layers[layerIndex] = newLayer;
- const moduleIndex: number = action.payload.module;
- const newModule: Module = Object.assign(new Module(), newLayer.modules[moduleIndex]);
- newLayer.modules = newLayer.modules.slice();
- newLayer.modules[moduleIndex] = newModule;
+ const moduleIndex: number = action.payload.module;
+ const newModule: Module = Object.assign(new Module(), newLayer.modules[moduleIndex]);
+ newLayer.modules = newLayer.modules.slice();
+ newLayer.modules[moduleIndex] = newModule;
- const keyIndex: number = action.payload.key;
- newModule.keyActions = newModule.keyActions.slice();
- newModule.keyActions[keyIndex] = KeyActionHelper.createKeyAction(action.payload.keyAction);
+ const keyIndex: number = action.payload.key;
+ newModule.keyActions = newModule.keyActions.slice();
+ newModule.keyActions[keyIndex] = KeyActionHelper.createKeyAction(action.payload.keyAction);
- changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
- if (keymap.abbreviation === newKeymap.abbreviation) {
- keymap = newKeymap;
- }
+ changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
+ if (keymap.abbreviation === newKeymap.abbreviation) {
+ keymap = newKeymap;
+ }
- return keymap;
- });
- break;
- }
+ return keymap;
+ });
+ break;
+ }
case KeymapActions.CHECK_MACRO:
changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
keymap = Object.assign(new Keymap(), keymap);
@@ -135,41 +142,43 @@ export default function (state = initialState, action: Action): UserConfiguratio
return keymap;
});
break;
- case MacroActions.ADD:
- {
- const newMacro = new Macro();
- newMacro.id = generateMacroId(state.macros);
- newMacro.name = generateName(state.macros, 'New macro');
- newMacro.isLooped = false;
- newMacro.isPrivate = true;
- newMacro.macroActions = [];
+ case MacroActions.ADD: {
+ const newMacro = new Macro();
+ newMacro.id = generateMacroId(state.macros);
+ newMacro.name = generateName(state.macros, 'New macro');
+ newMacro.isLooped = false;
+ newMacro.isPrivate = true;
+ newMacro.macroActions = [];
- changedUserConfiguration.macros = state.macros.concat(newMacro);
- break;
- }
- case MacroActions.DUPLICATE:
- {
- const newMacro = new Macro(action.payload);
- newMacro.name = generateName(state.macros, newMacro.name);
- newMacro.id = generateMacroId(state.macros);
+ changedUserConfiguration.macros = state.macros.concat(newMacro);
+ break;
+ }
+ case MacroActions.DUPLICATE: {
+ const newMacro = new Macro(action.payload);
+ newMacro.name = generateName(state.macros, newMacro.name);
+ newMacro.id = generateMacroId(state.macros);
- changedUserConfiguration.macros = state.macros.concat(newMacro);
- break;
- }
- case MacroActions.EDIT_NAME:
- {
- const name: string = generateName(state.macros, action.payload.name);
+ changedUserConfiguration.macros = state.macros.concat(newMacro);
+ break;
+ }
+ case MacroActions.EDIT_NAME: {
+ const name: string = action.payload.name;
- changedUserConfiguration.macros = state.macros.map((macro: Macro) => {
- if (macro.id === action.payload.id) {
- macro.name = name;
- }
+ const duplicate = state.macros.some((macro: Macro) => {
+ return macro.id !== action.payload.id && macro.name === name;
+ });
- return macro;
- });
+ changedUserConfiguration.macros = state.macros.map((macro: Macro) => {
+ macro = Object.assign(new Macro(), macro);
+ if (!duplicate && macro.id === action.payload.id) {
+ macro.name = name;
+ }
- break;
- }
+ return macro;
+ });
+
+ break;
+ }
case MacroActions.REMOVE:
changedUserConfiguration.macros = state.macros.filter((macro: Macro) => macro.id !== action.payload);
break;
@@ -274,7 +283,7 @@ export function getMacro(id: number) {
}
function generateAbbr(keymaps: Keymap[], abbr: string): string {
- const chars: string[] = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
+ const chars: string[] = '23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
let position = 0;
while (keymaps.some((keymap: Keymap) => keymap.abbreviation === abbr)) {
@@ -286,15 +295,15 @@ function generateAbbr(keymaps: Keymap[], abbr: string): string {
}
function generateName(items: { name: string }[], name: string) {
- let suffix = 2;
- const oldName: string = name;
-
- while (items.some(item => item.name === name)) {
- name = oldName + ` (${suffix})`;
- ++suffix;
- }
-
- return name;
+ let suffix = 1;
+ const regexp = / \(\d+\)$/g;
+ const matchName = name.replace(regexp, '');
+ items.forEach(item => {
+ if (item.name.replace(regexp, '') === matchName) {
+ suffix++;
+ }
+ });
+ return `${matchName} (${suffix})`;
}
function generateMacroId(macros: Macro[]) {