Skip to content
78 changes: 8 additions & 70 deletions packages/react-native/Libraries/LogBox/UI/LogBoxInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,37 @@
*/

import Keyboard from '../../Components/Keyboard/Keyboard';
import ScrollView from '../../Components/ScrollView/ScrollView';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import * as LogBoxData from '../Data/LogBoxData';
import LogBoxLog, {type LogLevel} from '../Data/LogBoxLog';
import LogBoxInspectorCodeFrame from './LogBoxInspectorCodeFrame';
import LogBoxInspectorBody from './LogBoxInspectorBody';
import LogBoxInspectorFooter from './LogBoxInspectorFooter';
import LogBoxInspectorHeader from './LogBoxInspectorHeader';
import LogBoxInspectorMessageHeader from './LogBoxInspectorMessageHeader';
import LogBoxInspectorReactFrames from './LogBoxInspectorReactFrames';
import LogBoxInspectorStackFrames from './LogBoxInspectorStackFrames';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';
import {useEffect} from 'react';

type Props = $ReadOnly<{|
type Props = $ReadOnly<{
onDismiss: () => void,
onChangeSelectedIndex: (index: number) => void,
onMinimize: () => void,
logs: $ReadOnlyArray<LogBoxLog>,
selectedIndex: number,
fatalType?: ?LogLevel,
|}>;
}>;

