UNPKG

react-native-debug-toolkit

Version:

A simple yet powerful debugging toolkit for React Native with a convenient floating UI for development

302 lines (278 loc) 7.23 kB
import React from 'react' import { View, Text, StyleSheet, Clipboard } from 'react-native' import { ScrollView, Pressable } from 'react-native' import JSONTree from 'react-native-json-tree' import { getNavigationActionColor } from '../utils/DebugConst' // Re-using the theme from ConsoleLogDetails for consistency const theme = { scheme: 'monokai', author: 'wimer hazenberg (http://www.monokai.nl)', base00: '#272822', base01: '#383830', base02: '#49483e', base03: '#75715e', base04: '#a59f85', base05: '#f8f8f2', base06: '#f5f4f1', base07: '#f9f8f5', base08: '#f92672', base09: '#fd971f', base0A: '#f4bf75', base0B: '#a6e22e', base0C: '#a1efe4', base0D: '#66d9ef', base0E: '#ae81ff', base0F: '#cc6633' }; const CopyButton = ({ text, style }) => { const [copied, setCopied] = React.useState(false) const handleCopy = async () => { await Clipboard.setString(text) setCopied(true) setTimeout(() => setCopied(false), 2000) } return ( <Pressable style={[styles.copyButton, style]} onPress={handleCopy}> <Text style={styles.copyButtonText}>{copied ? 'Copied!' : 'Copy'}</Text> </Pressable> ) } const CollapsibleSection = ({ title, children, initiallyExpanded = false }) => { const [expanded, setExpanded] = React.useState(initiallyExpanded) return ( <View style={styles.collapsibleSection}> <Pressable style={styles.sectionHeader} onPress={() => setExpanded(!expanded)}> <Text style={styles.sectionTitle}>{title}</Text> <Text style={styles.expandIcon}>{expanded ? '▼' : '▶'}</Text> </Pressable> {expanded && children} </View> ) } // Basic JSONValue renderer const JSONValue = ({ value }) => { if (value === null) { return <Text style={styles.jsonNull}>null</Text> } if (value === undefined) { return <Text style={styles.jsonNull}>undefined</Text> } if (typeof value === 'boolean') { return <Text style={styles.jsonBoolean}>{value.toString()}</Text> } if (typeof value === 'number') { return <Text style={styles.jsonNumber}>{value}</Text> } if (typeof value === 'string') { return ( <Text style={styles.jsonString} selectable={true}> "{value}" </Text> ) } if (typeof value === 'object') { return ( <JSONTree data={value} theme={theme} invertTheme={true} hideRoot={true} shouldExpandNode={(keyPath, nodeData, currentLevel) => currentLevel < 1} /> ) } return <Text style={styles.jsonOther}>{String(value)}</Text> } const NavigationLogDetails = ({ log }) => { if (!log) { return ( <View style={styles.errorContainer}> <Text style={styles.errorText}>Navigation log data is missing</Text> </View> ) } const { action, from, to, timestamp, startTime, duration, debugLog } = log const actionColor = getNavigationActionColor(action) // Format the log data for text display and copying const formatLogForCopy = () => { try { return `Navigation: ${action} From: ${JSON.stringify(from, null, 2)} To: ${JSON.stringify(to, null, 2)} Time: ${timestamp ? new Date(timestamp).toLocaleString() : 'Unknown'} Duration: ${duration || 'N/A'} ms`; } catch (e) { return 'Failed to format navigation log'; } }; return ( <ScrollView style={styles.container} contentContainerStyle={styles.contentContainer} showsVerticalScrollIndicator={true} scrollEventThrottle={16} keyboardShouldPersistTaps='handled'> <View style={styles.header}> <View style={styles.headerInfo}> <Text style={[styles.actionIndicator, { color: actionColor }]}> {action?.toUpperCase() || 'UNKNOWN'} </Text> <Text style={styles.timestamp}> {timestamp ? new Date(timestamp).toLocaleString() : 'Unknown time'} </Text> {duration && ( <Text style={styles.duration}> {`${duration} ms`} </Text> )} </View> <CopyButton text={formatLogForCopy()} /> </View> <CollapsibleSection title='From Route' initiallyExpanded={true}> <View style={styles.dataContentWrapper}> <View style={styles.dataContent}> <JSONValue value={from} /> </View> </View> </CollapsibleSection> <CollapsibleSection title='To Route' initiallyExpanded={true}> <View style={styles.dataContentWrapper}> <View style={styles.dataContent}> <JSONValue value={to} /> </View> </View> </CollapsibleSection> <CollapsibleSection title='Debug Log' initiallyExpanded={true}> <View style={styles.dataContentWrapper}> <View style={styles.dataContent}> <JSONValue value={debugLog} /> </View> </View> </CollapsibleSection> </ScrollView> ) } // Styles adapted from ConsoleLogDetails const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, contentContainer: { paddingBottom: 20, }, header: { flexDirection: 'row', padding: 15, borderBottomWidth: 1, borderBottomColor: '#eee', alignItems: 'center', justifyContent: 'space-between', }, headerInfo: { flexShrink: 1, marginRight: 10, }, actionIndicator: { fontSize: 14, fontWeight: 'bold', marginBottom: 4, }, timestamp: { fontSize: 13, color: '#666', marginBottom: 2, }, duration: { fontSize: 12, color: '#888', }, collapsibleSection: { marginBottom: 1, backgroundColor: '#fff', }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 15, backgroundColor: '#f5f5f5', }, sectionTitle: { fontSize: 15, fontWeight: 'bold', color: '#333', }, expandIcon: { fontSize: 14, color: '#666', }, content: { padding: 15, }, dataContentWrapper: { flex: 1, padding: 10, }, dataContent: { backgroundColor: '#f8f9fa', padding: 10, borderRadius: 4, borderWidth: 1, borderColor: '#e9ecef', }, errorContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, errorText: { color: '#ff4444', fontSize: 16, }, copyButton: { backgroundColor: '#e9ecef', paddingHorizontal: 10, paddingVertical: 5, borderRadius: 4, flexShrink: 0, }, copyButtonText: { fontSize: 12, color: '#666', }, // JSON Value Styles (reused from ConsoleLogDetails) jsonString: { color: '#CB772F', fontFamily: 'monospace', fontSize: 13, }, jsonNumber: { color: '#AE81FF', fontFamily: 'monospace', fontSize: 13, }, jsonBoolean: { color: '#66D9EF', fontWeight: 'bold', fontFamily: 'monospace', fontSize: 13, }, jsonNull: { color: '#F92672', fontStyle: 'italic', fontFamily: 'monospace', fontSize: 13, }, jsonOther: { color: '#75715e', fontFamily: 'monospace', fontSize: 13, }, }); export default NavigationLogDetails