mirror of
https://github.com/morten-olsen/react-native-debug-console.git
synced 2026-02-08 00:36:26 +01:00
Lots of UI updates
This commit is contained in:
@@ -17,6 +17,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
fontFamily: 'Menlo-Regular',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -39,13 +40,13 @@ const Input = ({
|
||||
onPress={() => {
|
||||
const fn = new Function(text);
|
||||
try {
|
||||
const response = eval(text);
|
||||
log.info(response);
|
||||
const response = fn();
|
||||
log.info([response]);
|
||||
setState({
|
||||
text: '',
|
||||
});
|
||||
} catch (err) {
|
||||
log.error(err);
|
||||
log.error([err]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,59 +1,127 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import JSONTree from 'react-native-json-tree';
|
||||
import {
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
View,
|
||||
Text,
|
||||
ScrollView
|
||||
} from 'react-native';
|
||||
import JSONTree from 'react-native-json-tree'
|
||||
import prune from './tools';
|
||||
import {
|
||||
Body,
|
||||
Emphasis,
|
||||
Fixed,
|
||||
} from '../../base/text';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const getCircularReplacer = () => {
|
||||
const seen = [];
|
||||
return (key, val) => {
|
||||
if (val != null && typeof val == "object") {
|
||||
if (seen.indexOf(val) >= 0) {
|
||||
return;
|
||||
}
|
||||
seen.push(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
const theme = {
|
||||
scheme: 'bright',
|
||||
author: 'chris kempson (http://chriskempson.com)',
|
||||
base00: '#000000',
|
||||
base01: '#303030',
|
||||
base02: '#505050',
|
||||
base03: '#b0b0b0',
|
||||
base04: '#d0d0d0',
|
||||
base05: '#e0e0e0',
|
||||
base06: '#f5f5f5',
|
||||
base07: '#ffffff',
|
||||
base08: '#fb0120',
|
||||
base09: '#fc6d24',
|
||||
base0A: '#fda331',
|
||||
base0B: '#a1c659',
|
||||
base0C: '#76c7b7',
|
||||
base0D: '#6fb3d2',
|
||||
base0E: '#d381c3',
|
||||
base0F: '#be643c'
|
||||
};
|
||||
|
||||
const formatData = (data) => {
|
||||
const Wrapper = styled.View``;
|
||||
const List = styled.View`
|
||||
padding-left: 10px;
|
||||
border-left-width: 10px;
|
||||
border-color: ${props => props.color || 'black' }
|
||||
`;
|
||||
const Row = styled.View`
|
||||
margin: 10px;
|
||||
`;
|
||||
|
||||
const getColor = (type) => {
|
||||
if (type === 'error') {
|
||||
return 'red';
|
||||
}
|
||||
if (type === 'warn') {
|
||||
return 'yellow';
|
||||
}
|
||||
if (type === 'verbose') {
|
||||
return 'gray';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const formatData = (data, options) => {
|
||||
const {
|
||||
includeStackTrace
|
||||
} = options;
|
||||
if (typeof data === 'undefined') {
|
||||
return <Text>undefined</Text>;
|
||||
return <Fixed>undefined</Fixed>;
|
||||
}
|
||||
if (data instanceof Error) {
|
||||
return <Text>Error {data.toString()} {data.stack.toString()}</Text>;
|
||||
if (includeStackTrace) {
|
||||
return (
|
||||
<JSONTree
|
||||
theme={theme}
|
||||
data={{
|
||||
message: data.toString(),
|
||||
stackTrace: data.stack.toString(),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <Fixed>{data.toString()}</Fixed>;
|
||||
}
|
||||
}
|
||||
if (typeof data === 'object') {
|
||||
return <JSONTree data={prune(data, null, ' ')} />
|
||||
return <JSONTree data={data} />
|
||||
}
|
||||
return <Text>{data.toString()}</Text>;
|
||||
return <Fixed>{data.toString()}</Fixed>;
|
||||
}
|
||||
|
||||
const OutputList = ({
|
||||
items,
|
||||
color,
|
||||
includeStackTrace,
|
||||
}) => (
|
||||
<List color={color}>
|
||||
{items.map((data, i) => (
|
||||
<Fragment key={i}>
|
||||
{formatData(data, {
|
||||
includeStackTrace,
|
||||
})}
|
||||
</Fragment>
|
||||
))}
|
||||
</List>
|
||||
)
|
||||
|
||||
const Console = ({
|
||||
logs,
|
||||
includeStackTrace,
|
||||
}) => (
|
||||
<ScrollView style={styles.container}>
|
||||
<View>
|
||||
<ScrollView
|
||||
ref={ref => this.scrollView = ref}
|
||||
onContentSizeChange={(contentWidth, contentHeight)=>{
|
||||
this.scrollView.scrollToEnd({animated: true});
|
||||
}}
|
||||
>
|
||||
<Wrapper>
|
||||
{logs.map((log, i) => (
|
||||
<View key={i}>
|
||||
<Text>
|
||||
<Row key={i}>
|
||||
<Emphasis color={getColor(log.type)}>
|
||||
{log.type}
|
||||
</Text>
|
||||
{formatData(log.data)}
|
||||
</View>
|
||||
</Emphasis>
|
||||
<OutputList
|
||||
items={log.data}
|
||||
includeStackTrace={includeStackTrace}
|
||||
color={getColor(log.type)}
|
||||
/>
|
||||
</Row>
|
||||
))}
|
||||
</View>
|
||||
</Wrapper>
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
@@ -14,11 +14,13 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const Console = () => (
|
||||
const Console = ({
|
||||
includeStackTrace,
|
||||
}) => (
|
||||
<Log>
|
||||
{({ logs }) => (
|
||||
<View style={styles.container}>
|
||||
<Output logs={logs} />
|
||||
<Output logs={logs} includeStackTrace={includeStackTrace} />
|
||||
<Input />
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
SafeAreaView,
|
||||
KeyboardAvoidingView,
|
||||
} from 'react-native';
|
||||
import events from '../../events';
|
||||
import DevTool from './index';
|
||||
@@ -39,6 +41,10 @@ class Events extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
includeStackTrace
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
animationType="slide"
|
||||
@@ -47,15 +53,24 @@ class Events extends Component {
|
||||
onRequestClose={() => {
|
||||
}}
|
||||
>
|
||||
<Fragment>
|
||||
<DevTool />
|
||||
<Button
|
||||
title="close"
|
||||
onPress={() => {
|
||||
events.publish('HIDE_DEVTOOLS');
|
||||
}}
|
||||
/>
|
||||
</Fragment>
|
||||
<SafeAreaView
|
||||
forceInset={{ top: 'always', vertical: 'always' }}
|
||||
style={{flex: 1}}
|
||||
>
|
||||
<KeyboardAvoidingView
|
||||
style={{flex: 1}}
|
||||
behavior="padding"
|
||||
enabled
|
||||
>
|
||||
<DevTool includeStackTrace={includeStackTrace} />
|
||||
<Button
|
||||
title="close"
|
||||
onPress={() => {
|
||||
events.publish('HIDE_DEVTOOLS');
|
||||
}}
|
||||
/>
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,43 +1,98 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
View,
|
||||
Text,
|
||||
} from 'react-native';
|
||||
import styled from 'styled-components/native';
|
||||
import {
|
||||
Emphasis,
|
||||
Fixed,
|
||||
} from '../../base/text';
|
||||
import JSONTree from 'react-native-json-tree';
|
||||
import Cell from '../../base/Cell';
|
||||
import CellHeader from '../../base/CellHeader';
|
||||
import Tab from '../Tab';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
const theme = {
|
||||
scheme: 'bright',
|
||||
author: 'chris kempson (http://chriskempson.com)',
|
||||
base00: '#000000',
|
||||
base01: '#303030',
|
||||
base02: '#505050',
|
||||
base03: '#b0b0b0',
|
||||
base04: '#d0d0d0',
|
||||
base05: '#e0e0e0',
|
||||
base06: '#f5f5f5',
|
||||
base07: '#ffffff',
|
||||
base08: '#fb0120',
|
||||
base09: '#fc6d24',
|
||||
base0A: '#fda331',
|
||||
base0B: '#a1c659',
|
||||
base0C: '#76c7b7',
|
||||
base0D: '#6fb3d2',
|
||||
base0E: '#d381c3',
|
||||
base0F: '#be643c'
|
||||
};
|
||||
|
||||
const Indented = styled.View`
|
||||
margin: 0 25px;
|
||||
`;
|
||||
|
||||
const getResponse = (request) => {
|
||||
if (request.responseType == 'blob' || request.responseType == 'ArrayBuffer') {
|
||||
return <Emphasis>🤖 Binary</Emphasis>
|
||||
}
|
||||
const contentType = request.getResponseHeader('content-type');
|
||||
const contentTypes = contentType.split(';').map(c => c.trim());
|
||||
|
||||
if (contentTypes.includes('application/json')) {
|
||||
const data = JSON.parse(request.responseText);
|
||||
return <JSONTree theme={theme} data={data} />
|
||||
}
|
||||
|
||||
return <Fixed>{request.responseText}</Fixed>;
|
||||
}
|
||||
|
||||
const Data = ({
|
||||
url,
|
||||
method,
|
||||
status,
|
||||
headers,
|
||||
request,
|
||||
args = [],
|
||||
}) => (
|
||||
<ScrollView style={styles.container}>
|
||||
<View>
|
||||
<Text>Status: {status}</Text>
|
||||
<Text>Method: {method}</Text>
|
||||
<Text>Url: {url}</Text>
|
||||
<Text>Request Body:</Text>
|
||||
{args[0] && (
|
||||
<Text>{args[0].toString()}</Text>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}) => {
|
||||
const headerInfo = Object.keys(headers).map(key => `${key}: ${headers[key]}`).join('\n');
|
||||
return (
|
||||
<ScrollView>
|
||||
<View>
|
||||
<Cell left="Status" right={status} />
|
||||
<Cell left="Method" right={method} />
|
||||
<Cell left="Url" right={url} />
|
||||
<CellHeader>Response Headers</CellHeader>
|
||||
<Indented><Fixed>{request.getAllResponseHeaders()}</Fixed></Indented>
|
||||
{headerInfo && (
|
||||
<Fragment>
|
||||
<CellHeader>Request Headers</CellHeader>
|
||||
<Indented><Fixed>{headerInfo}</Fixed></Indented>
|
||||
</Fragment>
|
||||
)}
|
||||
{args[0] && (
|
||||
<Fragment>
|
||||
<CellHeader>Request Body</CellHeader>
|
||||
<Fixed>{args[0].toString()}</Fixed>
|
||||
</Fragment>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
const Response = ({
|
||||
request,
|
||||
}) => (
|
||||
<ScrollView style={styles.container}>
|
||||
<ScrollView>
|
||||
<View>
|
||||
<Text>Response: {request.responseText}</Text>
|
||||
{getResponse(request)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
@@ -46,10 +101,10 @@ const Response = ({
|
||||
const RequestDetails = (props) => (
|
||||
<Tab
|
||||
tabs={[{
|
||||
name: 'overview',
|
||||
name: 'Details',
|
||||
view: <Data {...props} />
|
||||
}, {
|
||||
name: 'response',
|
||||
name: 'Response',
|
||||
view: <Response {...props} />
|
||||
}]}
|
||||
/>
|
||||
|
||||
@@ -1,41 +1,31 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import Status from '../../base/Status';
|
||||
import Row from '../../base/Row';
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
Body,
|
||||
} from '../../base/text';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
borderColor: '#ccc',
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
padding: 10,
|
||||
},
|
||||
method: {
|
||||
padding: 5,
|
||||
},
|
||||
url: {
|
||||
flex: 1,
|
||||
padding: 5,
|
||||
},
|
||||
status: {
|
||||
padding: 5,
|
||||
},
|
||||
});
|
||||
const ScrollView = styled.ScrollView`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const Wrapper = styled.View`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const TouchableOpacity = styled.TouchableOpacity`
|
||||
`;
|
||||
|
||||
const RequestDetails = ({
|
||||
requests,
|
||||
onSelect,
|
||||
selected,
|
||||
}) => (
|
||||
<ScrollView style={styles.container}>
|
||||
<View>
|
||||
<ScrollView>
|
||||
<Wrapper>
|
||||
{requests.map(({
|
||||
id,
|
||||
status,
|
||||
method,
|
||||
url,
|
||||
@@ -44,14 +34,18 @@ const RequestDetails = ({
|
||||
key={i}
|
||||
onPress={() => onSelect(i)}
|
||||
>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.method}>{method}</Text>
|
||||
<Text style={styles.url}>{url}</Text>
|
||||
<Text style={styles.status}>{status}</Text>
|
||||
</View>
|
||||
<Row
|
||||
selected={selected === id}
|
||||
left={<Body>{method}</Body>}
|
||||
right={(
|
||||
<Status code={status} />
|
||||
)}
|
||||
>
|
||||
<Body>{url}</Body>
|
||||
</Row>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
</Wrapper>
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ const Console = () => (
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<List
|
||||
selected={selected ? selected.id : undefined}
|
||||
requests={requests}
|
||||
onSelect={(i) => setState({ active: i })}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text,
|
||||
@@ -30,20 +30,21 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'center',
|
||||
padding: 10,
|
||||
borderBottomWidth: 4,
|
||||
borderColor: 'red',
|
||||
borderColor: '#2980b9',
|
||||
},
|
||||
});
|
||||
|
||||
const Console = ({
|
||||
tabs,
|
||||
}) => (
|
||||
<State
|
||||
initState={{
|
||||
active: 0,
|
||||
}}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<State
|
||||
initState={{
|
||||
active: 0,
|
||||
}}
|
||||
>
|
||||
{({ active }, setState) => (
|
||||
<View style={styles.container}>
|
||||
<Fragment>
|
||||
<View style={styles.tabs}>
|
||||
{tabs.map(({ name }, i) => (
|
||||
<TouchableOpacity
|
||||
@@ -58,9 +59,10 @@ const Console = ({
|
||||
))}
|
||||
</View>
|
||||
{tabs[active] && tabs[active].view}
|
||||
</View>
|
||||
</Fragment>
|
||||
)}
|
||||
</State>
|
||||
</State>
|
||||
</View>
|
||||
);
|
||||
|
||||
Console.propTypes = {
|
||||
|
||||
@@ -15,14 +15,15 @@ const styles = StyleSheet.create({
|
||||
|
||||
const DevTool = ({
|
||||
style,
|
||||
includeStackTrace
|
||||
}) => (
|
||||
<View style={style || styles.container}>
|
||||
<Tab
|
||||
tabs={[{
|
||||
name: 'console',
|
||||
view: <Console />,
|
||||
name: 'Console',
|
||||
view: <Console includeStackTrace={includeStackTrace} />,
|
||||
}, {
|
||||
name: 'network',
|
||||
name: 'Network',
|
||||
view: <Requests />,
|
||||
}]}
|
||||
/>
|
||||
|
||||
29
lib/src/components/base/Cell.js
Normal file
29
lib/src/components/base/Cell.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import {
|
||||
Body,
|
||||
Emphasis,
|
||||
} from './text';
|
||||
|
||||
const Wrapper = styled.View`
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
`;
|
||||
|
||||
const Left = styled.View`
|
||||
width: 100px;
|
||||
`;
|
||||
|
||||
const Row = ({
|
||||
left,
|
||||
right,
|
||||
}) => (
|
||||
<Wrapper>
|
||||
<Left>
|
||||
<Emphasis>{left}:</Emphasis>
|
||||
</Left>
|
||||
<Body>{right}</Body>
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default Row;
|
||||
20
lib/src/components/base/CellHeader.js
Normal file
20
lib/src/components/base/CellHeader.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import {
|
||||
Emphasis,
|
||||
} from './text';
|
||||
|
||||
const Wrapper = styled.View`
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
`;
|
||||
|
||||
const Row = ({
|
||||
children,
|
||||
}) => (
|
||||
<Wrapper>
|
||||
<Emphasis>{children}:</Emphasis>
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default Row;
|
||||
35
lib/src/components/base/Row.js
Normal file
35
lib/src/components/base/Row.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
|
||||
const Wrapper = styled.View`
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
border-left-width: ${props => props.selected ? '10px' : '0'};
|
||||
border-color: #2980b9;
|
||||
`;
|
||||
|
||||
const Left = styled.View`
|
||||
`;
|
||||
|
||||
const Right = styled.View`
|
||||
`;
|
||||
|
||||
const Center = styled.View`
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
`;
|
||||
|
||||
const Row = ({
|
||||
left,
|
||||
right,
|
||||
children,
|
||||
selected,
|
||||
}) => (
|
||||
<Wrapper selected={selected}>
|
||||
{left && <Left>{left}</Left>}
|
||||
<Center>{children}</Center>
|
||||
{right && <Right>{right}</Right>}
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default Row;
|
||||
41
lib/src/components/base/Status.js
Normal file
41
lib/src/components/base/Status.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import {
|
||||
Body,
|
||||
} from '../base/text';
|
||||
|
||||
const getColor = (code) => {
|
||||
if (code >= 500) {
|
||||
return '#c0392b';
|
||||
}
|
||||
if (code >= 400) {
|
||||
return '#f1c40f';
|
||||
}
|
||||
if (code >= 300) {
|
||||
return '#2980b9';
|
||||
}
|
||||
return '#2ecc71';
|
||||
}
|
||||
|
||||
const Wrapper = styled.View`
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
const Icon = styled.View`
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 8px;
|
||||
background: ${props => getColor(props.code)};
|
||||
margin-left: 5px;
|
||||
`;
|
||||
|
||||
const Status = ({
|
||||
code,
|
||||
}) => (
|
||||
<Wrapper>
|
||||
<Body>{code}</Body>
|
||||
<Icon code={code} />
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default Status;
|
||||
14
lib/src/components/base/text.js
Normal file
14
lib/src/components/base/text.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import styled from 'styled-components/native';
|
||||
|
||||
export const Body = styled.Text`
|
||||
color: ${props => props.color || 'black'};
|
||||
`;
|
||||
|
||||
export const Emphasis = styled.Text`
|
||||
font-weight: bold;
|
||||
color: ${props => props.color || 'black'};
|
||||
`;
|
||||
|
||||
export const Fixed = styled.Text`
|
||||
font-family: Menlo-Regular;
|
||||
`;
|
||||
@@ -7,23 +7,18 @@ class Log extends Component {
|
||||
this.state = {
|
||||
logs: [],
|
||||
};
|
||||
this.addLog = this.addLog.bind(this);
|
||||
this.setLogs = this.setLogs.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
log.listen(this.addLog);
|
||||
log.listen(this.setLogs);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
log.unlisten(this.addLog);
|
||||
log.unlisten(this.setLogs);
|
||||
}
|
||||
|
||||
addLog(entry) {
|
||||
entry = Array.isArray(entry) ? entry : [entry];
|
||||
const logs = [
|
||||
...this.state.logs,
|
||||
...entry,
|
||||
];
|
||||
setLogs(logs) {
|
||||
this.setState({
|
||||
logs,
|
||||
});
|
||||
|
||||
@@ -7,23 +7,18 @@ class Network extends Component {
|
||||
this.state = {
|
||||
requests: [],
|
||||
};
|
||||
this.addRequest = this.addRequest.bind(this);
|
||||
this.setRequests = this.setRequests.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
network.listen(this.addRequest);
|
||||
network.listen(this.setRequests);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
network.unlisten(this.addRequest);
|
||||
network.unlisten(this.setRequests);
|
||||
}
|
||||
|
||||
addRequest(request) {
|
||||
request = Array.isArray(request) ? request : [request];
|
||||
const requests = [
|
||||
...this.state.requests,
|
||||
...request,
|
||||
];
|
||||
setRequests(requests) {
|
||||
this.setState({
|
||||
requests,
|
||||
});
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
/* const overrides = [
|
||||
'log',
|
||||
];
|
||||
|
||||
const proxies = overrides.reduce((output, key) => ({
|
||||
...output,
|
||||
[key]: window.console[key],
|
||||
}), {}); */
|
||||
|
||||
const proxyConsole = window.console;
|
||||
|
||||
class Log {
|
||||
@@ -24,41 +15,49 @@ class Log {
|
||||
this.listeners = this.listeners.filter(l => l !== fn);
|
||||
}
|
||||
|
||||
log(type, data) {
|
||||
log(type, data, keep) {
|
||||
const entry = {
|
||||
type,
|
||||
data,
|
||||
};
|
||||
this.logs.push(entry);
|
||||
this.listeners.forEach(l => l(entry));
|
||||
this.listeners.forEach(l => l(this.logs));
|
||||
if (keep) {
|
||||
proxyConsole[type](...data);
|
||||
}
|
||||
}
|
||||
|
||||
info(data) {
|
||||
this.log('info', data);
|
||||
info(data, keep) {
|
||||
this.log('info', data, keep);
|
||||
}
|
||||
|
||||
error(error) {
|
||||
this.log('error', error);
|
||||
error(data, keep) {
|
||||
this.log('error', data, keep);
|
||||
}
|
||||
|
||||
warn(data) {
|
||||
this.log('warn', data);
|
||||
warn(data, keep) {
|
||||
this.log('warn', data, keep);
|
||||
}
|
||||
|
||||
debug(data) {
|
||||
this.log('debug', data);
|
||||
debug(data, keep) {
|
||||
this.log('debug', data, keep);
|
||||
}
|
||||
|
||||
attach(keep) {
|
||||
const redirected = Object.keys(proxyConsole).reduce((output, key) => ({
|
||||
...output,
|
||||
[key]: keep ? (...args) => proxyConsole[key](...args) : () => {},
|
||||
}), {});
|
||||
window.console = {
|
||||
error: (...data) => this.error(...data),
|
||||
warn: (data) => this.warn(data),
|
||||
info: (data) => this.info(data),
|
||||
log: (data) => this.info(data),
|
||||
debug: (data) => this.debug(data),
|
||||
...redirected,
|
||||
error: (...data) => this.error(data, keep),
|
||||
warn: (...data) => this.warn(data, keep),
|
||||
info: (...data) => this.info(data, keep),
|
||||
log: (...data) => this.info(data, keep),
|
||||
debug: (...data) => this.debug(data, keep),
|
||||
};
|
||||
ErrorUtils.setGlobalHandler((err, fatal) => {
|
||||
this.error(err);
|
||||
this.error([err], keep);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ class Network {
|
||||
constructor() {
|
||||
this.requests = [];
|
||||
this.listeners = [];
|
||||
this.currentId = 0;
|
||||
}
|
||||
|
||||
listen(fn) {
|
||||
@@ -16,12 +17,16 @@ class Network {
|
||||
}
|
||||
|
||||
addRequest(request) {
|
||||
this.requests.push(request);
|
||||
this.listeners.forEach(l => l(request));
|
||||
this.requests.push({
|
||||
id: this.currentId++,
|
||||
...request,
|
||||
});
|
||||
this.listeners.forEach(l => l(this.requests));
|
||||
}
|
||||
|
||||
attach() {
|
||||
const me = this;
|
||||
const headers = {};
|
||||
window.XMLHttpRequest.prototype.open = function proxyOpen (...args) {
|
||||
let sendArgs;
|
||||
const [
|
||||
@@ -33,6 +38,7 @@ class Network {
|
||||
url,
|
||||
method,
|
||||
args: sendArgs,
|
||||
headers,
|
||||
request: this,
|
||||
status: this.status,
|
||||
});
|
||||
@@ -43,15 +49,21 @@ class Network {
|
||||
method,
|
||||
error,
|
||||
args: sendArgs,
|
||||
headers,
|
||||
request: this,
|
||||
status: this.status || 'CONN ERR',
|
||||
});
|
||||
})
|
||||
const proxiedSend = this.send;
|
||||
const proxiedSetRequestHeader = this.setRequestHeader;
|
||||
this.send = function proxySend (...sendargs) {
|
||||
sendArgs = sendargs;
|
||||
return proxiedSend.apply(this, [].slice.call(arguments));
|
||||
}
|
||||
this.setRequestHeader = function (name, value) {
|
||||
headers[name] = value;
|
||||
return proxiedSetRequestHeader.apply(this, [].slice.call(arguments));
|
||||
}
|
||||
return proxied.apply(this, [].slice.call(arguments));
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user