function LogBoxInspector(props: Props): React.Node {
export default function LogBoxInspector(props: Props): React.Node {
const {logs, selectedIndex} = props;
let log = logs[selectedIndex];

React.useEffect(() => {
useEffect(() => {
if (log) {
LogBoxData.symbolicateLogNow(log);
}
}, [log]);

React.useEffect(() => {
useEffect(() => {
// Optimistically symbolicate the last and next logs.
if (logs.length > 1) {
const selected = selectedIndex;
Expand All @@ -54,7 +51,7 @@ function LogBoxInspector(props: Props): React.Node {
}
}, [logs, selectedIndex]);

React.useEffect(() => {
useEffect(() => {
Keyboard.dismiss();
}, []);

Expand Down Expand Up @@ -84,68 +81,9 @@ function LogBoxInspector(props: Props): React.Node {
);
}

const headerTitleMap = {
warn: 'Console Warning',
error: 'Console Error',
fatal: 'Uncaught Error',
syntax: 'Syntax Error',
component: 'Render Error',
};

function LogBoxInspectorBody(props: {log: LogBoxLog, onRetry: () => void}) {
const [collapsed, setCollapsed] = React.useState(true);

React.useEffect(() => {
setCollapsed(true);
}, [props.log]);

const headerTitle =
props.log.type ??
headerTitleMap[props.log.isComponentError ? 'component' : props.log.level];

if (collapsed) {
return (
<>
<LogBoxInspectorMessageHeader
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
message={props.log.message}
level={props.log.level}
title={headerTitle}
/>
<ScrollView style={styles.scrollBody}>
<LogBoxInspectorCodeFrame codeFrame={props.log.codeFrame} />
<LogBoxInspectorReactFrames log={props.log} />
<LogBoxInspectorStackFrames log={props.log} onRetry={props.onRetry} />
</ScrollView>
</>
);
}
return (
<ScrollView style={styles.scrollBody}>
<LogBoxInspectorMessageHeader
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
message={props.log.message}
level={props.log.level}
title={headerTitle}
/>
<LogBoxInspectorCodeFrame codeFrame={props.log.codeFrame} />
<LogBoxInspectorReactFrames log={props.log} />
<LogBoxInspectorStackFrames log={props.log} onRetry={props.onRetry} />
</ScrollView>
);
}

const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: LogBoxStyle.getTextColor(),
},
scrollBody: {
backgroundColor: LogBoxStyle.getBackgroundColor(0.9),
flex: 1,
},
});

export default LogBoxInspector;
87 changes: 87 additions & 0 deletions packages/react-native/Libraries/LogBox/UI/LogBoxInspectorBody.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

import ScrollView from '../../Components/ScrollView/ScrollView';
import StyleSheet from '../../StyleSheet/StyleSheet';
import LogBoxLog from '../Data/LogBoxLog';
import LogBoxInspectorCodeFrame from './LogBoxInspectorCodeFrame';
import LogBoxInspectorMessageHeader from './LogBoxInspectorMessageHeader';
import LogBoxInspectorReactFrames from './LogBoxInspectorReactFrames';
import LogBoxInspectorStackFrames from './LogBoxInspectorStackFrames';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';
import {useEffect, useState} from 'react';

const headerTitleMap = {
warn: 'Console Warning',
error: 'Console Error',
fatal: 'Uncaught Error',
syntax: 'Syntax Error',
component: 'Render Error',
};

export default function LogBoxInspectorBody(props: {
log: LogBoxLog,
onRetry: () => void,
}): React.Node {
const [collapsed, setCollapsed] = useState(true);

useEffect(() => {
setCollapsed(true);
}, [props.log]);

const headerTitle =
props.log.type ??
headerTitleMap[props.log.isComponentError ? 'component' : props.log.level];

if (collapsed) {
return (
<>
<LogBoxInspectorMessageHeader
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
message={props.log.message}
level={props.log.level}
title={headerTitle}
/>
<ScrollView style={styles.scrollBody}>
<LogBoxInspectorCodeFrame codeFrame={props.log.codeFrame} />
<LogBoxInspectorReactFrames log={props.log} />
<LogBoxInspectorStackFrames log={props.log} onRetry={props.onRetry} />
</ScrollView>
</>
);
}
return (
<ScrollView style={styles.scrollBody}>
<LogBoxInspectorMessageHeader
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
message={props.log.message}
level={props.log.level}
title={headerTitle}
/>
<LogBoxInspectorCodeFrame codeFrame={props.log.codeFrame} />
<LogBoxInspectorReactFrames log={props.log} />
<LogBoxInspectorStackFrames log={props.log} onRetry={props.onRetry} />
</ScrollView>
);
}

const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: LogBoxStyle.getTextColor(),
},
scrollBody: {
backgroundColor: LogBoxStyle.getBackgroundColor(0.9),
flex: 1,
},
});
48 changes: 6 additions & 42 deletions packages/react-native/Libraries/LogBox/UI/LogBoxInspectorFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@

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

import SafeAreaView from '../../Components/SafeAreaView/SafeAreaView';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import LogBoxButton from './LogBoxButton';
import LogBoxInspectorFooterButton from './LogBoxInspectorFooterButton';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';

type Props = $ReadOnly<{|
type Props = $ReadOnly<{
onDismiss: () => void,
onMinimize: () => void,
level?: ?LogLevel,
|}>;
}>;

function LogBoxInspectorFooter(props: Props): React.Node {
export default function LogBoxInspectorFooter(props: Props): React.Node {
if (props.level === 'syntax') {
return (
<View style={styles.root}>
Expand All @@ -39,34 +38,12 @@ function LogBoxInspectorFooter(props: Props): React.Node {

return (
<View style={styles.root}>
<FooterButton text="Dismiss" onPress={props.onDismiss} />
<FooterButton text="Minimize" onPress={props.onMinimize} />
<LogBoxInspectorFooterButton text="Dismiss" onPress={props.onDismiss} />
<LogBoxInspectorFooterButton text="Minimize" onPress={props.onMinimize} />
</View>
);
}

type ButtonProps = $ReadOnly<{|
onPress: () => void,
text: string,
|}>;

function FooterButton(props: ButtonProps): React.Node {
return (
<SafeAreaView style={styles.button}>
<LogBoxButton
backgroundColor={{
default: 'transparent',
pressed: LogBoxStyle.getBackgroundDarkColor(),
}}
onPress={props.onPress}>
<View style={styles.buttonContent}>
<Text style={styles.buttonLabel}>{props.text}</Text>
</View>
</LogBoxButton>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
root: {
backgroundColor: LogBoxStyle.getBackgroundColor(1),
Expand All @@ -79,17 +56,6 @@ const styles = StyleSheet.create({
button: {
flex: 1,
},
buttonContent: {
alignItems: 'center',
height: 48,
justifyContent: 'center',
},
buttonLabel: {
color: LogBoxStyle.getTextColor(1),
fontSize: 14,
includeFontPadding: false,
lineHeight: 20,
},
syntaxErrorText: {
textAlign: 'center',
width: '100%',
Expand All @@ -102,5 +68,3 @@ const styles = StyleSheet.create({
color: LogBoxStyle.getTextColor(0.6),
},
});

export default LogBoxInspectorFooter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

import SafeAreaView from '../../Components/SafeAreaView/SafeAreaView';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';

type ButtonProps = $ReadOnly<{
onPress: () => void,
text: string,
}>;

export default function LogBoxInspectorFooterButton(
props: ButtonProps,
): React.Node {
return (
<SafeAreaView style={styles.button}>
<LogBoxButton
backgroundColor={{
default: 'transparent',
pressed: LogBoxStyle.getBackgroundDarkColor(),
}}
onPress={props.onPress}>
<View style={styles.buttonContent}>
<Text style={styles.buttonLabel}>{props.text}</Text>
</View>
</LogBoxButton>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
button: {
flex: 1,
},
buttonContent: {
alignItems: 'center',
height: 48,
justifyContent: 'center',
},
buttonLabel: {
color: LogBoxStyle.getTextColor(1),
fontSize: 14,
includeFontPadding: false,
lineHeight: 20,
},
});
Loading