import React from 'react'; import { Box, Text } from 'ink'; import { colors, borders } from '../theme/index.js'; import { formatTimestamp } from '../utils/format.js'; /** * Log entry structure for torrent activity */ export interface LogEntry { /** Timestamp when the log entry was created */ timestamp: Date; /** Log level for color coding */ level: 'info' | 'warn' | 'error'; /** Log message text */ message: string; } export interface LogViewProps { /** Array of log entries to display */ logs: LogEntry[]; /** Maximum number of entries to show (default: 20) */ maxEntries?: number; } /** * Log level display configuration */ const LEVEL_DISPLAY: Record< LogEntry['level'], { color: string; prefix: string } > = { info: { color: colors.primary, prefix: 'INF' }, warn: { color: colors.warning, prefix: 'WRN' }, error: { color: colors.error, prefix: 'ERR' }, }; /** * Column widths for log display */ const COLUMN_WIDTHS = { timestamp: 10, level: 5, message: 60, } as const; /** * Header row for log view */ const LogViewHeader: React.FC = () => { return ( Time Level Message {borders.horizontal.repeat( COLUMN_WIDTHS.timestamp + COLUMN_WIDTHS.level + COLUMN_WIDTHS.message )} ); }; /** * Single log entry row component */ const LogEntryRow: React.FC<{ entry: LogEntry }> = ({ entry }) => { const levelInfo = LEVEL_DISPLAY[entry.level]; const timestamp = formatTimestamp(entry.timestamp); return ( {timestamp} {levelInfo.prefix} {entry.message} ); }; /** * Empty state when no logs */ const EmptyState: React.FC = () => { return ( No activity recorded ); }; /** * LogView component for displaying torrent activity log * * Shows a scrollable list of log entries with timestamps, * log levels, and messages. Entries are color-coded by level. * * @example * const logs = [ * { timestamp: new Date(), level: 'info', message: 'Torrent started' }, * { timestamp: new Date(), level: 'warn', message: 'Tracker timeout' }, * ]; * * * // Output: * // Time Level Message * // ───────────────────────────────────────────────────────────────────── * // 14:32:15 INF Torrent started * // 14:32:45 WRN Tracker timeout */ export const LogView: React.FC = ({ logs, maxEntries = 20 }) => { if (logs.length === 0) { return ; } // Show most recent entries first, limited by maxEntries const displayLogs = logs.slice(-maxEntries).reverse(); return ( {displayLogs.map((entry, index) => ( ))} {logs.length > maxEntries && ( Showing {maxEntries} of {logs.length} entries )} ); }; export default LogView;