Add the whole user configuration to the AppState
Closes #252 Fixes #219
This commit is contained in:
committed by
József Farkas
parent
e41a62be13
commit
f1f8a8d64e
@@ -68,7 +68,7 @@ import { MapperService } from './shared/services/mapper.service';
|
|||||||
import { UhkDeviceService } from './services/uhk-device.service';
|
import { UhkDeviceService } from './services/uhk-device.service';
|
||||||
|
|
||||||
import { KeymapEffects, MacroEffects } from './shared/store/effects';
|
import { KeymapEffects, MacroEffects } from './shared/store/effects';
|
||||||
import { keymapReducer, macroReducer, presetReducer } from './shared/store/reducers';
|
import { userConfigurationReducer, presetReducer } from './shared/store/reducers';
|
||||||
import { DataStorage } from './shared/store/storage';
|
import { DataStorage } from './shared/store/storage';
|
||||||
|
|
||||||
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
||||||
@@ -81,8 +81,7 @@ const storageService: DataStorage = storageInjector.get(DataStorage);
|
|||||||
|
|
||||||
// All reducers that are used in application
|
// All reducers that are used in application
|
||||||
const storeConfig = {
|
const storeConfig = {
|
||||||
keymaps: storageService.saveState(keymapReducer),
|
userConfiguration: storageService.saveState(userConfigurationReducer),
|
||||||
macros: storageService.saveState(macroReducer),
|
|
||||||
presetKeymaps: presetReducer
|
presetKeymaps: presetReducer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import 'rxjs/add/operator/switchMap';
|
|||||||
|
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { Keymap } from './../../../config-serializer/config-items/Keymap';
|
||||||
import { AppState } from '../../../store/index';
|
import { AppState } from '../../../store/index';
|
||||||
import { getKeymapEntities } from '../../../store/reducers';
|
import { getKeymaps } from '../../../store/reducers/user-configuration';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class KeymapEditGuard implements CanActivate {
|
export class KeymapEditGuard implements CanActivate {
|
||||||
@@ -20,8 +21,8 @@ export class KeymapEditGuard implements CanActivate {
|
|||||||
|
|
||||||
canActivate(): Observable<boolean> {
|
canActivate(): Observable<boolean> {
|
||||||
return this.store
|
return this.store
|
||||||
.let(getKeymapEntities())
|
.let(getKeymaps())
|
||||||
.do(keymaps => {
|
.do((keymaps: Keymap[]) => {
|
||||||
const defaultKeymap = keymaps.find(keymap => keymap.isDefault);
|
const defaultKeymap = keymaps.find(keymap => keymap.isDefault);
|
||||||
this.router.navigate(['/keymap', defaultKeymap.abbreviation]);
|
this.router.navigate(['/keymap', defaultKeymap.abbreviation]);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
|
|
||||||
import { Keymap } from '../../../config-serializer/config-items/Keymap';
|
import { Keymap } from '../../../config-serializer/config-items/Keymap';
|
||||||
import { AppState } from '../../../store';
|
import { AppState } from '../../../store';
|
||||||
import { getKeymap, getKeymapEntities } from '../../../store/reducers/keymap';
|
import { getKeymap, getKeymaps } from '../../../store/reducers/user-configuration';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'keymap-edit',
|
selector: 'keymap-edit',
|
||||||
@@ -37,7 +37,7 @@ export class KeymapEditComponent {
|
|||||||
.publishReplay(1)
|
.publishReplay(1)
|
||||||
.refCount();
|
.refCount();
|
||||||
|
|
||||||
this.deletable$ = store.let(getKeymapEntities())
|
this.deletable$ = store.let(getKeymaps())
|
||||||
.map((keymaps: Keymap[]) => keymaps.length > 1);
|
.map((keymaps: Keymap[]) => keymaps.length > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { MacroAction } from '../../../config-serializer/config-items/macro-actio
|
|||||||
|
|
||||||
import { MacroActions } from '../../../store/actions';
|
import { MacroActions } from '../../../store/actions';
|
||||||
import { AppState } from '../../../store/index';
|
import { AppState } from '../../../store/index';
|
||||||
import { getMacro } from '../../../store/reducers/macro';
|
import { getMacro } from '../../../store/reducers/user-configuration';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'macro-edit',
|
selector: 'macro-edit',
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import 'rxjs/add/operator/map';
|
|||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
import { AppState } from '../../../store/index';
|
import { AppState } from '../../../store/index';
|
||||||
import { getMacroEntities } from '../../../store/reducers';
|
import { getMacros } from '../../../store/reducers/user-configuration';
|
||||||
|
import { Macro } from './../../../config-serializer/config-items/Macro';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MacroNotFoundGuard implements CanActivate {
|
export class MacroNotFoundGuard implements CanActivate {
|
||||||
@@ -18,8 +19,8 @@ export class MacroNotFoundGuard implements CanActivate {
|
|||||||
|
|
||||||
canActivate(): Observable<boolean> {
|
canActivate(): Observable<boolean> {
|
||||||
return this.store
|
return this.store
|
||||||
.let(getMacroEntities())
|
.let(getMacros())
|
||||||
.map(macros => {
|
.map((macros: Macro[]) => {
|
||||||
const hasMacros = macros.length > 0;
|
const hasMacros = macros.length > 0;
|
||||||
if (hasMacros) {
|
if (hasMacros) {
|
||||||
this.router.navigate(['/macro', macros[0].id]);
|
this.router.navigate(['/macro', macros[0].id]);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { Keymap } from '../../config-serializer/config-items/Keymap';
|
|||||||
import { Tab } from './tab/tab';
|
import { Tab } from './tab/tab';
|
||||||
|
|
||||||
import { AppState } from '../../store';
|
import { AppState } from '../../store';
|
||||||
import { getKeymapEntities } from '../../store/reducers';
|
import { getKeymaps } from '../../store/reducers/user-configuration';
|
||||||
|
|
||||||
enum TabName {
|
enum TabName {
|
||||||
Keypress,
|
Keypress,
|
||||||
@@ -90,7 +90,7 @@ export class PopoverComponent implements OnChanges {
|
|||||||
|
|
||||||
constructor(private store: Store<AppState>) {
|
constructor(private store: Store<AppState>) {
|
||||||
this.animationState = 'closed';
|
this.animationState = 'closed';
|
||||||
this.keymaps$ = store.let(getKeymapEntities())
|
this.keymaps$ = store.let(getKeymaps())
|
||||||
.map((keymaps: Keymap[]) =>
|
.map((keymaps: Keymap[]) =>
|
||||||
keymaps.filter((keymap: Keymap) => this.currentKeymap.abbreviation !== keymap.abbreviation)
|
keymaps.filter((keymap: Keymap) => this.currentKeymap.abbreviation !== keymap.abbreviation)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { Macro } from '../../../../config-serializer/config-items/Macro';
|
|||||||
import { Tab } from '../tab';
|
import { Tab } from '../tab';
|
||||||
|
|
||||||
import { AppState } from '../../../../store/index';
|
import { AppState } from '../../../../store/index';
|
||||||
import { getMacroEntities } from '../../../../store/reducers/macro';
|
import { getMacros } from '../../../../store/reducers/user-configuration';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'macro-tab',
|
selector: 'macro-tab',
|
||||||
@@ -29,7 +29,7 @@ export class MacroTabComponent extends Tab implements OnInit, OnChanges, OnDestr
|
|||||||
|
|
||||||
constructor(private store: Store<AppState>) {
|
constructor(private store: Store<AppState>) {
|
||||||
super();
|
super();
|
||||||
this.subscription = store.let(getMacroEntities())
|
this.subscription = store.let(getMacros())
|
||||||
.subscribe((macros: Macro[]) => this.macros = macros);
|
.subscribe((macros: Macro[]) => this.macros = macros);
|
||||||
this.macroOptions = [];
|
this.macroOptions = [];
|
||||||
this.selectedMacroIndex = 0;
|
this.selectedMacroIndex = 0;
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ import { Component, Renderer, animate, state, style, transition, trigger } from
|
|||||||
|
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
import 'rxjs/add/operator/do';
|
import 'rxjs/add/operator/do';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import 'rxjs/add/operator/let';
|
||||||
|
|
||||||
import { Keymap } from '../../config-serializer/config-items/Keymap';
|
import { Keymap } from '../../config-serializer/config-items/Keymap';
|
||||||
import { Macro } from '../../config-serializer/config-items/Macro';
|
import { Macro } from '../../config-serializer/config-items/Macro';
|
||||||
|
|
||||||
import { AppState } from '../../store';
|
import { AppState } from '../../store';
|
||||||
import { MacroActions } from '../../store/actions';
|
import { MacroActions } from '../../store/actions';
|
||||||
import { getKeymapEntities, getMacroEntities } from '../../store/reducers';
|
import { getKeymaps, getMacros } from '../../store/reducers/user-configuration';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
animations: [
|
animations: [
|
||||||
@@ -41,13 +42,13 @@ export class SideMenuComponent {
|
|||||||
addon: 'active'
|
addon: 'active'
|
||||||
};
|
};
|
||||||
|
|
||||||
this.keymaps$ = store.let(getKeymapEntities())
|
this.keymaps$ = store.let(getKeymaps())
|
||||||
.map(keymaps => keymaps.slice()) // Creating a new array reference, because the sort is working in place
|
.map(keymaps => keymaps.slice()) // Creating a new array reference, because the sort is working in place
|
||||||
.do((keymaps: Keymap[]) => {
|
.do((keymaps: Keymap[]) => {
|
||||||
keymaps.sort((first: Keymap, second: Keymap) => first.name.localeCompare(second.name));
|
keymaps.sort((first: Keymap, second: Keymap) => first.name.localeCompare(second.name));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.macros$ = store.let(getMacroEntities())
|
this.macros$ = store.let(getMacros())
|
||||||
.map(macros => macros.slice()) // Creating a new array reference, because the sort is working in place
|
.map(macros => macros.slice()) // Creating a new array reference, because the sort is working in place
|
||||||
.do((macros: Macro[]) => {
|
.do((macros: Macro[]) => {
|
||||||
macros.sort((first: Macro, second: Macro) => first.name.localeCompare(second.name));
|
macros.sort((first: Macro, second: Macro) => first.name.localeCompare(second.name));
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { CaptureService } from '../../../../services/capture.service';
|
|||||||
import { MapperService } from '../../../../services/mapper.service';
|
import { MapperService } from '../../../../services/mapper.service';
|
||||||
|
|
||||||
import { AppState } from '../../../../store/index';
|
import { AppState } from '../../../../store/index';
|
||||||
import { getMacroEntities } from '../../../../store/reducers/macro';
|
import { getMacros } from '../../../../store/reducers/user-configuration';
|
||||||
|
|
||||||
enum LabelTypes {
|
enum LabelTypes {
|
||||||
KeystrokeKey,
|
KeystrokeKey,
|
||||||
@@ -146,7 +146,7 @@ export class SvgKeyboardKeyComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
private captureService: CaptureService,
|
private captureService: CaptureService,
|
||||||
private renderer: Renderer
|
private renderer: Renderer
|
||||||
) {
|
) {
|
||||||
this.subscription = store.let(getMacroEntities())
|
this.subscription = store.let(getMacros())
|
||||||
.subscribe((macros: Macro[]) => this.macros = macros);
|
.subscribe((macros: Macro[]) => this.macros = macros);
|
||||||
|
|
||||||
this.reset();
|
this.reset();
|
||||||
|
|||||||
@@ -283,8 +283,8 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
|
|||||||
} else if (keyAction instanceof PlayMacroAction) {
|
} else if (keyAction instanceof PlayMacroAction) {
|
||||||
const playMacroAction: PlayMacroAction = keyAction;
|
const playMacroAction: PlayMacroAction = keyAction;
|
||||||
return this.store
|
return this.store
|
||||||
.select(appState => appState.macros)
|
.select(appState => appState.userConfiguration.macros)
|
||||||
.map(macroState => macroState.entities.find(macro => {
|
.map(macroState => macroState.find(macro => {
|
||||||
return macro.id === playMacroAction.macroId;
|
return macro.id === playMacroAction.macroId;
|
||||||
}).name)
|
}).name)
|
||||||
.map(macroName => {
|
.map(macroName => {
|
||||||
@@ -303,7 +303,7 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
|
|||||||
} else if (keyAction instanceof SwitchKeymapAction) {
|
} else if (keyAction instanceof SwitchKeymapAction) {
|
||||||
const switchKeymapAction: SwitchKeymapAction = keyAction;
|
const switchKeymapAction: SwitchKeymapAction = keyAction;
|
||||||
return this.store
|
return this.store
|
||||||
.select(appState => appState.keymaps.entities)
|
.select(appState => appState.userConfiguration.keymaps)
|
||||||
.map(keymaps => keymaps.find(keymap => keymap.abbreviation === switchKeymapAction.keymapAbbreviation).name)
|
.map(keymaps => keymaps.find(keymap => keymap.abbreviation === switchKeymapAction.keymapAbbreviation).name)
|
||||||
.map(keymapName => {
|
.map(keymapName => {
|
||||||
const content: NameValuePair[] = [
|
const content: NameValuePair[] = [
|
||||||
|
|||||||
@@ -16,34 +16,23 @@ import { Keymap } from '../../config-serializer/config-items/Keymap';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class KeymapEffects {
|
export class KeymapEffects {
|
||||||
|
|
||||||
@Effect({ dispatch: false }) add$: any = this.actions$
|
@Effect({ dispatch: false }) addOrDuplicate$: any = this.actions$
|
||||||
.ofType(KeymapActions.ADD)
|
.ofType(KeymapActions.ADD, KeymapActions.DUPLICATE)
|
||||||
.withLatestFrom(this.store)
|
.withLatestFrom(this.store)
|
||||||
.do((latest) => {
|
.map(latest => latest[1].userConfiguration.keymaps)
|
||||||
const state: AppState = latest[1];
|
.do(keymaps => {
|
||||||
const entities: Keymap[] = state.keymaps.entities;
|
this.router.navigate(['/keymap', keymaps[keymaps.length - 1].abbreviation]);
|
||||||
this.router.navigate(['/keymap', entities[entities.length - 1].abbreviation]);
|
|
||||||
});
|
|
||||||
|
|
||||||
@Effect({ dispatch: false }) duplicate$: any = this.actions$
|
|
||||||
.ofType(KeymapActions.DUPLICATE)
|
|
||||||
.withLatestFrom(this.store)
|
|
||||||
.do((latest) => {
|
|
||||||
const state: AppState = latest[1];
|
|
||||||
const entities: Keymap[] = state.keymaps.entities;
|
|
||||||
this.router.navigate(['/keymap', entities[entities.length - 1].abbreviation]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@Effect({ dispatch: false }) remove$: any = this.actions$
|
@Effect({ dispatch: false }) remove$: any = this.actions$
|
||||||
.ofType(KeymapActions.REMOVE)
|
.ofType(KeymapActions.REMOVE)
|
||||||
.withLatestFrom(this.store)
|
.withLatestFrom(this.store)
|
||||||
.do((latest) => {
|
.map(latest => latest[1].userConfiguration.keymaps)
|
||||||
const state: AppState = latest[1];
|
.do(keymaps => {
|
||||||
|
if (keymaps.length === 0) {
|
||||||
if (state.keymaps.entities.length === 0) {
|
|
||||||
this.router.navigate(['/keymap/add']);
|
this.router.navigate(['/keymap/add']);
|
||||||
} else {
|
} else {
|
||||||
const favourite: Keymap = state.keymaps.entities.find(keymap => keymap.isDefault);
|
const favourite: Keymap = keymaps.find(keymap => keymap.isDefault);
|
||||||
this.router.navigate(['/keymap', favourite.abbreviation]);
|
this.router.navigate(['/keymap', favourite.abbreviation]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,25 +20,22 @@ export class MacroEffects {
|
|||||||
.ofType(MacroActions.REMOVE)
|
.ofType(MacroActions.REMOVE)
|
||||||
.map(action => this.store.dispatch(KeymapActions.checkMacro(action.payload)))
|
.map(action => this.store.dispatch(KeymapActions.checkMacro(action.payload)))
|
||||||
.withLatestFrom(this.store)
|
.withLatestFrom(this.store)
|
||||||
.do((latest) => {
|
.map(latest => latest[1].userConfiguration.macros)
|
||||||
const state: AppState = latest[1];
|
.do(macros => {
|
||||||
const macro: Macro[] = state.macros.entities;
|
if (macros.length === 0) {
|
||||||
|
|
||||||
if (state.macros.entities.length === 0) {
|
|
||||||
this.router.navigate(['/macro']);
|
this.router.navigate(['/macro']);
|
||||||
} else {
|
} else {
|
||||||
this.router.navigate(['/macro', macro[0].id]);
|
this.router.navigate(['/macro', macros[0].id]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@Effect({dispatch: false}) add$: any = this.actions$
|
@Effect({dispatch: false}) add$: any = this.actions$
|
||||||
.ofType(MacroActions.ADD)
|
.ofType(MacroActions.ADD)
|
||||||
.withLatestFrom(this.store)
|
.withLatestFrom(this.store)
|
||||||
.do((latest) => {
|
.map(latest => latest[1].userConfiguration.macros)
|
||||||
const state: AppState = latest[1];
|
.map(macros => macros[macros.length - 1])
|
||||||
const macro: Macro = state.macros.entities[state.macros.entities.length - 1];
|
.do(lastMacro => {
|
||||||
|
this.router.navigate(['/macro', lastMacro.id, 'new']);
|
||||||
this.router.navigate(['/macro', macro.id, 'new']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions, private router: Router, private store: Store<AppState>) {}
|
constructor(private actions$: Actions, private router: Router, private store: Store<AppState>) {}
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
import { Keymap } from '../config-serializer/config-items/Keymap';
|
import { Keymap } from '../config-serializer/config-items/Keymap';
|
||||||
import { Macro } from '../config-serializer/config-items/Macro';
|
import { UserConfiguration } from '../config-serializer/config-items/UserConfiguration';
|
||||||
|
|
||||||
export interface KeymapState {
|
|
||||||
entities: Keymap[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MacroState {
|
|
||||||
entities: Macro[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// State interface for the application
|
// State interface for the application
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
keymaps: KeymapState;
|
userConfiguration: UserConfiguration;
|
||||||
macros: MacroState;
|
|
||||||
presetKeymaps: Keymap[];
|
presetKeymaps: Keymap[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import keymapReducer, { getKeymapEntities } from './keymap';
|
import userConfigurationReducer, { getUserConfiguration } from './user-configuration';
|
||||||
import macroReducer, { getMacroEntities } from './macro';
|
|
||||||
import presetReducer from './preset';
|
import presetReducer from './preset';
|
||||||
|
|
||||||
export { keymapReducer, macroReducer, presetReducer, getKeymapEntities, getMacroEntities };
|
export { userConfigurationReducer, presetReducer, getUserConfiguration };
|
||||||
|
|||||||
@@ -1,237 +0,0 @@
|
|||||||
import '@ngrx/core/add/operator/select';
|
|
||||||
import { Action } from '@ngrx/store';
|
|
||||||
|
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { Helper as KeyActionHelper, KeyAction } from '../../config-serializer/config-items/key-action';
|
|
||||||
import { Keymap } from '../../config-serializer/config-items/Keymap';
|
|
||||||
import { Layer } from '../../config-serializer/config-items/Layer';
|
|
||||||
import { Module } from '../../config-serializer/config-items/Module';
|
|
||||||
import { KeymapActions } from '../actions';
|
|
||||||
import { AppState, KeymapState } from '../index';
|
|
||||||
|
|
||||||
const initialState: KeymapState = {
|
|
||||||
entities: []
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function (state = initialState, action: Action): KeymapState {
|
|
||||||
let newState: Keymap[];
|
|
||||||
let changedKeymap: Keymap = new Keymap();
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
case KeymapActions.ADD:
|
|
||||||
case KeymapActions.DUPLICATE:
|
|
||||||
{
|
|
||||||
let newKeymap: Keymap = new Keymap(action.payload);
|
|
||||||
|
|
||||||
newKeymap.abbreviation = generateAbbr(state.entities, newKeymap.abbreviation);
|
|
||||||
newKeymap.name = generateName(state.entities, newKeymap.name);
|
|
||||||
newKeymap.isDefault = (state.entities.length === 0);
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: [...state.entities, newKeymap]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/* tslint:disable:no-switch-case-fall-through */
|
|
||||||
// tslint bug: https://github.com/palantir/tslint/issues/1538
|
|
||||||
case KeymapActions.EDIT_NAME:
|
|
||||||
/* tslint:enable:no-switch-case-fall-through */
|
|
||||||
let name: string = generateName(state.entities, action.payload.name);
|
|
||||||
|
|
||||||
newState = state.entities.map((keymap: Keymap) => {
|
|
||||||
if (keymap.abbreviation === action.payload.abbr) {
|
|
||||||
keymap.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keymap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case KeymapActions.EDIT_ABBR:
|
|
||||||
let abbr: string = generateAbbr(state.entities, action.payload.newAbbr);
|
|
||||||
|
|
||||||
newState = state.entities.map((keymap: Keymap) => {
|
|
||||||
if (keymap.abbreviation === action.payload.abbr) {
|
|
||||||
keymap.abbreviation = abbr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keymap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case KeymapActions.SET_DEFAULT:
|
|
||||||
newState = state.entities.map((keymap: Keymap) => {
|
|
||||||
if (keymap.abbreviation === action.payload || keymap.isDefault) {
|
|
||||||
let newKeymap: Keymap = new Keymap();
|
|
||||||
Object.assign(newKeymap, keymap);
|
|
||||||
keymap = newKeymap;
|
|
||||||
keymap.isDefault = keymap.abbreviation === action.payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keymap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case KeymapActions.REMOVE:
|
|
||||||
let isDefault: boolean;
|
|
||||||
|
|
||||||
let filtered: Keymap[] = state.entities.filter((keymap: Keymap) => {
|
|
||||||
if (keymap.abbreviation === action.payload) {
|
|
||||||
isDefault = keymap.isDefault;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If deleted one is default set default keymap to the first on the list of keymaps
|
|
||||||
if (isDefault && filtered.length > 0) {
|
|
||||||
filtered[0].isDefault = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for the deleted keymap in other keymaps
|
|
||||||
newState = filtered.map((keymap: Keymap) => {
|
|
||||||
changedKeymap = new Keymap();
|
|
||||||
Object.assign(changedKeymap, keymap);
|
|
||||||
changedKeymap.layers = checkExistence(changedKeymap.layers, 'keymapAbbreviation', action.payload);
|
|
||||||
|
|
||||||
return changedKeymap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case KeymapActions.SAVE_KEY:
|
|
||||||
{
|
|
||||||
const keymap: Keymap = action.payload.keymap;
|
|
||||||
Object.assign(changedKeymap, keymap);
|
|
||||||
|
|
||||||
const layerIndex: number = action.payload.layer;
|
|
||||||
const layer: Layer = changedKeymap.layers[layerIndex];
|
|
||||||
const changedLayer: Layer = new Layer();
|
|
||||||
Object.assign(changedLayer, layer);
|
|
||||||
changedKeymap.layers = changedKeymap.layers.slice();
|
|
||||||
changedKeymap.layers[layerIndex] = changedLayer;
|
|
||||||
|
|
||||||
const moduleIndex: number = action.payload.module;
|
|
||||||
const module: Module = changedLayer.modules[moduleIndex];
|
|
||||||
const changedModule: Module = new Module();
|
|
||||||
Object.assign(changedModule, module);
|
|
||||||
changedLayer.modules[moduleIndex] = changedModule;
|
|
||||||
|
|
||||||
const keyIndex: number = action.payload.key;
|
|
||||||
changedModule.keyActions[keyIndex] = KeyActionHelper.createKeyAction(action.payload.keyAction);
|
|
||||||
|
|
||||||
newState = state.entities.map((_keymap: Keymap) => {
|
|
||||||
if (_keymap.abbreviation === changedKeymap.abbreviation) {
|
|
||||||
_keymap = changedKeymap;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _keymap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/* tslint:disable:no-switch-case-fall-through */
|
|
||||||
// tslint bug: https://github.com/palantir/tslint/issues/1538
|
|
||||||
case KeymapActions.CHECK_MACRO:
|
|
||||||
/* tslint:enable:no-switch-case-fall-through */
|
|
||||||
newState = state.entities.map((keymap: Keymap) => {
|
|
||||||
changedKeymap = new Keymap();
|
|
||||||
Object.assign(changedKeymap, keymap);
|
|
||||||
changedKeymap.layers = checkExistence(changedKeymap.layers, '_macroId', action.payload);
|
|
||||||
|
|
||||||
return changedKeymap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getKeymapEntities(): (state$: Observable<AppState>) => Observable<Keymap[]> {
|
|
||||||
return (state$: Observable<AppState>) => state$
|
|
||||||
.select(state => state.keymaps.entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getKeymap(abbr: string) {
|
|
||||||
if (abbr === undefined) {
|
|
||||||
return getDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (state$: Observable<AppState>) => state$
|
|
||||||
.select(appState => appState.keymaps.entities)
|
|
||||||
.map((keymaps: Keymap[]) =>
|
|
||||||
keymaps.find((keymap: Keymap) => keymap.abbreviation === abbr)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDefault() {
|
|
||||||
return (state$: Observable<AppState>) => state$
|
|
||||||
.select(appState => appState.keymaps.entities)
|
|
||||||
.map((keymaps: Keymap[]) =>
|
|
||||||
keymaps.find((keymap: Keymap) => keymap.isDefault)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateAbbr(keymaps: Keymap[], abbr: string): string {
|
|
||||||
const chars: string[] = '23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
|
||||||
let position = 0;
|
|
||||||
|
|
||||||
while (keymaps.some((keymap: Keymap) => keymap.abbreviation === abbr)) {
|
|
||||||
abbr = abbr.substring(0, abbr.length - 1) + chars[position];
|
|
||||||
++position;
|
|
||||||
}
|
|
||||||
|
|
||||||
return abbr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateName(keymaps: Keymap[], name: string) {
|
|
||||||
let suffix = 2;
|
|
||||||
const oldName: string = name;
|
|
||||||
|
|
||||||
while (keymaps.some((keymap: Keymap) => keymap.name === name)) {
|
|
||||||
name = oldName + ` (${suffix})`;
|
|
||||||
++suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkExistence(layers: Layer[], property: string, value: any) {
|
|
||||||
let newLayers = layers.map((layer) => {
|
|
||||||
let newLayer = new Layer(layer);
|
|
||||||
|
|
||||||
newLayer.modules = layer.modules.map((module: Module) => {
|
|
||||||
module.keyActions.forEach((action: KeyAction, index: number) => {
|
|
||||||
if (action && action.hasOwnProperty(property) && action[property] === value) {
|
|
||||||
module.keyActions[index] = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return module;
|
|
||||||
});
|
|
||||||
|
|
||||||
return newLayer;
|
|
||||||
});
|
|
||||||
|
|
||||||
return newLayers;
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
import '@ngrx/core/add/operator/select';
|
|
||||||
import { Action } from '@ngrx/store';
|
|
||||||
|
|
||||||
import 'rxjs/add/observable/of';
|
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { Macro } from '../../config-serializer/config-items/Macro';
|
|
||||||
|
|
||||||
import { MacroActions } from '../actions';
|
|
||||||
import { AppState, MacroState } from '../index';
|
|
||||||
|
|
||||||
const initialState: MacroState = {
|
|
||||||
entities: []
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function (state = initialState, action: Action): MacroState {
|
|
||||||
let newMacro: Macro;
|
|
||||||
let newState: Macro[];
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
case MacroActions.ADD:
|
|
||||||
newMacro = new Macro();
|
|
||||||
newMacro.id = generateId(state.entities);
|
|
||||||
newMacro.name = generateName(state.entities, 'New macro');
|
|
||||||
newMacro.isLooped = false;
|
|
||||||
newMacro.isPrivate = true;
|
|
||||||
newMacro.macroActions = [];
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: [...state.entities, newMacro]
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.DUPLICATE:
|
|
||||||
|
|
||||||
newMacro = new Macro(action.payload);
|
|
||||||
newMacro.name = generateName(state.entities, newMacro.name);
|
|
||||||
newMacro.id = generateId(state.entities);
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: [...state.entities, newMacro]
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.EDIT_NAME:
|
|
||||||
let name: string = generateName(state.entities, action.payload.name);
|
|
||||||
|
|
||||||
newState = state.entities.map((macro: Macro) => {
|
|
||||||
if (macro.id === action.payload.id) {
|
|
||||||
macro.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return macro;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.REMOVE:
|
|
||||||
newState = state.entities.filter((macro: Macro) => macro.id !== action.payload);
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.ADD_ACTION:
|
|
||||||
newState = state.entities.map((macro: Macro) => {
|
|
||||||
if (macro.id === action.payload.id) {
|
|
||||||
newMacro = new Macro(macro);
|
|
||||||
newMacro.macroActions.push(action.payload.action);
|
|
||||||
|
|
||||||
return newMacro;
|
|
||||||
}
|
|
||||||
|
|
||||||
return macro;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.SAVE_ACTION:
|
|
||||||
newState = state.entities.map((macro: Macro) => {
|
|
||||||
if (macro.id === action.payload.id) {
|
|
||||||
newMacro = new Macro(macro);
|
|
||||||
newMacro.macroActions[action.payload.index] = action.payload.action;
|
|
||||||
|
|
||||||
return newMacro;
|
|
||||||
}
|
|
||||||
|
|
||||||
return macro;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.DELETE_ACTION:
|
|
||||||
newState = state.entities.map((macro: Macro) => {
|
|
||||||
if (macro.id === action.payload.id) {
|
|
||||||
newMacro = new Macro(macro);
|
|
||||||
newMacro.macroActions.splice(action.payload.index, 1);
|
|
||||||
|
|
||||||
return newMacro;
|
|
||||||
}
|
|
||||||
|
|
||||||
return macro;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
case MacroActions.REORDER_ACTION:
|
|
||||||
newState = state.entities.map((macro: Macro) => {
|
|
||||||
if (macro.id === action.payload.id) {
|
|
||||||
let newIndex: number = action.payload.newIndex;
|
|
||||||
|
|
||||||
// We need to reduce the new index for one when we are moving action down
|
|
||||||
if (newIndex > action.payload.oldIndex) {
|
|
||||||
--newIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
newMacro = new Macro(macro);
|
|
||||||
newMacro.macroActions.splice(
|
|
||||||
newIndex,
|
|
||||||
0,
|
|
||||||
newMacro.macroActions.splice(action.payload.oldIndex, 1)[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
return newMacro;
|
|
||||||
}
|
|
||||||
|
|
||||||
return macro;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
entities: newState
|
|
||||||
};
|
|
||||||
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMacroEntities(): (state$: Observable<AppState>) => Observable<Macro[]> {
|
|
||||||
return (state$: Observable<AppState>) => state$
|
|
||||||
.select(state => state.macros.entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMacro(id: number) {
|
|
||||||
if (isNaN(id)) {
|
|
||||||
return () => Observable.of<Macro>(undefined);
|
|
||||||
} else {
|
|
||||||
return (state$: Observable<AppState>) => state$
|
|
||||||
.select(appState => appState.macros.entities)
|
|
||||||
.map((macros: Macro[]) => macros.find((macro: Macro) => macro.id === id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateName(macros: Macro[], name: string) {
|
|
||||||
let suffix = 2;
|
|
||||||
const oldName: string = name;
|
|
||||||
|
|
||||||
while (macros.some((macro: Macro) => macro.name === name)) {
|
|
||||||
name = oldName + ` (${suffix})`;
|
|
||||||
++suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateId(macros: Macro[]) {
|
|
||||||
let newId = 0;
|
|
||||||
|
|
||||||
macros.forEach((macro: Macro) => {
|
|
||||||
if (macro.id > newId) {
|
|
||||||
newId = macro.id;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ++newId;
|
|
||||||
|
|
||||||
}
|
|
||||||
321
shared/src/store/reducers/user-configuration.ts
Normal file
321
shared/src/store/reducers/user-configuration.ts
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import '@ngrx/core/add/operator/select';
|
||||||
|
import { Action } from '@ngrx/store';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import { Helper as KeyActionHelper, KeyAction } 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/UserConfiguration';
|
||||||
|
import { Layer } from '../../config-serializer/config-items/Layer';
|
||||||
|
import { Module } from '../../config-serializer/config-items/Module';
|
||||||
|
import { KeymapActions, MacroActions } from '../actions';
|
||||||
|
import { AppState } from '../index';
|
||||||
|
|
||||||
|
const initialState: UserConfiguration = new UserConfiguration();
|
||||||
|
|
||||||
|
/* tslint:disable:no-switch-case-fall-through */
|
||||||
|
// tslint bug: https://github.com/palantir/tslint/issues/1538
|
||||||
|
|
||||||
|
export default function (state = initialState, action: Action): UserConfiguration {
|
||||||
|
const changedUserConfiguration: UserConfiguration = Object.assign(new UserConfiguration(), state);
|
||||||
|
|
||||||
|
switch (action.type) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
changedUserConfiguration.keymaps = state.keymaps.concat(newKeymap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KeymapActions.EDIT_NAME:
|
||||||
|
{
|
||||||
|
const name: string = generateName(state.keymaps, action.payload.name);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
changedUserConfiguration.keymaps = state.keymaps.map((keymap: Keymap) => {
|
||||||
|
if (keymap.abbreviation === action.payload.abbr) {
|
||||||
|
keymap = Object.assign(new Keymap(), keymap);
|
||||||
|
keymap.abbreviation = abbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keymap;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case KeymapActions.SET_DEFAULT:
|
||||||
|
changedUserConfiguration.keymaps = state.keymaps.map((keymap: Keymap) => {
|
||||||
|
if (keymap.abbreviation === action.payload || keymap.isDefault) {
|
||||||
|
keymap = Object.assign(new Keymap(), keymap);
|
||||||
|
keymap.isDefault = keymap.abbreviation === action.payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keymap;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case KeymapActions.REMOVE:
|
||||||
|
let isDefault: boolean;
|
||||||
|
|
||||||
|
let filtered: Keymap[] = state.keymaps.filter((keymap: Keymap) => {
|
||||||
|
if (keymap.abbreviation === action.payload) {
|
||||||
|
isDefault = keymap.isDefault;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If deleted one is default set default keymap to the first on the list of keymaps
|
||||||
|
if (isDefault && filtered.length > 0) {
|
||||||
|
filtered[0].isDefault = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the deleted keymap in other keymaps
|
||||||
|
changedUserConfiguration.keymaps = filtered.map(keymap => {
|
||||||
|
keymap = Object.assign(new Keymap(), keymap);
|
||||||
|
keymap.layers = checkExistence(keymap.layers, 'keymapAbbreviation', action.payload);
|
||||||
|
|
||||||
|
return keymap;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
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 moduleIndex: number = action.payload.module;
|
||||||
|
const newModule: Module = Object.assign(new Module(), newLayer.modules[moduleIndex]);
|
||||||
|
newLayer.modules[moduleIndex] = newModule;
|
||||||
|
|
||||||
|
const keyIndex: number = action.payload.key;
|
||||||
|
newModule.keyActions[keyIndex] = KeyActionHelper.createKeyAction(action.payload.keyAction);
|
||||||
|
|
||||||
|
changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
|
||||||
|
if (keymap.abbreviation === newKeymap.abbreviation) {
|
||||||
|
keymap = newKeymap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keymap;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KeymapActions.CHECK_MACRO:
|
||||||
|
changedUserConfiguration.keymaps = state.keymaps.map(keymap => {
|
||||||
|
keymap = Object.assign(new Keymap(), keymap);
|
||||||
|
keymap.layers = checkExistence(keymap.layers, '_macroId', action.payload);
|
||||||
|
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 = [];
|
||||||
|
|
||||||
|
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.map((macro: Macro) => {
|
||||||
|
if (macro.id === action.payload.id) {
|
||||||
|
macro.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return macro;
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MacroActions.REMOVE:
|
||||||
|
changedUserConfiguration.macros = state.macros.filter((macro: Macro) => macro.id !== action.payload);
|
||||||
|
break;
|
||||||
|
case MacroActions.ADD_ACTION:
|
||||||
|
changedUserConfiguration.macros = state.macros.map((macro: Macro) => {
|
||||||
|
if (macro.id === action.payload.id) {
|
||||||
|
macro = new Macro(macro);
|
||||||
|
macro.macroActions.push(action.payload.action);
|
||||||
|
}
|
||||||
|
|
||||||
|
return macro;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case MacroActions.SAVE_ACTION:
|
||||||
|
changedUserConfiguration.macros = state.macros.map((macro: Macro) => {
|
||||||
|
if (macro.id === action.payload.id) {
|
||||||
|
macro = new Macro(macro);
|
||||||
|
macro.macroActions[action.payload.index] = action.payload.action;
|
||||||
|
}
|
||||||
|
|
||||||
|
return macro;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case MacroActions.DELETE_ACTION:
|
||||||
|
changedUserConfiguration.macros = state.macros.map((macro: Macro) => {
|
||||||
|
if (macro.id === action.payload.id) {
|
||||||
|
macro = new Macro(macro);
|
||||||
|
macro.macroActions.splice(action.payload.index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return macro;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case MacroActions.REORDER_ACTION:
|
||||||
|
changedUserConfiguration.macros = state.macros.map((macro: Macro) => {
|
||||||
|
if (macro.id === action.payload.id) {
|
||||||
|
let newIndex: number = action.payload.newIndex;
|
||||||
|
|
||||||
|
// We need to reduce the new index for one when we are moving action down
|
||||||
|
if (newIndex > action.payload.oldIndex) {
|
||||||
|
--newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro = new Macro(macro);
|
||||||
|
macro.macroActions.splice(
|
||||||
|
newIndex,
|
||||||
|
0,
|
||||||
|
macro.macroActions.splice(action.payload.oldIndex, 1)[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return macro;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changedUserConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUserConfiguration(): (state$: Observable<AppState>) => Observable<UserConfiguration> {
|
||||||
|
return (state$: Observable<AppState>) => state$
|
||||||
|
.select(state => state.userConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getKeymaps(): (state$: Observable<AppState>) => Observable<Keymap[]> {
|
||||||
|
return (state$: Observable<AppState>) => state$
|
||||||
|
.select(state => state.userConfiguration.keymaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getKeymap(abbr: string) {
|
||||||
|
if (abbr === undefined) {
|
||||||
|
return getDefaultKeymap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (state$: Observable<AppState>) => getKeymaps()(state$)
|
||||||
|
.map((keymaps: Keymap[]) =>
|
||||||
|
keymaps.find((keymap: Keymap) => keymap.abbreviation === abbr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefaultKeymap() {
|
||||||
|
return (state$: Observable<AppState>) => getKeymaps()(state$)
|
||||||
|
.map((keymaps: Keymap[]) =>
|
||||||
|
keymaps.find((keymap: Keymap) => keymap.isDefault)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMacros(): (state$: Observable<AppState>) => Observable<Macro[]> {
|
||||||
|
return (state$: Observable<AppState>) => state$
|
||||||
|
.select(state => state.userConfiguration.macros);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMacro(id: number) {
|
||||||
|
if (isNaN(id)) {
|
||||||
|
return () => Observable.of<Macro>(undefined);
|
||||||
|
} else {
|
||||||
|
return (state$: Observable<AppState>) => getMacros()(state$)
|
||||||
|
.map((macros: Macro[]) => macros.find((macro: Macro) => macro.id === id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateAbbr(keymaps: Keymap[], abbr: string): string {
|
||||||
|
const chars: string[] = '23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||||
|
let position = 0;
|
||||||
|
|
||||||
|
while (keymaps.some((keymap: Keymap) => keymap.abbreviation === abbr)) {
|
||||||
|
abbr = abbr.substring(0, abbr.length - 1) + chars[position];
|
||||||
|
++position;
|
||||||
|
}
|
||||||
|
|
||||||
|
return abbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateMacroId(macros: Macro[]) {
|
||||||
|
let newId = 0;
|
||||||
|
|
||||||
|
macros.forEach((macro: Macro) => {
|
||||||
|
if (macro.id > newId) {
|
||||||
|
newId = macro.id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newId + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkExistence(layers: Layer[], property: string, value: any) {
|
||||||
|
let newLayers = layers.map((layer) => {
|
||||||
|
let newLayer = new Layer(layer);
|
||||||
|
|
||||||
|
newLayer.modules = layer.modules.map((module: Module) => {
|
||||||
|
module.keyActions.forEach((action: KeyAction, index: number) => {
|
||||||
|
if (action && action.hasOwnProperty(property) && action[property] === value) {
|
||||||
|
module.keyActions[index] = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return module;
|
||||||
|
});
|
||||||
|
|
||||||
|
return newLayer;
|
||||||
|
});
|
||||||
|
|
||||||
|
return newLayers;
|
||||||
|
}
|
||||||
@@ -26,12 +26,7 @@ export class DataStorage {
|
|||||||
initialState(): AppState {
|
initialState(): AppState {
|
||||||
const config: UserConfiguration = this.getConfiguration();
|
const config: UserConfiguration = this.getConfiguration();
|
||||||
return {
|
return {
|
||||||
keymaps: {
|
userConfiguration: config,
|
||||||
entities: config.keymaps
|
|
||||||
},
|
|
||||||
macros: {
|
|
||||||
entities: config.macros
|
|
||||||
},
|
|
||||||
presetKeymaps: this.uhkPresets
|
presetKeymaps: this.uhkPresets
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -51,31 +46,8 @@ export class DataStorage {
|
|||||||
// TODO: Add type for state
|
// TODO: Add type for state
|
||||||
saveState(reducer: any): (state: any, action: Action) => AppState {
|
saveState(reducer: any): (state: any, action: Action) => AppState {
|
||||||
return (state: any, action: Action) => {
|
return (state: any, action: Action) => {
|
||||||
let nextState = reducer(state, action);
|
const nextState = reducer(state, action);
|
||||||
let config: UserConfiguration;
|
this._environment.saveConfig(nextState);
|
||||||
|
|
||||||
// Save elements to the UhkConfiguration
|
|
||||||
if (
|
|
||||||
action.type.startsWith(KeymapActions.PREFIX) &&
|
|
||||||
(
|
|
||||||
(nextState.entities && nextState.entities.length && nextState.entities[0] instanceof Keymap) ||
|
|
||||||
(state.entities && state.entities.length && state.entities[0] instanceof Keymap)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
config = this.getConfiguration();
|
|
||||||
config.keymaps = Object.values(nextState.entities);
|
|
||||||
this._environment.saveConfig(config);
|
|
||||||
} else if (
|
|
||||||
action.type.startsWith(MacroActions.PREFIX) &&
|
|
||||||
(
|
|
||||||
(nextState.entities && nextState.entities.length && nextState.entities[0] instanceof Macro) ||
|
|
||||||
(state.entities && state.entities.length && state.entities[0] instanceof Macro)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
config = this.getConfiguration();
|
|
||||||
config.macros = Object.values(nextState.entities);
|
|
||||||
this._environment.saveConfig(config);
|
|
||||||
}
|
|
||||||
return nextState;
|
return nextState;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ import { CaptureService } from './shared/services/capture.service';
|
|||||||
import { MapperService } from './shared/services/mapper.service';
|
import { MapperService } from './shared/services/mapper.service';
|
||||||
|
|
||||||
import { KeymapEffects, MacroEffects } from './shared/store/effects';
|
import { KeymapEffects, MacroEffects } from './shared/store/effects';
|
||||||
import { keymapReducer, macroReducer, presetReducer } from './shared/store/reducers';
|
import { userConfigurationReducer, presetReducer } from './shared/store/reducers';
|
||||||
import { DataStorage } from './shared/store/storage';
|
import { DataStorage } from './shared/store/storage';
|
||||||
|
|
||||||
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
import { KeymapEditGuard } from './shared/components/keymap/edit';
|
||||||
@@ -79,8 +79,7 @@ const storageService: DataStorage = storageInjector.get(DataStorage);
|
|||||||
|
|
||||||
// All reducers that are used in application
|
// All reducers that are used in application
|
||||||
const storeConfig = {
|
const storeConfig = {
|
||||||
keymaps: storageService.saveState(keymapReducer),
|
userConfiguration: storageService.saveState(userConfigurationReducer),
|
||||||
macros: storageService.saveState(macroReducer),
|
|
||||||
presetKeymaps: presetReducer
|
presetKeymaps: presetReducer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user