Spaces:
Paused
Paused
| import 'dart:developer' as developer; | |
| import 'package:flutter/foundation.dart'; | |
| /// ANSI color codes for terminal output | |
| class AnsiColors { | |
| static const String reset = '\x1B[0m'; | |
| static const String bold = '\x1B[1m'; | |
| static const String dim = '\x1B[2m'; | |
| static const String italic = '\x1B[3m'; | |
| static const String underline = '\x1B[4m'; | |
| // Foreground colors | |
| static const String black = '\x1B[30m'; | |
| static const String red = '\x1B[31m'; | |
| static const String green = '\x1B[32m'; | |
| static const String yellow = '\x1B[33m'; | |
| static const String blue = '\x1B[34m'; | |
| static const String magenta = '\x1B[35m'; | |
| static const String cyan = '\x1B[36m'; | |
| static const String white = '\x1B[37m'; | |
| // Bright foreground colors | |
| static const String brightBlack = '\x1B[90m'; | |
| static const String brightRed = '\x1B[91m'; | |
| static const String brightGreen = '\x1B[92m'; | |
| static const String brightYellow = '\x1B[93m'; | |
| static const String brightBlue = '\x1B[94m'; | |
| static const String brightMagenta = '\x1B[95m'; | |
| static const String brightCyan = '\x1B[96m'; | |
| static const String brightWhite = '\x1B[97m'; | |
| // Background colors | |
| static const String bgBlack = '\x1B[40m'; | |
| static const String bgRed = '\x1B[41m'; | |
| static const String bgGreen = '\x1B[42m'; | |
| static const String bgYellow = '\x1B[43m'; | |
| static const String bgBlue = '\x1B[44m'; | |
| static const String bgMagenta = '\x1B[45m'; | |
| static const String bgCyan = '\x1B[46m'; | |
| static const String bgWhite = '\x1B[47m'; | |
| } | |
| /// Log levels with associated colors and emojis | |
| enum LogLevel { | |
| debug(AnsiColors.brightBlack, 'π', 'DEBUG'), | |
| info(AnsiColors.brightCyan, 'π‘', 'INFO'), | |
| warning(AnsiColors.brightYellow, 'β οΈ', 'WARN'), | |
| error(AnsiColors.brightRed, 'β', 'ERROR'), | |
| success(AnsiColors.brightGreen, 'β ', 'SUCCESS'), | |
| network(AnsiColors.brightMagenta, 'π', 'NET'), | |
| websocket(AnsiColors.cyan, 'π', 'WS'), | |
| video(AnsiColors.brightBlue, 'π¬', 'VIDEO'), | |
| chat(AnsiColors.green, 'π¬', 'CHAT'), | |
| search(AnsiColors.yellow, 'π', 'SEARCH'); | |
| const LogLevel(this.color, this.emoji, this.label); | |
| final String color; | |
| final String emoji; | |
| final String label; | |
| } | |
| /// Beautiful colored logger for Flutter applications | |
| class ColoredLogger { | |
| final String _className; | |
| ColoredLogger(this._className); | |
| /// Create a logger for a specific class | |
| static ColoredLogger get(String className) { | |
| return ColoredLogger(className); | |
| } | |
| /// Debug level logging - for detailed debugging info | |
| void debug(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.debug, message, data); | |
| } | |
| /// Info level logging - for general information | |
| void info(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.info, message, data); | |
| } | |
| /// Warning level logging - for potential issues | |
| void warning(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.warning, message, data); | |
| } | |
| /// Error level logging - for errors and exceptions | |
| void error(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.error, message, data); | |
| } | |
| /// Success level logging - for successful operations | |
| void success(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.success, message, data); | |
| } | |
| /// Network level logging - for network operations | |
| void network(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.network, message, data); | |
| } | |
| /// WebSocket level logging - for WebSocket operations | |
| void websocket(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.websocket, message, data); | |
| } | |
| /// Video level logging - for video generation operations | |
| void video(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.video, message, data); | |
| } | |
| /// Chat level logging - for chat operations | |
| void chat(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.chat, message, data); | |
| } | |
| /// Search level logging - for search operations | |
| void search(String message, [Map<String, dynamic>? data]) { | |
| _log(LogLevel.search, message, data); | |
| } | |
| void _log(LogLevel level, String message, Map<String, dynamic>? data) { | |
| if (!kDebugMode) return; // Only log in debug mode | |
| final timestamp = DateTime.now(); | |
| final timeStr = '${timestamp.hour.toString().padLeft(2, '0')}:' | |
| '${timestamp.minute.toString().padLeft(2, '0')}:' | |
| '${timestamp.second.toString().padLeft(2, '0')}.' | |
| '${timestamp.millisecond.toString().padLeft(3, '0')}'; | |
| // Format the main log message with colors | |
| final coloredMessage = _colorizeMessage(message); | |
| // Build the log line | |
| final logLine = StringBuffer(); | |
| // Timestamp (dim) | |
| logLine.write('${AnsiColors.dim}$timeStr${AnsiColors.reset} '); | |
| // Level with color and emoji | |
| logLine.write('${level.color}${level.emoji} ${level.label.padRight(7)}${AnsiColors.reset} '); | |
| // Class name (bright black) | |
| logLine.write('${AnsiColors.brightBlack}[$_className]${AnsiColors.reset} '); | |
| // Message | |
| logLine.write(coloredMessage); | |
| // Add data if provided | |
| if (data != null && data.isNotEmpty) { | |
| logLine.write(' ${AnsiColors.dim}${_formatData(data)}${AnsiColors.reset}'); | |
| } | |
| // Use developer.log for better IDE integration | |
| developer.log( | |
| logLine.toString(), | |
| name: _className, | |
| level: _getLevelValue(level), | |
| ); | |
| } | |
| String _colorizeMessage(String message) { | |
| String result = message; | |
| // Highlight request IDs in brackets | |
| result = result.replaceAllMapped( | |
| RegExp(r'\[([a-zA-Z0-9-]+)\]'), | |
| (match) => '${AnsiColors.brightGreen}[${match.group(1)}]${AnsiColors.reset}', | |
| ); | |
| // Highlight user IDs | |
| result = result.replaceAllMapped( | |
| RegExp(r'\buser ([a-zA-Z0-9-]+)'), | |
| (match) => 'user ${AnsiColors.brightBlue}${match.group(1)}${AnsiColors.reset}', | |
| ); | |
| // Highlight actions | |
| result = result.replaceAllMapped( | |
| RegExp(r'\b(generate_video|search|simulate|join_chat|leave_chat|chat_message|connect|disconnect)\b'), | |
| (match) => '${AnsiColors.brightYellow}${match.group(1)}${AnsiColors.reset}', | |
| ); | |
| // Highlight status keywords | |
| result = result.replaceAllMapped( | |
| RegExp(r'\b(success|successful|completed|connected|ready|ok)\b', caseSensitive: false), | |
| (match) => '${AnsiColors.brightGreen}${match.group(1)}${AnsiColors.reset}', | |
| ); | |
| result = result.replaceAllMapped( | |
| RegExp(r'\b(error|failed|timeout|exception|crash)\b', caseSensitive: false), | |
| (match) => '${AnsiColors.brightRed}${match.group(1)}${AnsiColors.reset}', | |
| ); | |
| result = result.replaceAllMapped( | |
| RegExp(r'\b(warning|retry|reconnect|fallback)\b', caseSensitive: false), | |
| (match) => '${AnsiColors.brightYellow}${match.group(1)}${AnsiColors.reset}', | |
| ); | |
| // Highlight numbers with units | |
| result = result.replaceAllMapped( | |
| RegExp(r'\b(\d+\.?\d*)(ms|s|MB|KB|bytes|chars|fps)?\b'), | |
| (match) => '${AnsiColors.brightMagenta}${match.group(1)}${AnsiColors.cyan}${match.group(2) ?? ''}${AnsiColors.reset}', | |
| ); | |
| // Highlight URLs | |
| result = result.replaceAllMapped( | |
| RegExp(r'https?://[^\s]+'), | |
| (match) => '${AnsiColors.underline}${AnsiColors.brightCyan}${match.group(0)}${AnsiColors.reset}', | |
| ); | |
| // Highlight JSON-like structures | |
| result = result.replaceAllMapped( | |
| RegExp(r'\{[^}]*\}'), | |
| (match) => '${AnsiColors.dim}${match.group(0)}${AnsiColors.reset}', | |
| ); | |
| // Highlight strings in quotes | |
| result = result.replaceAllMapped( | |
| RegExp(r'"([^"]*)"'), | |
| (match) => '"${AnsiColors.green}${match.group(1)}${AnsiColors.reset}"', | |
| ); | |
| return result; | |
| } | |
| String _formatData(Map<String, dynamic> data) { | |
| final entries = data.entries.map((e) { | |
| final key = e.key; | |
| final value = e.value.toString(); | |
| return '${AnsiColors.cyan}$key${AnsiColors.reset}=${AnsiColors.brightWhite}$value${AnsiColors.reset}'; | |
| }).join(' '); | |
| return '{$entries}'; | |
| } | |
| int _getLevelValue(LogLevel level) { | |
| switch (level) { | |
| case LogLevel.debug: | |
| return 500; | |
| case LogLevel.info: | |
| return 800; | |
| case LogLevel.warning: | |
| return 900; | |
| case LogLevel.error: | |
| return 1000; | |
| case LogLevel.success: | |
| return 800; | |
| case LogLevel.network: | |
| return 700; | |
| case LogLevel.websocket: | |
| return 700; | |
| case LogLevel.video: | |
| return 700; | |
| case LogLevel.chat: | |
| return 700; | |
| case LogLevel.search: | |
| return 700; | |
| } | |
| } | |
| } | |
| /// Extension methods for easy logging | |
| extension ColoredLogging on Object { | |
| ColoredLogger get log => ColoredLogger.get(runtimeType.toString()); | |
| } | |
| /// Global logger instance for quick access | |
| final appLog = ColoredLogger.get('App'); |