import 'dart:async'; import 'package:cc_ui_kit/cc_ui_kit.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:vibration/vibration.dart'; import 'package:maibu_satabot_v2/core/localization/app_localizations.dart'; import '../bloc/remote_control_cubit.dart'; class LeftJoystickArea extends StatefulWidget { final bool isLocked; final double width; const LeftJoystickArea({ Key? key, required this.isLocked, required this.width, }) : super(key: key); @override State createState() => _LeftJoystickAreaState(); } class _LeftJoystickAreaState extends State { int _lastSentY = 0; bool _isTouching = false; bool _hasShownNoPushDialog = false; // 防止重复弹窗 /// 检查是否可以控制,不能则弹出提示 bool _checkCanControl(BuildContext context) { final cubit = context.read(); if (!cubit.isStatusPushActive()) { if (!_hasShownNoPushDialog) { _hasShownNoPushDialog = true; _showNoStatusPushDialog(context); } return false; } _hasShownNoPushDialog = false; return true; } /// 显示暂未收到推送的提示弹窗(小圆角) void _showNoStatusPushDialog(BuildContext context) { showDialog( context: context, builder: (ctx) => Dialog( backgroundColor: Colors.transparent, child: Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), decoration: BoxDecoration( color: const Color(0xE5333333), borderRadius: BorderRadius.circular(12), ), child: Text( '暂未收到该机器的推送,不能控制', style: const TextStyle( color: Colors.white, fontSize: 14, ), ), ), ), ); // 1.5秒后自动关闭 Future.delayed(const Duration(milliseconds: 1500), () { Navigator.of(context).pop(); }); } @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ IgnorePointer( ignoring: widget.isLocked, child: AnimatedOpacity( duration: const Duration(milliseconds: 300), opacity: widget.isLocked ? 0.3 : 1.0, child: CCJoystick( radius: widget.width, axisHint: AxisHint.forwardBackward, onValueChanged: (value) { if (!_checkCanControl(context)) return; // 标记:正在触摸 _isTouching = true; int currentY = value.y.toInt(); if (currentY != _lastSentY) { _lastSentY = currentY; debugPrint('左摇杆的数据- x: 0, y: $currentY'); context.read().updateOriginY(currentY); } }, onPress: () { if (!_checkCanControl(context)) return; _isTouching = true; debugPrint('onPress'); _triggerVibration(); }, onPanEnd: () async { _hasShownNoPushDialog = false; // 松手重置,下次触摸重新检查 // 🔥 松手 100% 归零 debugPrint('onPanEnd'); await _stopJoystick(); }, ), ), ), const SizedBox(height: 18), Text( AppLocalizations.of(context).translate('remote_control.forward_backward'), style: TextStyle( color: Colors.white.withOpacity(0.5), fontSize: 12, fontWeight: FontWeight.w500, ), ), ], ); } // 统一停车方法(万能保险) Future _stopJoystick() async { _isTouching = false; _lastSentY = 0; debugPrint('✅ 摇杆已停止 -> 强制 X=0, Y=0 停车'); // 🔥 使用安全方法,一次性清零双轴,确保只发送 (X=0, Y=0) await context.read().stopAllMovement(); } void _triggerVibration() { Vibration.hasVibrator().then((has) { if (has ?? false) Vibration.vibrate(duration: 12); }); } }