Skip to content

Commit

Permalink
LogBox - Display errors for notifications and inspector
Browse files Browse the repository at this point in the history
Summary:
This diff adds and displays errors in LogBox. We will now toast both warnings and errors, open errors for inspection, and allow paginating through errors and warnings.

Changelog: [Internal]

Reviewed By: cpojer

Differential Revision: D18091519

fbshipit-source-id: c155969dc505de5cfb0e95bb5a8221b9f8cfe4f7
  • Loading branch information
rickhanlonii authored and facebook-github-bot committed Oct 28, 2019
1 parent c5aa26d commit 3c525d5
Show file tree
Hide file tree
Showing 13 changed files with 527 additions and 70 deletions.
64 changes: 42 additions & 22 deletions Libraries/LogBox/UI/LogBoxContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ function LogBoxContainer(props: Props): React.Node {

const logs = Array.from(props.logs);

function getVisibleLog() {
// TODO: currently returns the newest log but later will need to return
// the newest log of the highest level. For example, we want to show
// the latest error message even if there are newer warnings.
return logs[logs.length - 1];
}

function handleInspectorDismissAll() {
props.onDismissAll();
}
Expand All @@ -59,8 +52,12 @@ function LogBoxContainer(props: Props): React.Node {
setSelectedLog(null);
}

function handleRowPress(index: number) {
setSelectedLog(logs.length - 1);
function openLog(log: LogBoxLog) {
let index = logs.length - 1;
while (index > 0 && logs[index] !== log) {
index -= 1;
}
setSelectedLog(index);
}

if (selectedLogIndex != null) {
Expand All @@ -77,20 +74,42 @@ function LogBoxContainer(props: Props): React.Node {
);
}

return logs.length === 0 ? null : (
if (logs.length === 0) {
return null;
}

const warnings = logs.filter(log => log.level === 'warn');
const errors = logs.filter(log => log.level === 'error');
return (
<View style={styles.list}>
<View style={styles.toast}>
<LogBoxLogNotification
log={getVisibleLog()}
level="warn"
totalLogCount={logs.length}
onPressOpen={handleRowPress}
onPressList={() => {
/* TODO: open log list */
}}
onPressDismiss={handleInspectorDismissAll}
/>
</View>
{warnings.length > 0 && (
<View style={styles.toast}>
<LogBoxLogNotification
log={warnings[warnings.length - 1]}
level="warn"
totalLogCount={warnings.length}
onPressOpen={() => openLog(warnings[warnings.length - 1])}
onPressList={() => {
/* TODO: open log list */
}}
onPressDismiss={handleInspectorDismissAll}
/>
</View>
)}
{errors.length > 0 && (
<View style={styles.toast}>
<LogBoxLogNotification
log={errors[errors.length - 1]}
level="error"
totalLogCount={errors.length}
onPressOpen={() => openLog(errors[errors.length - 1])}
onPressList={() => {
/* TODO: open log list */
}}
onPressDismiss={handleInspectorDismissAll}
/>
</View>
)}
<SafeAreaView style={styles.safeArea} />
</View>
);
Expand All @@ -105,6 +124,7 @@ const styles = StyleSheet.create({
},
toast: {
borderRadius: 8,
marginBottom: 5,
overflow: 'hidden',
},
safeArea: {
Expand Down
3 changes: 3 additions & 0 deletions Libraries/LogBox/UI/LogBoxInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class LogBoxInspector extends React.Component<Props> {
onSelectIndex={this._handleSelectIndex}
selectedIndex={selectedIndex}
total={logs.length}
level={log.level}
/>
<LogBoxInspectorBody
log={log}
Expand Down Expand Up @@ -113,6 +114,7 @@ function LogBoxInspectorBody(props) {
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
message={props.log.message}
level={props.log.level}
/>
<ScrollView style={styles.scrollBody}>
<LogBoxInspectorReactFrames log={props.log} />
Expand All @@ -128,6 +130,7 @@ function LogBoxInspectorBody(props) {
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
message={props.log.message}
level={props.log.level}
/>
<LogBoxInspectorReactFrames log={props.log} />
<LogBoxInspectorStackFrames log={props.log} onRetry={props.onRetry} />
Expand Down
25 changes: 19 additions & 6 deletions Libraries/LogBox/UI/LogBoxInspectorHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import View from '../../Components/View/View';
import LogBoxImageSource from './LogBoxImageSource';
import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';

import type {LogLevel} from '../Data/LogBoxLog';
type Props = $ReadOnly<{|
onSelectIndex: (selectedIndex: number) => void,
selectedIndex: number,
total: number,
level: LogLevel,
|}>;

function LogBoxInspectorHeader(props: Props): React.Node {
Expand All @@ -37,10 +38,11 @@ function LogBoxInspectorHeader(props: Props): React.Node {
: `Log ${props.selectedIndex + 1} of ${props.total}`;

return (
<SafeAreaView style={styles.root}>
<SafeAreaView style={styles[props.level]}>
<View style={styles.header}>
<LogBoxInspectorHeaderButton
disabled={prevIndex < 0}
level={props.level}
image={LogBoxImageSource.chevronLeft}
onPress={() => props.onSelectIndex(prevIndex)}
/>
Expand All @@ -49,6 +51,7 @@ function LogBoxInspectorHeader(props: Props): React.Node {
</View>
<LogBoxInspectorHeaderButton
disabled={nextIndex >= props.total}
level={props.level}
image={LogBoxImageSource.chevronRight}
onPress={() => props.onSelectIndex(nextIndex)}
/>
Expand All @@ -61,14 +64,21 @@ function LogBoxInspectorHeaderButton(
props: $ReadOnly<{|
disabled: boolean,
image: string,
level: LogLevel,
onPress?: ?() => void,
|}>,
): React.Node {
return (
<LogBoxButton
backgroundColor={{
default: LogBoxStyle.getWarningColor(),
pressed: LogBoxStyle.getWarningDarkColor(),
default:
props.level === 'warn'
? LogBoxStyle.getWarningColor()
: LogBoxStyle.getErrorColor(),
pressed:
props.level === 'warn'
? LogBoxStyle.getWarningDarkColor()
: LogBoxStyle.getErrorDarkColor(),
}}
onPress={props.disabled ? null : props.onPress}
style={headerStyles.button}>
Expand Down Expand Up @@ -99,8 +109,11 @@ const headerStyles = StyleSheet.create({
});

const styles = StyleSheet.create({
root: {
backgroundColor: LogBoxStyle.getWarningColor(1),
warn: {
backgroundColor: LogBoxStyle.getWarningColor(),
},
error: {
backgroundColor: LogBoxStyle.getErrorColor(),
},
header: {
flexDirection: 'row',
Expand Down
14 changes: 11 additions & 3 deletions Libraries/LogBox/UI/LogBoxInspectorMessageHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import View from '../../Components/View/View';
import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';
import LogBoxMessage from './LogBoxMessage';

import type {LogLevel} from '../Data/LogBoxLog';
import type {Message} from '../Data/parseLogBoxLog';

type Props = $ReadOnly<{|
collapsed: boolean,
message: Message,
level: LogLevel,
onPress: () => void,
|}>;

Expand All @@ -49,7 +50,9 @@ function LogBoxInspectorMessageHeader(props: Props): React.Node {
return (
<View style={messageStyles.body}>
<View style={messageStyles.heading}>
<Text style={messageStyles.headingText}>Warning</Text>
<Text style={[messageStyles.headingText, messageStyles[props.level]]}>
{props.level === 'warn' ? 'Warning' : 'Error'}
</Text>
{renderShowMore()}
</View>
<Text
Expand Down Expand Up @@ -91,13 +94,18 @@ const messageStyles = StyleSheet.create({
marginBottom: 5,
},
headingText: {
color: LogBoxStyle.getWarningColor(1),
flex: 1,
fontSize: 20,
fontWeight: '600',
includeFontPadding: false,
lineHeight: 28,
},
warn: {
color: LogBoxStyle.getWarningColor(1),
},
error: {
color: LogBoxStyle.getErrorColor(1),
},
messageText: {
color: LogBoxStyle.getTextColor(0.6),
},
Expand Down
4 changes: 4 additions & 0 deletions Libraries/LogBox/UI/LogBoxStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export function getErrorColor(opacity?: number): string {
return `rgba(243, 83, 105, ${opacity == null ? 1 : opacity})`;
}

export function getErrorDarkColor(opacity?: number): string {
return `rgba(208, 75, 95, ${opacity == null ? 1 : opacity})`;
}

export function getLogColor(opacity?: number): string {
return `rgba(119, 119, 119, ${opacity == null ? 1 : opacity})`;
}
Expand Down
72 changes: 71 additions & 1 deletion Libraries/LogBox/UI/__tests__/LogBoxContainer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('LogBoxContainer', () => {
expect(output).toMatchSnapshot();
});

it('should render the latest log', () => {
it('should render the latest warning', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
Expand Down Expand Up @@ -63,4 +63,74 @@ describe('LogBoxContainer', () => {

expect(output).toMatchSnapshot();
});

it('should render the latest error', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissAll={() => {}}
logs={
new Set([
new LogBoxLog(
'error',
{
content: 'Some kind of message',
substitutions: [],
},
[],
'Some kind of message',
[],
),
new LogBoxLog(
'error',
{
content: 'Some kind of message (latest)',
substitutions: [],
},
[],
'Some kind of message (latest)',
[],
),
])
}
/>,
);

expect(output).toMatchSnapshot();
});

it('should render both an error and warning', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissAll={() => {}}
logs={
new Set([
new LogBoxLog(
'warn',
{
content: 'Some kind of message',
substitutions: [],
},
[],
'Some kind of message',
[],
),
new LogBoxLog(
'error',
{
content: 'Some kind of message (latest)',
substitutions: [],
},
[],
'Some kind of message (latest)',
[],
),
])
}
/>,
);

expect(output).toMatchSnapshot();
});
});
6 changes: 3 additions & 3 deletions Libraries/LogBox/UI/__tests__/LogBoxInspector-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const logs = [
[],
),
new LogBoxLog(
'warn',
'error',
{
content: 'Some kind of message (second)',
substitutions: [],
Expand All @@ -54,7 +54,7 @@ describe('LogBoxContainer', () => {
expect(output).toMatchSnapshot();
});

it('should render first log with selectedIndex 0', () => {
it('should render warning with selectedIndex 0', () => {
const output = render.shallowRender(
<LogBoxInspector
onDismiss={() => {}}
Expand All @@ -68,7 +68,7 @@ describe('LogBoxContainer', () => {
expect(output).toMatchSnapshot();
});

it('should render second log with selectedIndex 1', () => {
it('should render error with selectedIndex 1', () => {
const output = render.shallowRender(
<LogBoxInspector
onDismiss={() => {}}
Expand Down
Loading

0 comments on commit 3c525d5

Please sign in to comment.