Skip to content

Commit d7089e4

Browse files
committed
Implement Monitor class
Related to #145.
1 parent 9254258 commit d7089e4

File tree

2 files changed

+52
-44
lines changed

2 files changed

+52
-44
lines changed

src/app/service/Monitor.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const monitorActions = [
2+
'TOGGLE_ACTION', 'SWEEP', 'SET_ACTIONS_ACTIVE', 'IMPORT_STATE'
3+
];
4+
5+
export default class Monitor {
6+
constructor(update) {
7+
this.update = update;
8+
}
9+
reducer = (state = {}, action) => {
10+
if (!this.active) return state;
11+
this.lastAction = action.type;
12+
if (this.isHotReloaded()) {
13+
// Send new lifted state on hot-reloading
14+
setTimeout(this.update, 0);
15+
}
16+
return state;
17+
};
18+
start = () => {
19+
this.active = true;
20+
this.update();
21+
};
22+
stop = () => {
23+
this.active = false;
24+
clearTimeout(this.waitingTimeout);
25+
};
26+
isWaiting = () => {
27+
const currentTime = Date.now();
28+
if (this.lastTime && currentTime - this.lastTime < 200) {
29+
// no more frequently than once in 200ms
30+
this.stop();
31+
this.waitingTimeout = setTimeout(this.start, 1000);
32+
return true;
33+
}
34+
this.lastTime = currentTime;
35+
return false;
36+
};
37+
isHotReloaded = () => this.lastAction === '@@redux/INIT';
38+
isMonitorAction = () => monitorActions.indexOf(this.lastAction) !== -1;
39+
isTimeTraveling = () => this.lastAction === 'JUMP_TO_STATE';
40+
}

src/browser/extension/inject/pageScript.js

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import createStore from '../../../app/store/createStore';
22
import configureStore from '../../../app/store/configureStore';
33
import { isAllowed } from '../options/syncOptions';
4+
import Monitor from '../../../app/service/Monitor';
45
import { getLocalFilter, isFiltered, filterState } from '../utils/filters';
56
import notifyErrors from '../utils/notifyErrors';
67
import importState from '../utils/importState';
@@ -21,16 +22,15 @@ window.devToolsExtension = function(reducer, preloadedState, config) {
2122

2223
let store;
2324
let shouldSerialize = config.serializeState || config.serializeAction;
24-
let lastAction;
25-
let lastTime;
26-
let waitingTimeout;
2725
let errorOccurred = false;
28-
let isMonitored = false;
2926
let isExcess;
3027
const instanceId = generateId(config.instanceId);
3128
const localFilter = getLocalFilter(config);
3229
const { statesFilter, actionsFilter } = config;
3330

31+
const monitor = new Monitor(relayState);
32+
if (config.getMonitor) config.getMonitor(monitor);
33+
3434
function relay(type, state, action, nextActionId) {
3535
const message = {
3636
type,
@@ -60,16 +60,6 @@ window.devToolsExtension = function(reducer, preloadedState, config) {
6060
relay('STATE', store.liftedStore.getState());
6161
}
6262

63-
function start() {
64-
isMonitored = true;
65-
relayState();
66-
}
67-
68-
function stop() {
69-
isMonitored = false;
70-
clearTimeout(waitingTimeout);
71-
}
72-
7363
function onMessage(message) {
7464
switch (message.type) {
7565
case 'DISPATCH':
@@ -88,10 +78,10 @@ window.devToolsExtension = function(reducer, preloadedState, config) {
8878
relayState();
8979
return;
9080
case 'START':
91-
start();
81+
monitor.start();
9282
return;
9383
case 'STOP':
94-
stop();
84+
monitor.stop();
9585
relay('STOP');
9686
}
9787
}
@@ -111,39 +101,17 @@ window.devToolsExtension = function(reducer, preloadedState, config) {
111101
relay('INIT_INSTANCE');
112102
}
113103

114-
function monitorReducer(state = {}, action) {
115-
if (!isMonitored) return state;
116-
lastAction = action.type;
117-
if (lastAction === '@@redux/INIT' && store.liftedStore) {
118-
// Send new lifted state on hot-reloading
119-
setTimeout(relayState, 0);
120-
}
121-
return state;
122-
}
123-
124-
const monitorActions = [
125-
'TOGGLE_ACTION', 'SWEEP', 'SET_ACTIONS_ACTIVE', 'IMPORT_STATE'
126-
];
127-
function isWaiting() {
128-
const currentTime = Date.now();
129-
if (lastTime && currentTime - lastTime < 200) { // no more frequently than once in 200ms
130-
stop();
131-
waitingTimeout = setTimeout(start, 1000);
132-
return true;
133-
}
134-
lastTime = currentTime;
135-
return false;
136-
}
137-
138104
function handleChange(state, liftedState) {
139-
if (!isMonitored) return;
105+
if (!monitor.active) return;
140106
const nextActionId = liftedState.nextActionId;
141107
const liftedAction = liftedState.actionsById[nextActionId - 1];
142108
const action = liftedAction.action;
143109
if (action.type === '@@INIT') {
144110
relay('INIT', state, { timestamp: Date.now() });
145-
} else if (!errorOccurred && monitorActions.indexOf(lastAction) === -1) {
146-
if (lastAction === 'JUMP_TO_STATE' || isFiltered(action, localFilter) || isWaiting()) return;
111+
} else if (!errorOccurred && !monitor.isMonitorAction()) {
112+
if (
113+
monitor.isTimeTraveling() || isFiltered(action, localFilter) || monitor.isWaiting()
114+
) return;
147115
const { maxAge } = window.devToolsOptions;
148116
relay('ACTION', state, liftedAction, nextActionId);
149117
if (!isExcess && maxAge) isExcess = liftedState.stagedActionIds.length >= maxAge;
@@ -160,7 +128,7 @@ window.devToolsExtension = function(reducer, preloadedState, config) {
160128
if (!isAllowed(window.devToolsOptions)) return next(reducer_, initialState_, enhancer_);
161129

162130
store = stores[instanceId] =
163-
configureStore(next, monitorReducer, config)(reducer_, initialState_, enhancer_);
131+
configureStore(next, monitor.reducer, config)(reducer_, initialState_, enhancer_);
164132

165133
init();
166134
store.subscribe(() => {

0 commit comments

Comments
 (0)