mirror of
https://github.com/morten-olsen/react-native-debug-console.git
synced 2026-02-08 00:36:26 +01:00
Misc
This commit is contained in:
@@ -14,10 +14,12 @@ import {
|
|||||||
log,
|
log,
|
||||||
network,
|
network,
|
||||||
show,
|
show,
|
||||||
|
context,
|
||||||
} from 'react-native-debug-console';
|
} from 'react-native-debug-console';
|
||||||
|
|
||||||
network.attach();
|
network.attach();
|
||||||
log.attach();
|
log.attach();
|
||||||
|
context.hello = () => 'earth';
|
||||||
|
|
||||||
console.log('fooo');
|
console.log('fooo');
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
@@ -105,11 +107,11 @@ export default class App extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<View style={{ height: 10 }} />
|
<View style={{ height: 10 }} />
|
||||||
</View>
|
</View>
|
||||||
<DevTool
|
{/* <DevTool
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}}
|
}}
|
||||||
/>
|
/> */}
|
||||||
<DevToolModal />
|
<DevToolModal />
|
||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-native-debug-console",
|
"name": "react-native-debug-console",
|
||||||
"version": "1.0.0-beta.12",
|
"version": "1.0.0-beta.13",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "https://github.com/morten-olsen/react-native-debugger"
|
"url": "https://github.com/morten-olsen/react-native-debugger"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import styled from 'styled-components/native';
|
import styled from 'styled-components/native';
|
||||||
import State from '../../data/State';
|
import State from '../../data/State';
|
||||||
|
import { context } from '../../../console';
|
||||||
import log from '../../../log';
|
import log from '../../../log';
|
||||||
import Icon from '../../base/Icon';
|
import Icon from '../../base/Icon';
|
||||||
|
|
||||||
@@ -86,8 +87,8 @@ const Input = ({
|
|||||||
<Button
|
<Button
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
const newHistory = [...history, text];
|
const newHistory = [...history, text];
|
||||||
const contextKeys = Object.keys(log.context);
|
const contextKeys = Object.keys(context);
|
||||||
const contextValues = Object.values(log.context);
|
const contextValues = Object.values(context);
|
||||||
const fn = new Function(...contextKeys, text);
|
const fn = new Function(...contextKeys, text);
|
||||||
try {
|
try {
|
||||||
fn(...contextValues);
|
fn(...contextValues);
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ const OutputList = ({
|
|||||||
const Console = ({
|
const Console = ({
|
||||||
logs,
|
logs,
|
||||||
includeStackTrace,
|
includeStackTrace,
|
||||||
|
filter = [],
|
||||||
}) => (
|
}) => (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
ref={ref => this.scrollView = ref}
|
ref={ref => this.scrollView = ref}
|
||||||
@@ -109,7 +110,7 @@ const Console = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{logs.map((log, i) => (
|
{logs.filter(l => filter.includes(l.type)).map((log, i) => (
|
||||||
<Row key={i}>
|
<Row key={i}>
|
||||||
<Emphasis color={getColor(log.type)}>
|
<Emphasis color={getColor(log.type)}>
|
||||||
{log.type}
|
{log.type}
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Clipboard,
|
|
||||||
Alert,
|
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import log from '../../../log';
|
import log from '../../../log';
|
||||||
import Log from '../../data/Log';
|
import Log from '../../data/Log';
|
||||||
import Toolbar from '../../base/Toolbar';
|
import State from '../../data/State';
|
||||||
|
import Toolbar, {
|
||||||
|
Button,
|
||||||
|
Selector,
|
||||||
|
Seperator,
|
||||||
|
} from '../../base/Toolbar';
|
||||||
import Output from './Output';
|
import Output from './Output';
|
||||||
import Input from './Input';
|
import Input from './Input';
|
||||||
|
|
||||||
@@ -17,32 +20,54 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const initFilters = [
|
||||||
|
'error',
|
||||||
|
'warn',
|
||||||
|
'info',
|
||||||
|
'debug',
|
||||||
|
].map(i => ({
|
||||||
|
name: i,
|
||||||
|
value: i,
|
||||||
|
selected: true,
|
||||||
|
}))
|
||||||
|
|
||||||
const Console = ({
|
const Console = ({
|
||||||
includeStackTrace,
|
includeStackTrace,
|
||||||
}) => (
|
}) => (
|
||||||
<Log>
|
<Log>
|
||||||
{({ logs }) => (
|
{({ logs }) => (
|
||||||
|
<State
|
||||||
|
initState={{
|
||||||
|
filters: initFilters,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ filters }, setState) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Toolbar
|
<Toolbar>
|
||||||
items={[{
|
<Selector
|
||||||
name: 'Download',
|
name="Filter"
|
||||||
icon: 'download',
|
icon="filter"
|
||||||
onPress: () => {
|
options={filters}
|
||||||
Clipboard.setString(JSON.stringify(logs, null, ' '));
|
multiSelect
|
||||||
Alert.alert(
|
onSelect={(selected) => {
|
||||||
'Copied to clipboard',
|
setState({
|
||||||
);
|
filters: selected,
|
||||||
},
|
});
|
||||||
}, {
|
}}
|
||||||
name: 'Clear',
|
|
||||||
icon: 'trash',
|
|
||||||
onPress: () => log.clear(),
|
|
||||||
}]}
|
|
||||||
/>
|
/>
|
||||||
<Output logs={logs} includeStackTrace={includeStackTrace} />
|
<Seperator />
|
||||||
|
<Button
|
||||||
|
name="Clear"
|
||||||
|
icon="trash"
|
||||||
|
onPress={() => log.clear()}
|
||||||
|
/>
|
||||||
|
</Toolbar>
|
||||||
|
<Output filter={filters.filter(f => f.selected).map(f => f.name)} logs={logs} includeStackTrace={includeStackTrace} />
|
||||||
<Input />
|
<Input />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
</State>
|
||||||
|
)}
|
||||||
</Log>
|
</Log>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import CellHeader from '../../base/CellHeader';
|
|||||||
import Tab from '../Tab';
|
import Tab from '../Tab';
|
||||||
|
|
||||||
const WebView = styled.WebView`
|
const WebView = styled.WebView`
|
||||||
background: red;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
@@ -42,11 +41,10 @@ const Indented = styled.View`
|
|||||||
margin: 0 25px;
|
margin: 0 25px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const getResponse = (request) => {
|
const getResponse = (contentType, request) => {
|
||||||
if (request.responseType == 'blob' || request.responseType == 'ArrayBuffer') {
|
if (request.responseType == 'blob' || request.responseType == 'ArrayBuffer') {
|
||||||
return <Emphasis>🤖 Binary</Emphasis>
|
return <Emphasis>🤖 Binary</Emphasis>
|
||||||
}
|
}
|
||||||
const contentType = request.getResponseHeader('content-type') || '';
|
|
||||||
const contentTypes = contentType.split(';').map(c => c.trim());
|
const contentTypes = contentType.split(';').map(c => c.trim());
|
||||||
|
|
||||||
if (contentTypes.includes('application/json')) {
|
if (contentTypes.includes('application/json')) {
|
||||||
@@ -57,12 +55,13 @@ const getResponse = (request) => {
|
|||||||
return <Fixed selectable={true}>{request.responseText}</Fixed>;
|
return <Fixed selectable={true}>{request.responseText}</Fixed>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
const Data = ({
|
const Data = ({
|
||||||
url,
|
url,
|
||||||
method,
|
method,
|
||||||
status,
|
status,
|
||||||
headers,
|
headers,
|
||||||
request,
|
requestHeaders,
|
||||||
args = [],
|
args = [],
|
||||||
}) => {
|
}) => {
|
||||||
const headerInfo = Object.keys(headers).map(key => `${key}: ${headers[key]}`).join('\n');
|
const headerInfo = Object.keys(headers).map(key => `${key}: ${headers[key]}`).join('\n');
|
||||||
@@ -73,7 +72,7 @@ const Data = ({
|
|||||||
<Cell left="Method" right={method} />
|
<Cell left="Method" right={method} />
|
||||||
<Cell left="Url" right={url} />
|
<Cell left="Url" right={url} />
|
||||||
<CellHeader>Response Headers</CellHeader>
|
<CellHeader>Response Headers</CellHeader>
|
||||||
<Indented><Fixed>{request.getAllResponseHeaders()}</Fixed></Indented>
|
<Indented><Fixed>{requestHeaders}</Fixed></Indented>
|
||||||
{headerInfo && (
|
{headerInfo && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<CellHeader>Request Headers</CellHeader>
|
<CellHeader>Request Headers</CellHeader>
|
||||||
@@ -92,21 +91,21 @@ const Data = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Response = ({
|
const Response = ({
|
||||||
|
contentType,
|
||||||
request,
|
request,
|
||||||
}) => (
|
}) => (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View>
|
<View>
|
||||||
{getResponse(request)}
|
{getResponse(contentType, request)}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const getPreview = (request, url) => {
|
const getPreview = (contentType, request, url) => {
|
||||||
if (request.responseType == 'blob' || request.responseType == 'ArrayBuffer') {
|
if (request.responseType == 'blob' || request.responseType == 'ArrayBuffer') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const contentType = request.getResponseHeader('content-type') || '';
|
|
||||||
const contentTypes = contentType.split(';').map(c => c.trim());
|
const contentTypes = contentType.split(';').map(c => c.trim());
|
||||||
|
|
||||||
if (contentTypes.includes('text/html')) {
|
if (contentTypes.includes('text/html')) {
|
||||||
@@ -134,7 +133,7 @@ const RequestDetails = (props) => (
|
|||||||
}, {
|
}, {
|
||||||
name: 'Response',
|
name: 'Response',
|
||||||
view: <Response {...props} />
|
view: <Response {...props} />
|
||||||
}, ...getPreview(props.request, props.url)]}
|
}, ...getPreview(props.contentType, props.request, props.url)]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ import React from 'react';
|
|||||||
import {
|
import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
Clipboard,
|
|
||||||
Alert,
|
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import network from '../../../network';
|
import network from '../../../network';
|
||||||
import State from '../../data/State';
|
import State from '../../data/State';
|
||||||
import Network from '../../data/Network';
|
import Network from '../../data/Network';
|
||||||
import Toolbar from '../../base/Toolbar';
|
import Toolbar, {
|
||||||
|
Button,
|
||||||
|
Seperator,
|
||||||
|
} from '../../base/Toolbar';
|
||||||
import Details from './Details';
|
import Details from './Details';
|
||||||
import List from './List';
|
import List from './List';
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@ const styles = StyleSheet.create({
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
let i = 0;
|
||||||
const Console = () => (
|
const Console = () => (
|
||||||
<State>
|
<State>
|
||||||
{({
|
{({
|
||||||
@@ -38,22 +37,14 @@ const Console = () => (
|
|||||||
const selected = active >= 0 ? requests[active] : undefined;
|
const selected = active >= 0 ? requests[active] : undefined;
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Toolbar
|
<Toolbar>
|
||||||
items={[{
|
<Seperator />
|
||||||
name: 'Download',
|
<Button
|
||||||
icon: 'download',
|
name="Clear"
|
||||||
onPress: () => {
|
icon="trash"
|
||||||
Clipboard.setString(JSON.stringify(requests, null, ' '));
|
onPress={() => network.clear()}
|
||||||
Alert.alert(
|
|
||||||
'Copied to clipboard',
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: 'Clear',
|
|
||||||
icon: 'trash',
|
|
||||||
onPress: () => network.clear(),
|
|
||||||
}]}
|
|
||||||
/>
|
/>
|
||||||
|
</Toolbar>
|
||||||
<List
|
<List
|
||||||
selected={selected ? selected.id : undefined}
|
selected={selected ? selected.id : undefined}
|
||||||
requests={requests}
|
requests={requests}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const Keys = ({
|
|||||||
<Wrapper>
|
<Wrapper>
|
||||||
{keys.map(key => (
|
{keys.map(key => (
|
||||||
<Button
|
<Button
|
||||||
key={key}
|
key={key || '[unknown]'}
|
||||||
onPress={() => onSelect(key)}
|
onPress={() => onSelect(key)}
|
||||||
>
|
>
|
||||||
<Row
|
<Row
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components/native';
|
import styled from 'styled-components/native';
|
||||||
import {
|
|
||||||
Clipboard,
|
|
||||||
Alert,
|
|
||||||
} from 'react-native';
|
|
||||||
import Storage from '../../data/Storage';
|
import Storage from '../../data/Storage';
|
||||||
import State from '../../data/State';
|
import State from '../../data/State';
|
||||||
import Toolbar from '../../base/Toolbar';
|
import Toolbar, {
|
||||||
|
Button,
|
||||||
|
Seperator,
|
||||||
|
} from '../../base/Toolbar';
|
||||||
import Keys from './Keys';
|
import Keys from './Keys';
|
||||||
import Value from './Value';
|
import Value from './Value';
|
||||||
|
|
||||||
@@ -20,31 +19,25 @@ const StorageView = () => (
|
|||||||
<Storage>
|
<Storage>
|
||||||
{(data, update, removeItem, clear) => (
|
{(data, update, removeItem, clear) => (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Toolbar
|
<Toolbar>
|
||||||
items={[{
|
<Seperator />
|
||||||
name: 'Download',
|
<Button
|
||||||
icon: 'download',
|
name="Refresh"
|
||||||
onPress: () => {
|
icon="reload"
|
||||||
Clipboard.setString(JSON.stringify(data, null, ' '));
|
onPress={update}
|
||||||
Alert.alert(
|
|
||||||
'Copied to clipboard',
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: 'Refresh',
|
|
||||||
icon: 'reload',
|
|
||||||
onPress: update,
|
|
||||||
}, {
|
|
||||||
name: 'Clear',
|
|
||||||
icon: 'trash',
|
|
||||||
onPress: clear,
|
|
||||||
}, {
|
|
||||||
name: 'Delete',
|
|
||||||
icon: 'remove',
|
|
||||||
disabled: !selected,
|
|
||||||
onPress: () => removeItem(selected),
|
|
||||||
}]}
|
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
name="Clear"
|
||||||
|
icon="trash"
|
||||||
|
onPress={clear}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
name="Delete"
|
||||||
|
icon="remove"
|
||||||
|
disabled={!selected}
|
||||||
|
onPress={() => removeItem(selected)}
|
||||||
|
/>
|
||||||
|
</Toolbar>
|
||||||
<Keys
|
<Keys
|
||||||
selected={selected}
|
selected={selected}
|
||||||
onSelect={(key) => setState({ selected: key })}
|
onSelect={(key) => setState({ selected: key })}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const Console = ({
|
|||||||
tabs,
|
tabs,
|
||||||
buttons = [],
|
buttons = [],
|
||||||
onClose,
|
onClose,
|
||||||
|
onDownload,
|
||||||
}) => (
|
}) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<State
|
<State
|
||||||
@@ -66,7 +67,13 @@ const Console = ({
|
|||||||
<Text>{name}</Text>
|
<Text>{name}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
))}
|
))}
|
||||||
|
{onDownload && (
|
||||||
|
<Button
|
||||||
|
onPress={onDownload}
|
||||||
|
>
|
||||||
|
<Icon name="download" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{onClose && (
|
{onClose && (
|
||||||
<Button
|
<Button
|
||||||
onPress={onClose}
|
onPress={onClose}
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ import React from 'react';
|
|||||||
import {
|
import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
|
Alert,
|
||||||
|
Clipboard,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import Tab from './Tab';
|
import Tab from './Tab';
|
||||||
import Console from './Console';
|
import Console from './Console';
|
||||||
import Requests from './Requests';
|
import Requests from './Requests';
|
||||||
import Storage from './Storage';
|
import Storage from './Storage';
|
||||||
|
import log from '../../log';
|
||||||
|
import network from '../../network';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
@@ -18,22 +22,65 @@ const DevTool = ({
|
|||||||
style,
|
style,
|
||||||
includeStackTrace,
|
includeStackTrace,
|
||||||
onClose,
|
onClose,
|
||||||
}) => (
|
showNetwork = true,
|
||||||
<View style={style || styles.container}>
|
showStorage = true,
|
||||||
<Tab
|
showConsole = true,
|
||||||
tabs={[{
|
additionTools = [],
|
||||||
|
}) => {
|
||||||
|
const views = [];
|
||||||
|
|
||||||
|
if (showConsole) {
|
||||||
|
views.push({
|
||||||
name: 'Console',
|
name: 'Console',
|
||||||
view: <Console includeStackTrace={includeStackTrace} />,
|
view: <Console includeStackTrace={includeStackTrace} />,
|
||||||
}, {
|
getData: log.get,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showNetwork) {
|
||||||
|
views.push({
|
||||||
name: 'Network',
|
name: 'Network',
|
||||||
view: <Requests />,
|
view: <Requests />,
|
||||||
}, {
|
getData: network.get,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showStorage) {
|
||||||
|
views.push({
|
||||||
name: 'Storage',
|
name: 'Storage',
|
||||||
view: <Storage />,
|
view: <Storage />,
|
||||||
}]}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
additionTools.forEach(tool => {
|
||||||
|
views.push(tool);
|
||||||
|
});
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const result = {};
|
||||||
|
for (let i = 0; i < views.length; i++) {
|
||||||
|
const view = views[i];
|
||||||
|
|
||||||
|
if (view.getData) {
|
||||||
|
result[view.name] = await view.getData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Clipboard.setString(JSON.stringify(result, null, ' '));
|
||||||
|
Alert.alert(
|
||||||
|
'Copied to clipboard',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={style || styles.container}>
|
||||||
|
<Tab
|
||||||
|
tabs={views}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
|
onDownload={getData}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default DevTool;
|
export default DevTool;
|
||||||
|
|||||||
BIN
lib/src/components/base/Icon/check.png
Normal file
BIN
lib/src/components/base/Icon/check.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
BIN
lib/src/components/base/Icon/filter.png
Normal file
BIN
lib/src/components/base/Icon/filter.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
@@ -9,6 +9,9 @@ import left from './left.png';
|
|||||||
import play from './play.png';
|
import play from './play.png';
|
||||||
import download from './download.png';
|
import download from './download.png';
|
||||||
import close from './close.png';
|
import close from './close.png';
|
||||||
|
import filter from './filter.png';
|
||||||
|
import square from './square.png';
|
||||||
|
import check from './check.png';
|
||||||
|
|
||||||
const icons = {
|
const icons = {
|
||||||
reload,
|
reload,
|
||||||
@@ -19,6 +22,9 @@ const icons = {
|
|||||||
play,
|
play,
|
||||||
download,
|
download,
|
||||||
close,
|
close,
|
||||||
|
filter,
|
||||||
|
square,
|
||||||
|
check,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image = styled.Image`
|
const Image = styled.Image`
|
||||||
|
|||||||
BIN
lib/src/components/base/Icon/square.png
Normal file
BIN
lib/src/components/base/Icon/square.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,47 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components/native';
|
|
||||||
import Icon from './Icon';
|
|
||||||
import {
|
|
||||||
Body,
|
|
||||||
} from './text';
|
|
||||||
|
|
||||||
const Wrapper = styled.View`
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
border-color: #ccc;
|
|
||||||
padding: 0 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Item = styled.TouchableOpacity`
|
|
||||||
padding: 10px 10px;
|
|
||||||
opacity: ${({ disabled }) => disabled ? 0.3 : 1};
|
|
||||||
`
|
|
||||||
|
|
||||||
const Toolbar = ({
|
|
||||||
items = [],
|
|
||||||
}) => (
|
|
||||||
<Wrapper>
|
|
||||||
{items.map(({
|
|
||||||
name,
|
|
||||||
icon,
|
|
||||||
onPress,
|
|
||||||
disabled,
|
|
||||||
}) => (
|
|
||||||
<Item
|
|
||||||
key={name}
|
|
||||||
onPress={disabled ? undefined : onPress}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
{icon ? (
|
|
||||||
<Icon name={icon} />
|
|
||||||
) : (
|
|
||||||
<Body color={disabled ? '#ccc' : undefined}>{name}</Body>
|
|
||||||
)}
|
|
||||||
</Item>
|
|
||||||
))}
|
|
||||||
</Wrapper>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default Toolbar;
|
|
||||||
31
lib/src/components/base/Toolbar/Button.js
Normal file
31
lib/src/components/base/Toolbar/Button.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components/native';
|
||||||
|
import Icon from '../Icon';
|
||||||
|
import {
|
||||||
|
Body,
|
||||||
|
} from '../text';
|
||||||
|
|
||||||
|
const Item = styled.TouchableOpacity`
|
||||||
|
padding: 10px 10px;
|
||||||
|
opacity: ${({ disabled }) => disabled ? 0.3 : 1};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Button = ({
|
||||||
|
name,
|
||||||
|
icon,
|
||||||
|
onPress,
|
||||||
|
disabled,
|
||||||
|
}) => (
|
||||||
|
<Item
|
||||||
|
onPress={disabled ? undefined : onPress}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
{icon ? (
|
||||||
|
<Icon name={icon} />
|
||||||
|
) : (
|
||||||
|
<Body color={disabled ? '#ccc' : undefined}>{name}</Body>
|
||||||
|
)}
|
||||||
|
</Item>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Button;
|
||||||
78
lib/src/components/base/Toolbar/Selector.js
Normal file
78
lib/src/components/base/Toolbar/Selector.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import {
|
||||||
|
SafeAreaView,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from 'react-native';
|
||||||
|
import styled from 'styled-components/native';
|
||||||
|
import State from '../../data/State';
|
||||||
|
import Button from './Button';
|
||||||
|
import Row from '../Row';
|
||||||
|
import Icon from '../Icon';
|
||||||
|
import {
|
||||||
|
Body,
|
||||||
|
} from '../text';
|
||||||
|
|
||||||
|
const Modal = styled.Modal`
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Selector = ({
|
||||||
|
...others,
|
||||||
|
multiSelect = false,
|
||||||
|
onSelect,
|
||||||
|
options = [],
|
||||||
|
}) => (
|
||||||
|
<State>
|
||||||
|
{({ open }, setState) => (
|
||||||
|
<Fragment>
|
||||||
|
<Button
|
||||||
|
{...others}
|
||||||
|
onPress={() => {
|
||||||
|
setState({ open: true })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Modal
|
||||||
|
animationType="slide"
|
||||||
|
transparent={false}
|
||||||
|
visible={!!open}
|
||||||
|
onRequestClose={() => {
|
||||||
|
setState({ open: false })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SafeAreaView
|
||||||
|
forceInset={{ top: 'always', vertical: 'always' }}
|
||||||
|
style={{flex: 1}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
name="Close"
|
||||||
|
icon="close"
|
||||||
|
onPress={() => {
|
||||||
|
setState({ open: false })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{options.map((option) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
if (!multiSelect) {
|
||||||
|
options.forEach(o => o.selected = false);
|
||||||
|
}
|
||||||
|
option.selected = !option.selected
|
||||||
|
onSelect(options);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Row
|
||||||
|
left={(
|
||||||
|
<Icon name={option.selected ? 'check' : 'square'} />
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Body>{option.name}</Body>
|
||||||
|
</Row>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</SafeAreaView>
|
||||||
|
</Modal>
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</State>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Selector;
|
||||||
7
lib/src/components/base/Toolbar/Seperator.js
Normal file
7
lib/src/components/base/Toolbar/Seperator.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import styled from 'styled-components/native';
|
||||||
|
|
||||||
|
const Seperator = styled.View`
|
||||||
|
flex: 1;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Seperator;
|
||||||
29
lib/src/components/base/Toolbar/index.js
Normal file
29
lib/src/components/base/Toolbar/index.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components/native';
|
||||||
|
import Button from './Button';
|
||||||
|
import Seperator from './Seperator';
|
||||||
|
import Selector from './Selector';
|
||||||
|
|
||||||
|
export {
|
||||||
|
Button,
|
||||||
|
Seperator,
|
||||||
|
Selector,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Wrapper = styled.View`
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-color: #ccc;
|
||||||
|
padding: 0 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Toolbar = ({
|
||||||
|
children,
|
||||||
|
}) => (
|
||||||
|
<Wrapper>
|
||||||
|
{children}
|
||||||
|
</Wrapper>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Toolbar;
|
||||||
8
lib/src/console.js
Normal file
8
lib/src/console.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import log from './log';
|
||||||
|
import { AsyncStorage } from 'react-native';
|
||||||
|
|
||||||
|
export const context = {
|
||||||
|
storage: AsyncStorage,
|
||||||
|
log: (...args) => console.log(...args),
|
||||||
|
clear: log.clear,
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ import DevToolModal from './components/DevTool/Modal';
|
|||||||
import log from './log';
|
import log from './log';
|
||||||
import network from './network';
|
import network from './network';
|
||||||
import events from './events';
|
import events from './events';
|
||||||
|
import { context } from './console';
|
||||||
|
|
||||||
const show = () => events.publish('SHOW_DEVTOOLS');
|
const show = () => events.publish('SHOW_DEVTOOLS');
|
||||||
const hide = () => events.publish('HIDE_DEVTOOLS');
|
const hide = () => events.publish('HIDE_DEVTOOLS');
|
||||||
@@ -12,6 +13,7 @@ export {
|
|||||||
DevToolModal,
|
DevToolModal,
|
||||||
log,
|
log,
|
||||||
network,
|
network,
|
||||||
|
context,
|
||||||
show,
|
show,
|
||||||
hide,
|
hide,
|
||||||
};
|
};
|
||||||
@@ -1,16 +1,11 @@
|
|||||||
import { AsyncStorage } from 'react-native';
|
|
||||||
|
|
||||||
export const proxyConsole = window.console;
|
export const proxyConsole = window.console;
|
||||||
|
|
||||||
class Log {
|
class Log {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logs = [];
|
this.logs = [];
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
this.context = {
|
this.clear = this.clear.bind(this);
|
||||||
storage: AsyncStorage,
|
this.get = this.get.bind(this);
|
||||||
log: (...args) => console.log(...args),
|
|
||||||
clear: this.clear.bind(this),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(fn) {
|
listen(fn) {
|
||||||
@@ -27,6 +22,10 @@ class Log {
|
|||||||
this.listeners.forEach(l => l(this.logs));
|
this.listeners.forEach(l => l(this.logs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return this.logs;
|
||||||
|
}
|
||||||
|
|
||||||
log(type, data, keep) {
|
log(type, data, keep) {
|
||||||
const entry = {
|
const entry = {
|
||||||
type,
|
type,
|
||||||
@@ -67,6 +66,7 @@ class Log {
|
|||||||
info: (...data) => this.info(data, keep),
|
info: (...data) => this.info(data, keep),
|
||||||
log: (...data) => this.info(data, keep),
|
log: (...data) => this.info(data, keep),
|
||||||
debug: (...data) => this.debug(data, keep),
|
debug: (...data) => this.debug(data, keep),
|
||||||
|
verbose: (...data) => this.debug(data, keep),
|
||||||
};
|
};
|
||||||
ErrorUtils.setGlobalHandler((err, fatal) => {
|
ErrorUtils.setGlobalHandler((err, fatal) => {
|
||||||
this.error([err], keep);
|
this.error([err], keep);
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ class Network {
|
|||||||
this.requests = [];
|
this.requests = [];
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
this.currentId = 0;
|
this.currentId = 0;
|
||||||
|
// this.clear = this.clear.bind(this);
|
||||||
|
this.get = this.get.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
listen(fn) {
|
listen(fn) {
|
||||||
@@ -12,6 +14,10 @@ class Network {
|
|||||||
fn(this.requests);
|
fn(this.requests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return this.requests;
|
||||||
|
}
|
||||||
|
|
||||||
unlisten(fn) {
|
unlisten(fn) {
|
||||||
this.listeners = this.listeners.filter(l => l !== fn);
|
this.listeners = this.listeners.filter(l => l !== fn);
|
||||||
}
|
}
|
||||||
@@ -44,6 +50,8 @@ class Network {
|
|||||||
method,
|
method,
|
||||||
args: sendArgs,
|
args: sendArgs,
|
||||||
headers,
|
headers,
|
||||||
|
requestHeaders: this.getAllResponseHeaders(),
|
||||||
|
contentType: this.getResponseHeader('content-type') || '',
|
||||||
request: this,
|
request: this,
|
||||||
status: this.status,
|
status: this.status,
|
||||||
});
|
});
|
||||||
@@ -55,6 +63,7 @@ class Network {
|
|||||||
error,
|
error,
|
||||||
args: sendArgs,
|
args: sendArgs,
|
||||||
headers,
|
headers,
|
||||||
|
requestHeaders: this.getAllResponseHeaders(),
|
||||||
request: this,
|
request: this,
|
||||||
status: this.status || 'CONN ERR',
|
status: this.status || 'CONN ERR',
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user