import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; /// Widget that displays detailed error information for debugging class ErrorDisplay extends StatelessWidget { final String title; final String error; final String? stackTrace; final VoidCallback? onRetry; const ErrorDisplay({ super.key, this.title = 'Произошла ошибка', required this.error, this.stackTrace, this.onRetry, }); @override Widget build(BuildContext context) { return Center( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Error icon and title Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.error_outline, size: 48, color: Colors.red.shade400, ), ], ), const SizedBox(height: 16), // Title Text( title, style: Theme.of(context).textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: Colors.red.shade700, ), textAlign: TextAlign.center, ), const SizedBox(height: 24), // Error message card Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.red.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.red.shade200), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.info_outline, size: 20, color: Colors.red.shade700), const SizedBox(width: 8), Text( 'Сообщение об ошибке:', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.red.shade700, ), ), ], ), const SizedBox(height: 8), SelectableText( error, style: const TextStyle( fontFamily: 'monospace', fontSize: 13, ), ), const SizedBox(height: 12), Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: () { Clipboard.setData(ClipboardData(text: error)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Ошибка скопирована в буфер обмена'), duration: Duration(seconds: 2), ), ); }, icon: const Icon(Icons.copy, size: 18), label: const Text('Копировать ошибку'), style: OutlinedButton.styleFrom( foregroundColor: Colors.red.shade700, side: BorderSide(color: Colors.red.shade300), ), ), ), ], ), ], ), ), // Stack trace (if available) if (stackTrace != null && stackTrace!.isNotEmpty) ...[ const SizedBox(height: 16), ExpansionTile( title: Row( children: [ Icon(Icons.bug_report, size: 20, color: Colors.orange.shade700), const SizedBox(width: 8), Text( 'Stack Trace (для разработчиков)', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.orange.shade700, ), ), ], ), backgroundColor: Colors.orange.shade50, collapsedBackgroundColor: Colors.orange.shade50, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide(color: Colors.orange.shade200), ), collapsedShape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide(color: Colors.orange.shade200), ), children: [ Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey.shade900, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SelectableText( stackTrace!, style: const TextStyle( fontFamily: 'monospace', fontSize: 11, color: Colors.greenAccent, ), ), const SizedBox(height: 12), OutlinedButton.icon( onPressed: () { Clipboard.setData(ClipboardData(text: stackTrace!)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Stack trace скопирован в буфер обмена'), duration: Duration(seconds: 2), ), ); }, icon: const Icon(Icons.copy, size: 18), label: const Text('Копировать stack trace'), style: OutlinedButton.styleFrom( foregroundColor: Colors.greenAccent, side: const BorderSide(color: Colors.greenAccent), ), ), ], ), ), ], ), ], // Retry button if (onRetry != null) ...[ const SizedBox(height: 24), Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: onRetry, icon: const Icon(Icons.refresh), label: const Text('Попробовать снова'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), backgroundColor: Theme.of(context).primaryColor, foregroundColor: Colors.white, ), ), ), ], ), ], // Debug tips const SizedBox(height: 24), Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.blue.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.blue.shade200), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.lightbulb_outline, size: 20, color: Colors.blue.shade700), const SizedBox(width: 8), Text( 'Советы по отладке:', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.blue.shade700, ), ), ], ), const SizedBox(height: 8), Text( '• Скопируйте ошибку и отправьте разработчику\n' '• Проверьте соединение с интернетом\n' '• Проверьте логи Flutter в консоли\n' '• Попробуйте перезапустить приложение', style: TextStyle( fontSize: 12, color: Colors.blue.shade900, height: 1.5, ), ), ], ), ), ], ), ), ); } }