import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/client_provider.dart'; import '../services/log_service.dart'; import 'dart:async'; class LogViewerScreen extends StatefulWidget { const LogViewerScreen({super.key}); @override State createState() => _LogViewerScreenState(); } class _LogViewerScreenState extends State { final LogService _logService = LogService(); final ScrollController _scrollController = ScrollController(); String _logs = ''; StreamSubscription? _logSubscription; StreamSubscription? _clientLogSubscription; bool _autoScroll = true; @override void initState() { super.initState(); _loadLogs(); _startMonitoring(); } Future _loadLogs() async { final logs = await _logService.getRecentLogs(); setState(() { _logs = logs; }); if (_autoScroll && _scrollController.hasClients) { _scrollToBottom(); } } void _startMonitoring() { // 监控日志文件 _logSubscription = _logService.logStream.listen((log) { setState(() { _logs += '\n$log'; }); if (_autoScroll && _scrollController.hasClients) { _scrollToBottom(); } }); // 监控客户端日志流 final clientProvider = Provider.of(context, listen: false); _clientLogSubscription = clientProvider.logStream.listen((log) { setState(() { _logs += '\n$log'; }); if (_autoScroll && _scrollController.hasClients) { _scrollToBottom(); } }); } void _scrollToBottom() { if (_scrollController.hasClients) { _scrollController.animateTo( _scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ); } } @override void dispose() { _logSubscription?.cancel(); _clientLogSubscription?.cancel(); _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('日志查看'), actions: [ IconButton( icon: Icon(_autoScroll ? Icons.arrow_downward : Icons.arrow_upward), onPressed: () { setState(() { _autoScroll = !_autoScroll; }); }, tooltip: _autoScroll ? '关闭自动滚动' : '开启自动滚动', ), IconButton( icon: const Icon(Icons.refresh), onPressed: _loadLogs, tooltip: '刷新日志', ), IconButton( icon: const Icon(Icons.clear), onPressed: () async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认清理'), content: const Text('确定要清理所有日志吗?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('确定'), ), ], ), ); if (confirmed == true) { await _logService.clearLogs(); _loadLogs(); } }, tooltip: '清理日志', ), ], ), body: Container( padding: const EdgeInsets.all(8.0), child: SingleChildScrollView( controller: _scrollController, child: SelectableText( _logs.isEmpty ? '暂无日志' : _logs, style: const TextStyle( fontFamily: 'monospace', fontSize: 12, ), ), ), ), ); } }