import 'dart:io' show Platform; import 'package:ansicolor/ansicolor.dart'; import 'package:bloc/bloc.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_translate/flutter_translate.dart'; import 'package:intl/intl.dart'; import 'package:loggy/loggy.dart'; import 'package:veilid_support/veilid_support.dart'; import '../veilid_processor/views/developer.dart'; import 'state_logger.dart'; String wrapWithLogColor(LogLevel? level, String text) { // XXX: https://github.com/flutter/flutter/issues/64491 if (!kIsWeb && Platform.isIOS) { return text; } if (level == null) { return text; } final pen = AnsiPen(); ansiColorDisabled = false; switch (level) { case LogLevel.error: pen ..reset() ..red(bold: true); return pen(text); case LogLevel.warning: pen ..reset() ..yellow(bold: true); return pen(text); case LogLevel.info: pen ..reset() ..white(bold: true); return pen(text); case LogLevel.debug: pen ..reset() ..green(bold: true); return pen(text); case traceLevel: pen ..reset() ..blue(bold: true); return pen(text); } return text; } final DateFormat _dateFormatter = DateFormat('HH:mm:ss.SSS'); extension PrettyPrintLogRecord on LogRecord { String pretty() { final tm = _dateFormatter.format(time.toLocal()); final lev = logLevelEmoji(level); final lstr = wrapWithLogColor(level, tm); return '$lstr $lev $message'; } } List logLevels = [ LogLevel.error, LogLevel.warning, LogLevel.info, LogLevel.debug, traceLevel, ]; String logLevelName(LogLevel logLevel) { switch (logLevel) { case traceLevel: return translate('log.trace'); case LogLevel.debug: return translate('log.debug'); case LogLevel.info: return translate('log.info'); case LogLevel.warning: return translate('log.warning'); case LogLevel.error: return translate('log.error'); } return '???'; } String logLevelEmoji(LogLevel logLevel) { switch (logLevel) { case traceLevel: return '👾'; case LogLevel.debug: return '🐛'; case LogLevel.info: return '💡'; case LogLevel.warning: return '🍋'; case LogLevel.error: return '🛑'; } return '❓'; } class CallbackPrinter extends LoggyPrinter { CallbackPrinter() : super(); void Function(LogRecord)? callback; @override void onLog(LogRecord record) { final out = record.pretty(); debugPrint(out); globalDebugTerminal.write('$out\n'.replaceAll('\n', '\r\n')); callback?.call(record); } void setCallback(void Function(LogRecord)? cb) { callback = cb; } } CallbackPrinter globalTerminalPrinter = CallbackPrinter(); LogOptions getLogOptions(LogLevel? level) => LogOptions( level ?? LogLevel.all, stackTraceLevel: LogLevel.error, ); class RootLoggy implements LoggyType { @override Loggy get loggy => Loggy(''); } Loggy get log => Loggy('veilidchat'); void initLoggy() { Loggy.initLoggy( logPrinter: globalTerminalPrinter, logOptions: getLogOptions(null), ); // ignore: do_not_use_environment const isTrace = String.fromEnvironment('LOG_TRACE') != ''; LogLevel logLevel; if (isTrace) { logLevel = traceLevel; } else { logLevel = kDebugMode ? LogLevel.debug : LogLevel.info; } Loggy('').level = getLogOptions(logLevel); // Create state logger Bloc.observer = const StateLogger(); }