import 'package:basic_intl/intl.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '../services/message_service.dart'; import '../utils/common_util.dart'; import 'large_audio_wave.dart'; class ChatFooter extends StatefulWidget { final VoidCallback? onClear; const ChatFooter({super.key, this.onClear}); @override State createState() => _ChatFooterState(); } class _ChatFooterState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, ); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { // 定义颜色常量 const Color buttonColor = Color(0xFF6F72F1); // 主题紫色(应用栏和按钮边框) return Container( color: Colors.transparent, child: Row( children: [ Padding( padding: const EdgeInsets.only(left: 16, bottom: 12), child: GestureDetector( onTap: widget.onClear, child: Image.asset( 'assets/images/delete.png',package: 'ai_chat_assistant', width: 24, height: 24, ), ), ), Expanded( child: Padding( key: const Key('startBtn'), padding: const EdgeInsets.only(bottom: 12, left: 16, right: 16), child: Consumer( builder: (context, messageService, child) { // 立即响应录音状态变化,无延迟启动动画 WidgetsBinding.instance.addPostFrameCallback((_) { if (messageService.isRecording) { if (!_animationController.isAnimating) { _animationController.repeat(); } } else { if (_animationController.isAnimating) { _animationController.stop(); } } }); return GestureDetector( onTap: () { HapticFeedback.heavyImpact(); messageService.abortReply(); }, onLongPress: () { HapticFeedback.mediumImpact(); // 立即启动动画,无延迟 _animationController.repeat(); Future.delayed(const Duration(milliseconds: 100), () { HapticFeedback.heavyImpact(); }); messageService.startVoiceInput(); }, onLongPressUp: () { HapticFeedback.lightImpact(); // 立即停止动画 _animationController.stop(); messageService.stopAndProcessVoiceInput(); }, child: LayoutBuilder( builder: (context, constraints) { final containerWidth = constraints.maxWidth; final waveWidth = containerWidth * 0.57; // 波形宽度为容器的57% return Container( height: 48, // 固定高度 48px alignment: Alignment.center, decoration: BoxDecoration( color: const Color(0x14FFFFFF), // 白色背景透明度8% borderRadius: BorderRadius.circular(8), // 圆角按钮 8px border: Border.all( color: buttonColor, // 边框颜色 #6F72F1 width: 0.5, // 边框粗细 0.5px ), ), child: messageService.isRecording ? AudioWaveLarge( animationController: _animationController, totalWidth: waveWidth, ) : Text( Intl.getCurrentLocale().startsWith('zh') ? '按住 说话' : 'Hold to Speak', style: TextStyle( color: CommonUtil.commonColor, fontSize: 18, fontWeight: FontWeight.bold), ), ); }, ), ); }, ), ), ), Padding( padding: const EdgeInsets.only(bottom: 12, right: 16), child: GestureDetector( onTap: () { }, child: Image.asset( 'assets/images/keyboard_mini.png',package: 'ai_chat_assistant', width: 24, height: 24, ), ), ), ], ), ); } }