Files
flutterApp/lib/components/tcp_status_indicator.dart
2026-06-05 19:06:21 +08:00

124 lines
3.3 KiB
Dart

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; // 是否显示未连接状态
const TcpStatusIndicator({
super.key,
this.size = 12.0,
this.showDisconnected = false, // 默认不显示未连接状态
});
@override
State<TcpStatusIndicator> createState() => _TcpStatusIndicatorState();
}
class _TcpStatusIndicatorState extends State<TcpStatusIndicator>
with SingleTickerProviderStateMixin {
late TcpStatusCubit _tcpStatusCubit;
bool _hasActivity = false;
AnimationController? _controller;
Animation<double>? _animation;
@override
void initState() {
super.initState();
_tcpStatusCubit = GetIt.I<TcpStatusCubit>();
_controller = AnimationController(
duration: const Duration(milliseconds: 1500),
vsync: this,
);
_animation = Tween<double>(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: 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,
),
]
: [],
),
);
},
),
);
}
}