UNPKG

react-native-debug-toolkit

Version:

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

318 lines (303 loc) 7.8 kB
import React, { useState } from 'react' import { View, Text, StyleSheet, FlatList, TouchableOpacity, } from 'react-native' import TrackLogDetails from './TrackLogDetails' const SubViewTrackLogs = ({ logs = [] }) => { const [selectedLog, setSelectedLog] = useState(null) const getEventColor = (eventName) => { if (eventName?.includes('error')) return '#ff4444' if (eventName?.includes('click')) return '#4CAF50' if (eventName?.includes('view')) return '#2196F3' if (eventName?.includes('search')) return '#FF9800' return '#9C27B0' } const getTimeAgo = (timestamp) => { const now = new Date() const eventTime = new Date(timestamp) const diffMs = now - eventTime const diffSeconds = Math.floor(diffMs / 1000) const diffMinutes = Math.floor(diffSeconds / 60) const diffHours = Math.floor(diffMinutes / 60) if (diffSeconds < 60) { return `${diffSeconds}s ago` } else if (diffMinutes < 60) { return `${diffMinutes}m ago` } else if (diffHours < 24) { return `${diffHours}h ago` } else { const diffDays = Math.floor(diffHours / 24) return `${diffDays}d ago` } } const renderLogItem = ({ item }) => { const eventColor = getEventColor(item.eventName) return ( <TouchableOpacity style={styles.logItem} onPress={() => setSelectedLog(item)}> <View style={styles.logItemContainer}> <View style={[styles.eventIndicator, { backgroundColor: eventColor }]} /> <View style={styles.logContent}> <View style={styles.eventRow}> <Text style={[styles.eventName, { color: eventColor }]}> {item.eventName || 'Unknown Event'} </Text> {item.entityType && ( <Text style={styles.entityType}> {item.entityType} </Text> )} </View> {item.entityName && ( <Text style={styles.entityName} numberOfLines={1}> {item.entityName} </Text> )} {item.frontOperation && ( <Text style={styles.operation} numberOfLines={1}> Operation: {item.frontOperation} </Text> )} <View style={styles.logFooter}> <Text style={styles.time}> {item.timestamp ? getTimeAgo(item.timestamp) : 'Unknown time'} </Text> <View style={styles.additionalInfo}> {item.pageId && ( <Text style={styles.pageId} numberOfLines={1}> Page: {item.pageId} </Text> )} {item.position && ( <Text style={styles.position}> Pos: {item.position} </Text> )} </View> </View> </View> </View> </TouchableOpacity> ) } // If a log is selected, show the details view with a back button if (selectedLog) { return ( <View style={styles.container}> <View style={styles.detailsHeader}> <TouchableOpacity style={styles.backButton} onPress={() => setSelectedLog(null)}> <Text style={styles.backButtonText}>← Back</Text> </TouchableOpacity> <View style={styles.headerEventInfo}> <Text style={[ styles.headerEvent, { color: getEventColor(selectedLog.eventName) }, ]}> {selectedLog.eventName || 'Unknown Event'} </Text> {selectedLog.entityType && ( <Text style={styles.headerEntityType}> {selectedLog.entityType} </Text> )} </View> </View> <TrackLogDetails log={selectedLog} /> </View> ) } // Otherwise show the list view return ( <View style={styles.container}> {logs.length === 0 ? ( <View style={styles.emptyContainer}> <Text style={styles.emptyText}>No track events logged yet</Text> <Text style={styles.emptySubtext}> Track events will appear here as they occur during development </Text> </View> ) : ( <> <View style={styles.statsContainer}> <Text style={styles.statsText}> {logs.length} events logged </Text> </View> <FlatList data={[...logs].sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))} renderItem={renderLogItem} keyExtractor={(item, index) => `${item.timestamp}-${index}`} style={styles.list} showsVerticalScrollIndicator={true} /> </> )} </View> ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, list: { flex: 1, }, emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 40, }, emptyText: { textAlign: 'center', color: '#666', fontSize: 16, fontWeight: '500', marginBottom: 8, }, emptySubtext: { textAlign: 'center', color: '#999', fontSize: 14, }, statsContainer: { padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee', backgroundColor: '#f8f9fa', }, statsText: { fontSize: 12, color: '#666', fontWeight: '500', }, logItem: { borderBottomWidth: 1, borderBottomColor: '#eee', }, logItemContainer: { flexDirection: 'row', padding: 12, }, eventIndicator: { width: 4, borderRadius: 2, marginRight: 12, }, logContent: { flex: 1, }, eventRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 4, }, eventName: { fontSize: 15, fontWeight: 'bold', marginRight: 8, }, entityType: { fontSize: 11, backgroundColor: '#f0f0f0', color: '#666', paddingHorizontal: 6, paddingVertical: 2, borderRadius: 6, fontWeight: '500', }, entityName: { fontSize: 14, color: '#333', marginBottom: 4, fontWeight: '500', }, operation: { fontSize: 13, color: '#666', marginBottom: 6, fontStyle: 'italic', }, logFooter: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-end', }, time: { fontSize: 12, color: '#999', }, additionalInfo: { flexDirection: 'row', alignItems: 'center', gap: 8, }, pageId: { fontSize: 11, color: '#666', backgroundColor: '#f8f9fa', paddingHorizontal: 4, paddingVertical: 1, borderRadius: 3, maxWidth: 80, }, position: { fontSize: 11, color: '#666', backgroundColor: '#f8f9fa', paddingHorizontal: 4, paddingVertical: 1, borderRadius: 3, }, detailsHeader: { flexDirection: 'row', alignItems: 'center', padding: 15, borderBottomWidth: 1, borderBottomColor: '#eee', backgroundColor: '#f8f9fa', }, backButton: { paddingHorizontal: 10, paddingVertical: 5, borderRadius: 4, backgroundColor: '#eee', marginRight: 10, }, backButtonText: { color: '#333', fontWeight: '500', }, headerEventInfo: { flexDirection: 'row', alignItems: 'center', }, headerEvent: { fontSize: 16, fontWeight: 'bold', marginRight: 10, }, headerEntityType: { fontSize: 12, backgroundColor: '#f0f0f0', color: '#666', paddingHorizontal: 8, paddingVertical: 3, borderRadius: 8, fontWeight: '500', }, }) export default SubViewTrackLogs