import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:maibu_satabot_v2/core/network/tcp/tcp_status_cubit.dart'; class TcpStatusIndicator extends StatefulWidget { final double size; final bool showDisconnected; // 是否显示未连接状态 final VoidCallback? onTap; // 点击回调 const TcpStatusIndicator({ super.key, this.size = 12.0, this.showDisconnected = false, // 默认不显示未连接状态 this.onTap, // 点击回调 }); @override State createState() => _TcpStatusIndicatorState(); } class _TcpStatusIndicatorState extends State with SingleTickerProviderStateMixin { late TcpStatusCubit _tcpStatusCubit; bool _hasActivity = false; AnimationController? _controller; Animation? _animation; @override void initState() { super.initState(); _tcpStatusCubit = GetIt.I(); _controller = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); _animation = Tween( begin: 0.6, end: 1.0, ).animate(CurvedAnimation(parent: _controller!, curve: Curves.easeInOut)); _controller!.repeat(reverse: true); _tcpStatusCubit.stream.listen((state) { if (state.status != TcpConnectionStatus.disconnected) { _hasActivity = true; } if (mounted) { setState(() {}); } }); } @override void dispose() { _controller?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final state = _tcpStatusCubit.state; if (!widget.showDisconnected && !_hasActivity && state.status == TcpConnectionStatus.disconnected) { return const SizedBox.shrink(); } Color color; String tooltip; bool shouldAnimate; switch (state.status) { case TcpConnectionStatus.connected: color = Colors.green; tooltip = 'TCP已连接'; shouldAnimate = false; break; case TcpConnectionStatus.connecting: color = Colors.yellow; tooltip = 'TCP连接中...'; shouldAnimate = true; break; case TcpConnectionStatus.error: color = Colors.red; tooltip = state.errorMessage ?? 'TCP连接错误'; shouldAnimate = false; break; case TcpConnectionStatus.disconnected: default: color = Colors.grey; tooltip = 'TCP未连接'; shouldAnimate = false; break; } return Tooltip( message: tooltip, child: InkWell( onTap: widget.onTap, borderRadius: BorderRadius.circular(widget.size / 2), child: AnimatedBuilder( animation: _animation!, builder: (context, child) { final opacity = shouldAnimate ? _animation!.value : 1.0; return Container( width: widget.size, height: widget.size, decoration: BoxDecoration( color: color.withOpacity(opacity), shape: BoxShape.circle, boxShadow: state.status == TcpConnectionStatus.connected ? [ BoxShadow( color: Colors.green.withOpacity(0.5 * opacity), blurRadius: 6 * opacity, spreadRadius: 2 * opacity, ), ] : [], ), ); }, ), ), ); } }