131 lines
3.5 KiB
Dart
131 lines
3.5 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; // 是否显示未连接状态
|
|
final VoidCallback? onTap; // 点击回调
|
|
|
|
const TcpStatusIndicator({
|
|
super.key,
|
|
this.size = 12.0,
|
|
this.showDisconnected = false, // 默认不显示未连接状态
|
|
this.onTap, // 点击回调
|
|
});
|
|
|
|
@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: 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,
|
|
),
|
|
]
|
|
: [],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|