refactor(store): Refactor reducer initialisation (#298)

* refactor(store): Refactor reducer initialization

Refactored the ngrx/store reducer initialization, because hard to extend the original solution.
Bad practise the object initialization inside the components / services. The new solution use angular DI everywhere.
Separated the web and electron configuration store.

* Media key support (#294)

* Introduce type for KeystrokeAction

* Increment dataModelVersion

New property 'type' for KeystrokeAction

* Mapping for media keys

* Media key selecting support for KeypressTab

* refactor: Use more meaningful name (selectedScancodeOption)

* Store the keystroke type in key action type instead of a new field

* Fix NoneAction validation
Fixes #301

* Update electron version

It fixes electron build. The types are part of the electron package itself.

* Fix keystroke selection when additional field is given but no scancode (#306)

* Additional media keys with icons (#307)

* Add missing scancodes for media keystrokes

* Use icons for media keys

* Fix media scancodes.

* Create README.md

* build: upgrade electron and typescript version

Electron contains the typings files.

* refactor(store): Refactor reducer initialization

Refactored the ngrx/store reducer initialization, because hard to extend the original solution.
Bad practise the object initialization inside the components / services. The new solution use angular DI everywhere.
Separated the web and electron configuration store.

* build: upgrade electron and typescript version

Electron contains the typings files.

* fix(store): Remove the I prefix from IDataStorageRepositoryService

* fix(store): fix observer operator import

* fix(store): Add missing rxjs imports to user-config effect

* fix(store): Add missing rxjs imports to keymap effect
This commit is contained in:
Róbert Kiss
2017-06-13 14:41:40 +02:00
committed by László Monda
parent 679e20d915
commit 367bc42457
20 changed files with 232 additions and 141 deletions

View File

@@ -14,6 +14,21 @@ export namespace KeymapActions {
export const SET_DEFAULT = KeymapActions.PREFIX + 'Set default option';
export const REMOVE = KeymapActions.PREFIX + 'Remove keymap';
export const CHECK_MACRO = KeymapActions.PREFIX + 'Check deleted macro';
export const LOAD_KEYMAPS = KeymapActions.PREFIX + 'Load keymaps';
export const LOAD_KEYMAPS_SUCCESS = KeymapActions.PREFIX + 'Load keymaps success';
export function loadKeymaps(): Action {
return {
type: KeymapActions.LOAD_KEYMAPS
};
}
export function loadKeymapsSuccess(keymaps: Keymap[]): Action {
return {
type: KeymapActions.LOAD_KEYMAPS_SUCCESS,
payload: keymaps
};
}
export function addKeymap(item: Keymap): Action {
return {

View File

@@ -0,0 +1,28 @@
import { Action } from '@ngrx/store';
import { type } from '../../util';
import { UserConfiguration } from '../../config-serializer/config-items/UserConfiguration';
const PREFIX = '[user-config] ';
// tslint:disable-next-line:variable-name
export const ActionTypes = {
LOAD_USER_CONFIG: type(PREFIX + 'Load User Config'),
LOAD_USER_CONFIG_SUCCESS: type(PREFIX + 'Load User Config Success')
};
export class LoadUserConfigAction implements Action {
type = ActionTypes.LOAD_USER_CONFIG;
}
export class LoadUserConfigSuccessAction implements Action {
type = ActionTypes.LOAD_USER_CONFIG_SUCCESS;
constructor(public payload: UserConfiguration) {
}
}
export type Actions
= LoadUserConfigAction
| LoadUserConfigSuccessAction;

View File

@@ -1,2 +1,3 @@
export * from './keymap';
export * from './macro';
export * from './user-config';

View File

@@ -2,11 +2,15 @@ import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Actions, Effect } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { Action, Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/withLatestFrom';
import 'rxjs/add/observable/of';
import { KeymapActions } from '../actions';
import { AppState } from '../index';
@@ -16,6 +20,17 @@ import { Keymap } from '../../config-serializer/config-items/Keymap';
@Injectable()
export class KeymapEffects {
@Effect() loadKeymaps$: Observable<Action> = this.actions$
.ofType(KeymapActions.LOAD_KEYMAPS)
.startWith(KeymapActions.loadKeymaps())
.switchMap(() => {
const presetsRequireContext = (<any>require).context('../../../res/presets', false, /.json$/);
const uhkPresets = presetsRequireContext.keys().map(presetsRequireContext) // load the presets into an array
.map((keymap: any) => new Keymap().fromJsonObject(keymap));
return Observable.of(KeymapActions.loadKeymapsSuccess(uhkPresets));
});
@Effect({ dispatch: false }) addOrDuplicate$: any = this.actions$
.ofType(KeymapActions.ADD, KeymapActions.DUPLICATE)
.withLatestFrom(this.store)

View File

@@ -0,0 +1,32 @@
import { Injectable, Inject } from '@angular/core';
import { Effect, Actions } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { Action } from '@ngrx/store';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/of';
import { ActionTypes, LoadUserConfigAction, LoadUserConfigSuccessAction } from '../actions/user-config';
import { UserConfiguration } from '../../config-serializer/config-items/UserConfiguration';
import { DataStorageRepositoryService, DATA_STORAGE_REPOSITORY } from '../../services/datastorage-repository.service';
import { DefaultUserConfigurationService } from '../../services/default-user-configuration.service';
@Injectable()
export class UserConfigEffects {
@Effect() loadUserConfig$: Observable<Action> = this.actions$
.ofType(ActionTypes.LOAD_USER_CONFIG)
.startWith(new LoadUserConfigAction())
.switchMap(() => {
let config: UserConfiguration = this.dataStorageRepository.getConfig();
if (!config) {
config = this.defaultUserConfigurationService.getDefault();
}
return Observable.of(new LoadUserConfigSuccessAction(config));
});
constructor(private actions$: Actions,
@Inject(DATA_STORAGE_REPOSITORY)private dataStorageRepository: DataStorageRepositoryService,
private defaultUserConfigurationService: DefaultUserConfigurationService) { }
}

View File

@@ -1,4 +1,11 @@
import userConfigurationReducer, { getUserConfiguration } from './user-configuration';
import { routerReducer } from '@ngrx/router-store';
import userConfigurationReducer from './user-configuration';
import presetReducer from './preset';
export { userConfigurationReducer, presetReducer, getUserConfiguration };
// All reducers that are used in application
export const reducer = {
userConfiguration: userConfigurationReducer,
presetKeymaps: presetReducer,
router: routerReducer
};

View File

@@ -1,7 +1,17 @@
import { Action } from '@ngrx/store';
import { Keymap } from '../../config-serializer/config-items/Keymap';
import { KeymapActions } from '../actions/keymap';
const initialState: Keymap[] = [];
export default function(state = initialState): Keymap[] {
return state;
export default function(state = initialState, action: Action): Keymap[] {
switch (action.type) {
case KeymapActions.LOAD_KEYMAPS_SUCCESS: {
return Object.assign(state, action.payload);
}
default:
return state;
}
}

View File

@@ -13,6 +13,7 @@ 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';
import { ActionTypes } from '../actions/user-config';
const initialState: UserConfiguration = new UserConfiguration();
@@ -23,6 +24,10 @@ export default function (state = initialState, action: Action): UserConfiguratio
const changedUserConfiguration: UserConfiguration = Object.assign(new UserConfiguration(), state);
switch (action.type) {
case ActionTypes.LOAD_USER_CONFIG_SUCCESS: {
return Object.assign(changedUserConfiguration, action.payload);
}
case KeymapActions.ADD:
case KeymapActions.DUPLICATE:
{

View File

@@ -1,13 +0,0 @@
import { UserConfiguration } from '../../config-serializer/config-items/UserConfiguration';
export class Electron {
getConfig(): UserConfiguration {
// TODO implement load logic
return;
}
/* tslint:disable:no-unused-variable */
saveConfig(config: UserConfiguration): void {
// TODO implement save logic
}
}

View File

@@ -1,69 +0,0 @@
import { Injectable } from '@angular/core';
import { Action } from '@ngrx/store';
import { Keymap } from '../../config-serializer/config-items/Keymap';
import { UserConfiguration } from '../../config-serializer/config-items/UserConfiguration';
import { AppState } from '../index';
import { Electron } from './electron';
import { Local } from './local';
@Injectable()
export class DataStorage {
private _environment: Local | Electron;
private defaultUserConfiguration: UserConfiguration;
private uhkPresets: Keymap[];
constructor() {
this.initUHKJson();
this.detectEnvironment();
}
initialState(): AppState {
const config: UserConfiguration = this.getConfiguration();
return {
userConfiguration: config,
presetKeymaps: this.uhkPresets
};
}
detectEnvironment(): void {
// Electron
// TODO check if we can remove <any> when electron will be implemented (maybe use process.versions['electron'])
if (typeof window !== 'undefined' && (<any>window).process && (<any>window).process.type === 'renderer') {
this._environment = new Electron();
}
// Local storage
else {
this._environment = new Local(this.defaultUserConfiguration.dataModelVersion);
}
}
// TODO: Add type for state
saveState(reducer: any): (state: any, action: Action) => AppState {
return (state: any, action: Action) => {
const nextState = reducer(state, action);
this._environment.saveConfig(nextState);
return nextState;
};
}
initUHKJson() {
this.defaultUserConfiguration = new UserConfiguration()
.fromJsonObject(require('json-loader!../../config-serializer/user-config.json'));
const presetsRequireContext = (<any>require).context('../../../res/presets', false, /.json$/);
this.uhkPresets = presetsRequireContext.keys().map(presetsRequireContext) // load the presets into an array
.map((keymap: any) => new Keymap().fromJsonObject(keymap));
}
getConfiguration(): UserConfiguration {
let config: UserConfiguration = this._environment.getConfig();
if (!config) {
config = this.defaultUserConfiguration;
}
return config;
}
}

View File

@@ -1,24 +0,0 @@
import { UserConfiguration } from '../../config-serializer/config-items/UserConfiguration';
export class Local {
constructor(private dataModelVersion: number) { }
getConfig(): UserConfiguration {
const configJsonString = localStorage.getItem('config');
let config: UserConfiguration;
if (configJsonString) {
const configJsonObject = JSON.parse(configJsonString);
if (configJsonObject.dataModelVersion === this.dataModelVersion) {
config = new UserConfiguration().fromJsonObject(configJsonObject);
}
}
return config;
}
saveConfig(config: UserConfiguration): void {
localStorage.setItem('config', JSON.stringify(config.toJsonObject()));
}
}