Merge pull request #32 from MyEtherWallet/persist_language_select

Redux: Persist language selection to local storage via middleware and…
This commit is contained in:
Daniel Ternyak 2017-07-05 17:57:40 -05:00 committed by GitHub
commit 3a1eaf9af1
5 changed files with 119 additions and 3 deletions

View File

@ -12,9 +12,11 @@ import createSagaMiddleware from 'redux-saga';
import notificationsSaga from './sagas/notifications';
import ensSaga from './sagas/ens';
import walletSaga from './sagas/wallet';
import { initialState as configInitialState } from 'reducers/config';
import throttle from 'lodash/throttle';
// application styles
import 'assets/styles/etherwallet-master.less';
import { saveState, loadStatePropertyOrEmptyObject } from 'utils/localStorage';
let store;
@ -34,10 +36,32 @@ const configureStore = () => {
middleware = applyMiddleware(sagaMiddleware, routerMiddleware(history));
}
store = createStore(RootReducer, void 0, middleware);
const persistedConfigInitialState = {
config: {
...configInitialState,
...loadStatePropertyOrEmptyObject('config')
}
};
const completePersistedInitialState = {
...persistedConfigInitialState
};
store = createStore(RootReducer, completePersistedInitialState, middleware);
sagaMiddleware.run(notificationsSaga);
sagaMiddleware.run(ensSaga);
sagaMiddleware.run(walletSaga);
store.subscribe(
throttle(() => {
saveState({
config: {
languageSelection: store.getState().config.languageSelection
}
});
}),
1000
);
return store;
};

View File

@ -12,7 +12,7 @@ export type State = {
nodeSelection: string
};
const initialState: State = {
export const initialState: State = {
languageSelection: languages[0].sign,
nodeSelection: Object.keys(NODES)[0]
};

View File

@ -0,0 +1,33 @@
// @flow
export const REDUX_STATE = 'REDUX_STATE';
export const loadState = () => {
try {
const serializedState = localStorage.getItem(REDUX_STATE);
if (serializedState === null) {
return undefined;
}
return JSON.parse(serializedState);
} catch (err) {
console.warn(' Warning: corrupted local storage');
}
};
export const saveState = (state: Object) => {
try {
const serializedState = JSON.stringify(state);
localStorage.setItem(REDUX_STATE, serializedState);
} catch (err) {
console.warn(' Warning: failed to set to local storage', state);
}
};
export const loadStatePropertyOrEmptyObject = (key: string): Object => {
const localStorageState = loadState();
if (localStorageState) {
if (localStorageState.hasOwnProperty(key)) {
return localStorageState[key];
}
}
return {};
};

View File

@ -0,0 +1,21 @@
export default class LocalStorageMock {
constructor() {
this.store = {};
}
clear() {
this.store = {};
}
getItem(key) {
return this.store[key];
}
setItem(key, value) {
this.store[key] = value.toString();
}
removeItem(key) {
delete this.store[key];
}
}

View File

@ -0,0 +1,38 @@
import LocalStorageMock from '../mocks/localStorage';
import {
loadState,
saveState,
loadStatePropertyOrEmptyObject,
REDUX_STATE
} from '../../common/utils/localStorage';
window.localStorage = new LocalStorageMock();
describe('saveState', () => {
it('should serialize and persist state to local storage under key: "REDUX_STATE"', () => {
const persistMe = {
foo: 'bar'
};
saveState(persistMe);
expect(JSON.parse(localStorage.getItem(REDUX_STATE))).toEqual(persistMe);
});
});
describe('loadStage', () => {
it('should return local storage under KEY: "REDUX_STATE"', () => {
const exValue = 'foo';
localStorage.setItem(REDUX_STATE, JSON.stringify(exValue));
expect(loadState()).toEqual(exValue);
});
});
describe('loadStatePropertyOrEmptyObject', () => {
it('should return property of object from local storage under KEY: "REDUX_STATE"', () => {
const serializeThis = {
one: 'foo',
two: 'bar'
};
saveState(serializeThis);
expect(loadStatePropertyOrEmptyObject('one')).toEqual(serializeThis.one);
});
});