Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react-native/Libraries/LogBox/UI/AnsiHighlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default function Ansi({
<View style={styles.container}>
{parsedLines.map((items, i) => (
<View style={styles.line} key={i}>
<Text style={styles.text}>
<Text selectable={true} style={styles.text}>
{items.map((bundle, key) => {
const textStyle =
bundle.fg && COLORS[bundle.fg]
Expand Down
32 changes: 31 additions & 1 deletion packages/react-native/Libraries/LogBox/UI/LogBoxInspectorBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @format
*/

import Clipboard from '../../Components/Clipboard/Clipboard';
import ScrollView from '../../Components/ScrollView/ScrollView';
import StyleSheet from '../../StyleSheet/StyleSheet';
import LogBoxLog from '../Data/LogBoxLog';
Expand All @@ -17,7 +18,7 @@ import LogBoxInspectorReactFrames from './LogBoxInspectorReactFrames';
import LogBoxInspectorStackFrames from './LogBoxInspectorStackFrames';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';
import {useEffect, useState} from 'react';
import {useCallback, useEffect, useState} from 'react';

const headerTitleMap = {
warn: 'Console Warning',
Expand All @@ -27,6 +28,19 @@ const headerTitleMap = {
component: 'Render Error',
};

function formatStackFrameForCopy(frame: {
methodName: string,
file?: ?string,
lineNumber?: ?number,
column?: ?string | ?number,
...
}): string {
const location = frame.file
? ` (${frame.file}${frame.lineNumber != null ? ':' + frame.lineNumber : ''}${frame.column != null ? ':' + frame.column : ''})`
: '';
return ` at ${frame.methodName}${location}`;
}

export default function LogBoxInspectorBody(props: {
log: LogBoxLog,
onRetry: () => void,
Expand All @@ -41,12 +55,27 @@ export default function LogBoxInspectorBody(props: {
props.log.type ??
headerTitleMap[props.log.isComponentError ? 'component' : props.log.level];

const handleCopy = useCallback(() => {
const log = props.log;
const stack = log.getAvailableStack();

let text = `${headerTitle}\n\n${log.message.content}`;

if (stack.length > 0) {
const stackText = stack.map(formatStackFrameForCopy).join('\n');
text += `\n\n${stackText}`;
}

Clipboard.setString(text);
}, [props.log, headerTitle]);

if (collapsed) {
return (
<>
<LogBoxInspectorMessageHeader
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
onCopy={handleCopy}
message={props.log.message}
level={props.log.level}
title={headerTitle}
Expand All @@ -67,6 +96,7 @@ export default function LogBoxInspectorBody(props: {
<LogBoxInspectorMessageHeader
collapsed={collapsed}
onPress={() => setCollapsed(!collapsed)}
onCopy={handleCopy}
message={props.log.message}
level={props.log.level}
title={headerTitle}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {Message} from '../Data/parseLogBoxLog';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import LogBoxButton from './LogBoxButton';
import LogBoxMessage from './LogBoxMessage';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';
Expand All @@ -24,6 +25,7 @@ type Props = $ReadOnly<{
level: LogLevel,
title: string,
onPress: () => void,
onCopy: () => void,
}>;

const SHOW_MORE_MESSAGE_LENGTH = 300;
Expand All @@ -47,12 +49,25 @@ function LogBoxInspectorMessageHeader(props: Props): React.Node {
<View style={messageStyles.body}>
<View style={messageStyles.heading}>
<Text
selectable={true}
style={[messageStyles.headingText, messageStyles[props.level]]}
id="logbox_message_title_text">
{props.title}
</Text>
<LogBoxButton
backgroundColor={{
default: 'transparent',
pressed: LogBoxStyle.getBackgroundDarkColor(1),
}}
onPress={props.onCopy}
style={messageStyles.copyButton}>
<Text style={messageStyles.copyButtonText}>Copy</Text>
</LogBoxButton>
</View>
<Text style={messageStyles.bodyText} id="logbox_message_contents_text">
<Text
selectable={true}
style={messageStyles.bodyText}
id="logbox_message_contents_text">
<LogBoxMessage
maxLength={props.collapsed ? SHOW_MORE_MESSAGE_LENGTH : Infinity}
message={props.message}
Expand Down Expand Up @@ -122,6 +137,19 @@ const messageStyles = StyleSheet.create({
paddingHorizontal: 10,
borderRadius: 3,
},
copyButton: {
paddingVertical: 4,
paddingHorizontal: 8,
borderRadius: 3,
marginLeft: 8,
},
copyButtonText: {
color: LogBoxStyle.getTextColor(0.6),
fontSize: 12,
fontWeight: '600',
includeFontPadding: false,
lineHeight: 16,
},
});

export default LogBoxInspectorMessageHeader;
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ function LogBoxInspectorStackFrame(props: Props): React.Node {
onPress={onPress}
style={styles.frame}>
<Text
selectable={true}
id="logbox_stack_frame_text"
style={[styles.name, frame.collapse === true && styles.dim]}>
{frame.methodName}
</Text>
<Text
selectable={true}
ellipsizeMode="middle"
numberOfLines={1}
style={[styles.location, frame.collapse === true && styles.dim]}>
Expand Down
8 changes: 6 additions & 2 deletions packages/react-native/Libraries/LogBox/UI/LogBoxMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ function TappableLinks(props: {
);
}

return <Text style={props.style}>{fragments}</Text>;
return (
<Text selectable={true} style={props.style}>
{fragments}
</Text>
);
}

const cleanContent = (content: string) =>
Expand All @@ -107,7 +111,7 @@ function LogBoxMessage(props: Props): React.Node {
const {content, substitutions}: Message = props.message;

if (props.plaintext === true) {
return <Text>{cleanContent(content)}</Text>;
return <Text selectable={true}>{cleanContent(content)}</Text>;
}

const maxLength = props.maxLength != null ? props.maxLength : Infinity;
Expand Down
Loading