Skip to content

Commit c43e4dd

Browse files
committed
Rewrite to a better composition model
1 parent 794719d commit c43e4dd

File tree

5 files changed

+91
-71
lines changed

5 files changed

+91
-71
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@
5151
"webpack": "^1.11.0"
5252
},
5353
"peerDependencies": {
54-
"redux-devtools": "^3.0.0-alpha-3",
55-
"redux": ">=3.0.0"
54+
"redux-devtools": "^3.0.0-alpha-4",
55+
"redux": "^3.0.0",
56+
"react-redux": "^3.0.0"
5657
},
5758
"dependencies": {
5859
"react-json-tree": "^0.1.9",

src/LogMonitor.js

Lines changed: 88 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, { PropTypes, Component } from 'react';
2-
import { connectMonitor } from 'redux-devtools';
2+
import { ActionCreators } from 'redux-devtools';
33
import LogMonitorEntry from './LogMonitorEntry';
44
import LogMonitorButton from './LogMonitorButton';
5-
import { toggleVisibility } from './actions';
5+
import { combineReducers, bindActionCreators } from 'redux';
66
import * as themes from 'redux-devtools-themes';
7+
import { connect } from 'react-redux';
78

89
const styles = {
910
container: {
@@ -34,36 +35,31 @@ const styles = {
3435
}
3536
};
3637

37-
class LogMonitor extends Component {
38-
constructor(props) {
39-
super(props);
40-
if (typeof window !== 'undefined') {
41-
window.addEventListener('keydown', ::this.handleKeyPress);
42-
}
43-
}
44-
38+
export default class LogMonitor extends Component {
4539
static propTypes = {
46-
// Provided by Redux DevTools
47-
computedStates: PropTypes.array.isRequired,
48-
currentStateIndex: PropTypes.number.isRequired,
49-
stagedActions: PropTypes.array.isRequired,
50-
skippedActions: PropTypes.object.isRequired,
51-
reset: PropTypes.func.isRequired,
52-
commit: PropTypes.func.isRequired,
53-
rollback: PropTypes.func.isRequired,
54-
sweep: PropTypes.func.isRequired,
55-
toggleAction: PropTypes.func.isRequired,
56-
jumpToState: PropTypes.func.isRequired,
57-
58-
// Provided via built-in reducer and actions
5940
monitorState: PropTypes.shape({
60-
isVisible: PropTypes.bool.isRequired
41+
initialScrollTop: PropTypes.number.isRequired
6142
}).isRequired,
43+
6244
monitorActions: PropTypes.shape({
63-
toggleVisibility: PropTypes.func.isRequired
45+
updateScrollTop: PropTypes.func.isRequired
46+
}).isRequired,
47+
48+
devToolsState: PropTypes.shape({
49+
computedStates: PropTypes.array.isRequired,
50+
currentStateIndex: PropTypes.number.isRequired,
51+
stagedActions: PropTypes.array.isRequired,
52+
skippedActions: PropTypes.object.isRequired
53+
}).isRequired,
54+
55+
devToolsActions: PropTypes.shape({
56+
reset: PropTypes.func.isRequired,
57+
commit: PropTypes.func.isRequired,
58+
rollback: PropTypes.func.isRequired,
59+
sweep: PropTypes.func.isRequired,
60+
toggleAction: PropTypes.func.isRequired
6461
}).isRequired,
6562

66-
// Regular props
6763
select: PropTypes.func.isRequired,
6864
theme: PropTypes.oneOfType([
6965
PropTypes.object,
@@ -76,12 +72,32 @@ class LogMonitor extends Component {
7672
theme: 'nicinabox'
7773
};
7874

75+
componentDidMount() {
76+
const node = this.refs.container;
77+
if (!node) {
78+
return;
79+
}
80+
81+
node.scrollTop = this.props.monitorState.initialScrollTop;
82+
this.interval = setInterval(::this.updateScrollTop, 1000);
83+
}
84+
85+
componentWillUnmount() {
86+
clearInterval(this.setInterval);
87+
}
88+
89+
updateScrollTop() {
90+
const node = this.refs.container;
91+
this.props.monitorActions.updateScrollTop(node ? node.scrollTop : 0);
92+
}
93+
7994
componentWillReceiveProps(nextProps) {
80-
const node = this.refs.elements;
95+
const node = this.refs.container;
8196
if (!node) {
8297
this.scrollDown = true;
8398
} else if (
84-
this.props.stagedActions.length < nextProps.stagedActions.length
99+
this.props.devToolsState.stagedActions.length <
100+
nextProps.devToolsState.stagedActions.length
85101
) {
86102
const { scrollTop, offsetHeight, scrollHeight } = node;
87103

@@ -94,7 +110,7 @@ class LogMonitor extends Component {
94110
}
95111

96112
componentDidUpdate() {
97-
const node = this.refs.elements;
113+
const node = this.refs.container;
98114
if (!node) {
99115
return;
100116
}
@@ -106,35 +122,30 @@ class LogMonitor extends Component {
106122
}
107123

108124
handleRollback() {
109-
this.props.rollback();
125+
this.props.devToolsActions.rollback();
110126
}
111127

112128
handleSweep() {
113-
this.props.sweep();
129+
this.props.devToolsActions.sweep();
114130
}
115131

116132
handleCommit() {
117-
this.props.commit();
133+
this.props.devToolsActions.commit();
118134
}
119135

120136
handleToggleAction(index) {
121-
this.props.toggleAction(index);
137+
this.props.devToolsActions.toggleAction(index);
122138
}
123139

124140
handleReset() {
125-
this.props.reset();
126-
}
127-
128-
handleKeyPress(event) {
129-
if (event.ctrlKey && event.keyCode === 72) { // Ctrl+H
130-
event.preventDefault();
131-
this.props.monitorActions.toggleVisibility();
132-
}
141+
this.props.devToolsActions.reset();
133142
}
134143

135144
render() {
136145
const elements = [];
137-
const { monitorState, skippedActions, stagedActions, computedStates, select } = this.props;
146+
const { devToolsState, select } = this.props;
147+
// const { isVisible } = monitorState;
148+
const { skippedActions, stagedActions, computedStates } = devToolsState;
138149

139150
let theme;
140151
if (typeof this.props.theme === 'string') {
@@ -148,10 +159,6 @@ class LogMonitor extends Component {
148159
theme = this.props.theme;
149160
}
150161

151-
if (!monitorState.isVisible) {
152-
return null;
153-
}
154-
155162
for (let i = 0; i < stagedActions.length; i++) {
156163
const action = stagedActions[i];
157164
const { state, error } = computedStates[i];
@@ -181,12 +188,45 @@ class LogMonitor extends Component {
181188
<LogMonitorButton theme={theme} onClick={::this.handleSweep} enabled={Object.keys(skippedActions).some(key => skippedActions[key])}>Sweep</LogMonitorButton>
182189
<LogMonitorButton theme={theme} onClick={::this.handleCommit} enabled={computedStates.length > 1}>Commit</LogMonitorButton>
183190
</div>
184-
<div style={styles.elements} ref="elements">
191+
<div style={styles.elements} ref='container'>
185192
{elements}
186193
</div>
187194
</div>
188195
);
189196
}
190197
}
191198

192-
export default connectMonitor({ toggleVisibility })(LogMonitor);
199+
const UPDATE_SCROLL_TOP = '@@redux-devtools-log-monitor/UPDATE_SCROLL_TOP';
200+
function updateScrollTop(scrollTop) {
201+
return { type: UPDATE_SCROLL_TOP, scrollTop };
202+
}
203+
204+
function createReducer({ preserveScrollTop = true }) {
205+
function initialScrollTop(state = 0, action) {
206+
if (!preserveScrollTop) {
207+
return 0;
208+
}
209+
210+
return action.type === UPDATE_SCROLL_TOP ?
211+
action.scrollTop :
212+
state;
213+
}
214+
215+
return combineReducers({ initialScrollTop });
216+
}
217+
218+
function mapStateToProps(state) {
219+
return state;
220+
}
221+
222+
function mapDispatchToProps(dispatch) {
223+
return {
224+
monitorActions: bindActionCreators({ updateScrollTop }, dispatch),
225+
devToolsActions: bindActionCreators(ActionCreators, dispatch)
226+
};
227+
}
228+
229+
LogMonitor = connect(mapStateToProps, mapDispatchToProps)(LogMonitor);
230+
LogMonitor.createReducer = createReducer;
231+
232+
export default LogMonitor;

src/actions.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/createMonitorReducer.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
export default from './LogMonitor';
2-
export { default as createMonitorReducer } from './createMonitorReducer';

0 commit comments

Comments
 (0)