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;