mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-22 09:36:43 +03:00
feat(extension): add persistence of settings (#826)
This commit is contained in:
parent
ad23a3ed8b
commit
a3a46cabf0
|
@ -41,13 +41,15 @@
|
|||
"@redux-devtools/utils": "^1.0.0-6",
|
||||
"@types/jsan": "^3.1.2",
|
||||
"jsan": "^3.1.13",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react-icons": "^4.2.0",
|
||||
"react-json-tree": "^0.15.0",
|
||||
"react-redux": "^7.2.4",
|
||||
"redux": "^4.1.1"
|
||||
"redux": "^4.1.1",
|
||||
"redux-persist": "^6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/register": "^7.15.3",
|
||||
|
|
|
@ -1,14 +1,26 @@
|
|||
import { createStore, applyMiddleware, PreloadedState } from 'redux';
|
||||
import { createStore, applyMiddleware, PreloadedState, Reducer } from 'redux';
|
||||
import localForage from 'localforage';
|
||||
import { persistReducer, persistStore } from 'redux-persist';
|
||||
import exportState from '@redux-devtools/app/lib/middlewares/exportState';
|
||||
import panelDispatcher from '../middlewares/panelSync';
|
||||
import rootReducer from '../reducers/panel';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
import rootReducer, { StoreStateWithoutSocket } from '../reducers/panel';
|
||||
import { StoreAction } from '@redux-devtools/app/lib/actions';
|
||||
|
||||
const persistConfig = {
|
||||
key: 'redux-devtools',
|
||||
blacklist: ['instances', 'socket'],
|
||||
storage: localForage,
|
||||
};
|
||||
|
||||
const persistedReducer: Reducer<StoreStateWithoutSocket, StoreAction> =
|
||||
persistReducer(persistConfig, rootReducer) as any;
|
||||
|
||||
export default function configureStore(
|
||||
position: string,
|
||||
bgConnection: chrome.runtime.Port,
|
||||
preloadedState: PreloadedState<StoreState>
|
||||
bgConnection: chrome.runtime.Port
|
||||
) {
|
||||
const enhancer = applyMiddleware(exportState, panelDispatcher(bgConnection));
|
||||
return createStore(rootReducer, preloadedState, enhancer);
|
||||
const store = createStore(persistedReducer, enhancer);
|
||||
const persistor = persistStore(store);
|
||||
return { store, persistor };
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@ import {
|
|||
compose,
|
||||
applyMiddleware,
|
||||
Store,
|
||||
PreloadedState,
|
||||
StoreEnhancer,
|
||||
Reducer,
|
||||
} from 'redux';
|
||||
import localForage from 'localforage';
|
||||
import { persistReducer, persistStore } from 'redux-persist';
|
||||
import exportState from '@redux-devtools/app/lib/middlewares/exportState';
|
||||
import api from '@redux-devtools/app/lib/middlewares/api';
|
||||
import { CONNECT_REQUEST } from '@redux-devtools/app/lib/constants/socketActionTypes';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
import {
|
||||
StoreAction,
|
||||
StoreActionWithoutUpdateState,
|
||||
UpdateStateAction,
|
||||
} from '@redux-devtools/app/lib/actions';
|
||||
|
@ -22,6 +22,7 @@ import rootReducer from '../reducers/window';
|
|||
import { BackgroundState } from '../reducers/background';
|
||||
import { BackgroundAction } from './backgroundStore';
|
||||
import { EmptyUpdateStateAction, NAAction } from '../middlewares/api';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
|
||||
export interface ExpandedUpdateStateAction extends UpdateStateAction {
|
||||
readonly instances: InstancesState;
|
||||
|
@ -33,10 +34,20 @@ export type WindowStoreAction =
|
|||
| NAAction
|
||||
| EmptyUpdateStateAction;
|
||||
|
||||
const persistConfig = {
|
||||
key: 'redux-devtools',
|
||||
blacklist: ['instances', 'socket'],
|
||||
storage: localForage,
|
||||
};
|
||||
|
||||
const persistedReducer: Reducer<StoreState, WindowStoreAction> = persistReducer(
|
||||
persistConfig,
|
||||
rootReducer
|
||||
) as any;
|
||||
|
||||
export default function configureStore(
|
||||
baseStore: Store<BackgroundState, BackgroundAction>,
|
||||
position: string,
|
||||
preloadedState: PreloadedState<StoreState>
|
||||
position: string
|
||||
) {
|
||||
let enhancer: StoreEnhancer;
|
||||
const middlewares = [exportState, api, syncStores(baseStore)];
|
||||
|
@ -54,7 +65,8 @@ export default function configureStore(
|
|||
: (noop: unknown) => noop
|
||||
);
|
||||
}
|
||||
const store = createStore(rootReducer, preloadedState, enhancer);
|
||||
const store = createStore(persistedReducer, enhancer);
|
||||
const persistor = persistStore(store);
|
||||
|
||||
if (
|
||||
store.getState().connection.options.hostname &&
|
||||
|
@ -65,5 +77,5 @@ export default function configureStore(
|
|||
});
|
||||
}
|
||||
|
||||
return store;
|
||||
return { store, persistor };
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
import { PreloadedState } from 'redux';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
|
||||
const getIfExists = (sel: any, template: any) =>
|
||||
typeof sel === 'undefined' ||
|
||||
typeof template === 'undefined' ||
|
||||
typeof template[sel] === 'undefined'
|
||||
? 0
|
||||
: sel;
|
||||
|
||||
export default function getPreloadedState(
|
||||
position: string,
|
||||
cb: (state: PreloadedState<StoreState>) => void
|
||||
) {
|
||||
chrome.storage.local.get(
|
||||
[
|
||||
'monitor' + position,
|
||||
'slider' + position,
|
||||
'dispatcher' + position,
|
||||
'test-templates',
|
||||
'test-templates-sel',
|
||||
],
|
||||
(options) => {
|
||||
cb({
|
||||
monitor: {
|
||||
selected: options['monitor' + position],
|
||||
sliderIsOpen: options['slider' + position] || false,
|
||||
dispatcherIsOpen: options['dispatcher' + position] || false,
|
||||
},
|
||||
test: {
|
||||
selected: getIfExists(
|
||||
options['test-templates-sel'],
|
||||
options['test-templates']
|
||||
),
|
||||
templates: options['test-templates'],
|
||||
},
|
||||
} as any);
|
||||
}
|
||||
);
|
||||
}
|
|
@ -1,17 +1,17 @@
|
|||
import React, { CSSProperties } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Persistor } from 'redux-persist';
|
||||
import { REMOVE_INSTANCE } from '@redux-devtools/app/lib/constants/actionTypes';
|
||||
import App from '../../../app/containers/App';
|
||||
import configureStore from '../../../app/stores/panelStore';
|
||||
import getPreloadedState from '../background/getPreloadedState';
|
||||
|
||||
import '../../views/devpanel.pug';
|
||||
import { Action, PreloadedState, Store } from 'redux';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
import { Action, Store } from 'redux';
|
||||
import { StoreAction } from '@redux-devtools/app/lib/actions';
|
||||
import { PanelMessage } from '../../../app/middlewares/api';
|
||||
import { StoreStateWithoutSocket } from '../../../app/reducers/panel';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
|
||||
const position = location.hash;
|
||||
const messageStyle: CSSProperties = {
|
||||
|
@ -22,24 +22,22 @@ const messageStyle: CSSProperties = {
|
|||
|
||||
let rendered: boolean | undefined;
|
||||
let store: Store<StoreStateWithoutSocket, StoreAction> | undefined;
|
||||
let persistor: Persistor | undefined;
|
||||
let bgConnection: chrome.runtime.Port;
|
||||
let naTimeout: NodeJS.Timeout;
|
||||
let preloadedState: PreloadedState<StoreState>;
|
||||
|
||||
const isChrome = navigator.userAgent.indexOf('Firefox') === -1;
|
||||
|
||||
getPreloadedState(position, (state) => {
|
||||
preloadedState = state;
|
||||
});
|
||||
|
||||
function renderDevTools() {
|
||||
const node = document.getElementById('root');
|
||||
unmountComponentAtNode(node!);
|
||||
clearTimeout(naTimeout);
|
||||
store = configureStore(position, bgConnection, preloadedState);
|
||||
({ store, persistor } = configureStore(position, bgConnection));
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<App position={position} />
|
||||
<PersistGate loading={null} persistor={persistor}>
|
||||
<App position={position} />
|
||||
</PersistGate>
|
||||
</Provider>,
|
||||
node
|
||||
);
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { PreloadedState } from 'redux';
|
||||
import { Provider } from 'react-redux';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import { UPDATE_STATE } from '@redux-devtools/app/lib/constants/actionTypes';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
import App from '../../../app/containers/App';
|
||||
import configureStore from '../../../app/stores/windowStore';
|
||||
import getPreloadedState from '../background/getPreloadedState';
|
||||
import { MonitorMessage } from '../../../app/middlewares/api';
|
||||
|
||||
import '../../views/window.pug';
|
||||
|
||||
const position = location.hash;
|
||||
let preloadedState: PreloadedState<StoreState>;
|
||||
getPreloadedState(position, (state) => {
|
||||
preloadedState = state;
|
||||
});
|
||||
|
||||
chrome.runtime.getBackgroundPage((window) => {
|
||||
const { store } = window!;
|
||||
const localStore = configureStore(store, position, preloadedState);
|
||||
const { store: localStore, persistor } = configureStore(store, position);
|
||||
let name = 'monitor';
|
||||
if (chrome && chrome.devtools && chrome.devtools.inspectedWindow) {
|
||||
name += chrome.devtools.inspectedWindow.tabId;
|
||||
|
@ -33,7 +27,9 @@ chrome.runtime.getBackgroundPage((window) => {
|
|||
|
||||
render(
|
||||
<Provider store={localStore}>
|
||||
<App position={position} />
|
||||
<PersistGate loading={null} persistor={persistor}>
|
||||
<App position={position} />
|
||||
</PersistGate>
|
||||
</Provider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Provider } from 'react-redux';
|
|||
import configureStore from '../../../src/app/stores/windowStore';
|
||||
import App from '../../../src/app/containers/App';
|
||||
|
||||
const store = configureStore(store);
|
||||
const { store } = configureStore(store);
|
||||
const component = mount(
|
||||
<Provider store={store}>
|
||||
<App position="devtools-left" />
|
||||
|
|
|
@ -43,6 +43,7 @@ describe('Chrome extension', function () {
|
|||
});
|
||||
|
||||
it("should contain inspector monitor's component", async () => {
|
||||
await delay(500);
|
||||
const val = await driver
|
||||
.findElement(webdriver.By.xpath('//div[contains(@class, "inspector-")]'))
|
||||
.getText();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createStore, compose, applyMiddleware } from 'redux';
|
||||
import { createStore, compose, applyMiddleware, Reducer } from 'redux';
|
||||
import localForage from 'localforage';
|
||||
import { persistReducer, persistStore } from 'redux-persist';
|
||||
import api from '../middlewares/api';
|
||||
|
@ -12,7 +12,10 @@ const persistConfig = {
|
|||
storage: localForage,
|
||||
};
|
||||
|
||||
const persistedReducer = persistReducer(persistConfig, rootReducer);
|
||||
const persistedReducer: Reducer<StoreState, StoreAction> = persistReducer(
|
||||
persistConfig,
|
||||
rootReducer
|
||||
) as any;
|
||||
|
||||
export default function configureStore() {
|
||||
let composeEnhancers = compose;
|
||||
|
@ -40,8 +43,8 @@ export default function configureStore() {
|
|||
}
|
||||
}
|
||||
|
||||
const store = createStore<StoreState, StoreAction, unknown, unknown>(
|
||||
persistedReducer as any,
|
||||
const store = createStore(
|
||||
persistedReducer,
|
||||
composeEnhancers(applyMiddleware(exportState, api))
|
||||
);
|
||||
const persistor = persistStore(store);
|
||||
|
|
|
@ -25958,6 +25958,7 @@ fsevents@^1.2.7:
|
|||
eslint-plugin-react-hooks: ^4.2.0
|
||||
gitbook-cli: ^2.3.2
|
||||
jsan: ^3.1.13
|
||||
localforage: ^1.10.0
|
||||
lodash: ^4.17.21
|
||||
path-browserify: ^1.0.1
|
||||
react: ^16.14.0
|
||||
|
@ -25968,6 +25969,7 @@ fsevents@^1.2.7:
|
|||
react-transform-catch-errors: ^1.0.2
|
||||
react-transform-hmr: ^1.0.4
|
||||
redux: ^4.1.1
|
||||
redux-persist: ^6.0.0
|
||||
selenium-webdriver: ^3.6.0
|
||||
sinon-chrome: ^3.0.1
|
||||
languageName: unknown
|
||||
|
|
Loading…
Reference in New Issue
Block a user